#!/usr/bin/env python

# Copyright (C) 2007-2014 by Clement Lefebvre <root@linuxmint.com>
# Copyright (C) 2015 Martin Wimpress <code@ubuntu-mate.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.

import errno
import gettext
import getpass
import gi
import glob
import os
import shutil
import subprocess
import string
import time

from configobj import ConfigObj
from gi.repository import Gdk, GdkPixbuf, Gio, GObject, Gtk, Notify

__VERSION__="3.5.2"

# i18n
gettext.install("mate-tweak", "/usr/share/locale")

class SidePage:
    def __init__(self, notebook_index, name, icon):
        self.notebook_index = notebook_index
        self.name = name
        self.icon = icon

class MateTweak:

    def set_string(self, schema, key, value):
        settings = Gio.Settings.new(schema)
        try:
            settings.set_string(key, value)
        except:
            print('Unable set ' + key + ' with ' + value + ' in ' + schema)
            pass

    def get_string(self, schema, key):
        settings = Gio.Settings.new(schema)
        return settings.get_string(key)

    def set_bool(self, schema, key, value):
        settings = Gio.Settings.new(schema)
        settings.set_boolean(key, value.get_active())

        # If Maximus is being tweaked, replace it to make the settings effective.
        if schema == "org.mate.maximus" and (key == "undecorate" or key == "no-maximize"):
            devnull = open(os.devnull, 'wb')
            subprocess.Popen(['mate-maximus', '--replace'], stdout=devnull, stderr=devnull)

            # When changing undecorate state replace the window manager
            # to ensure there are no rendering or strut issues.
            if key == 'undecorate':
                replace_windowmanager(self.get_current_wm(), false)
            devnull.close()

        # If panel features are being changed replace the panel layout.
        if schema == "org.mate.panel" and (key == "undecorate" or key == "no-maximize"):
            devnull = open(os.devnull, 'wb')
            subprocess.Popen(['mate-maximus', '--replace'], stdout=devnull, stderr=devnull)

            # When changing undecorate state replace the window manager
            # to ensure there are no rendering or strut issues.
            if key == 'undecorate':
                replace_windowmanager(self.get_current_wm(), false)
            devnull.close()

    def get_bool(self, schema, key):
        settings = Gio.Settings.new(schema)
        return settings.get_boolean(key)

    def init_checkbox(self, schema, key, name):
        source = Gio.SettingsSchemaSource.get_default()
        if source.lookup(schema, True) != None:
            widget = self.builder.get_object(name)
            value = self.get_bool(schema, key)
            widget.set_active(value)
            widget.connect("clicked", lambda x: self.set_bool(schema, key, x))

    def init_combobox(self, schema, key, name):
        source = Gio.SettingsSchemaSource.get_default()
        if source.lookup(schema, True) != None:
            widget = self.builder.get_object(name)
            conf = self.get_string(schema, key)
            index = 0
            for row in widget.get_model():
                if(conf == row[1]):
                    widget.set_active(index)
                    break
                index = index +1
            widget.connect("changed", lambda x: self.combo_fallback(schema, key, x))

    def update_combobox(self, schema, key, name):
        source = Gio.SettingsSchemaSource.get_default()
        if source.lookup(schema, True) != None:
            widget = self.builder.get_object(name)
            conf = self.get_string(schema, key)
            index = 0
            for row in widget.get_model():
                if(conf == row[1]):
                    widget.set_active(index)
                    break
                index = index +1

    def find_on_path(self, command):
        """Is command on the executable search path?"""
        if 'PATH' not in os.environ:
            return False
        path = os.environ['PATH']
        for element in path.split(os.pathsep):
            if not element:
                continue
            filename = os.path.join(element, command)
            if os.path.isfile(filename) and os.access(filename, os.X_OK):
                return True
        return False

    def mkdir_p(self, path):
        try:
            os.makedirs(path)
        except OSError as exc: # Python >2.5
            if exc.errno == errno.EEXIST and os.path.isdir(path):
                pass
            else:
                raise

    def get_current_wm(self):
        process = subprocess.Popen(['wmctrl', '-m'], stdout=subprocess.PIPE)
        out, err = process.communicate()
        current_wm = out.decode('utf-8')

        if ('Marco' in current_wm):
            wm = 'marco'
        elif ('Metacity' in current_wm):
            wm = 'metacity'
        elif ('Mutter' in current_wm):
            wm = 'mutter'
        elif ('Compiz' in current_wm):
            wm = 'compiz'
        else:
            wm = 'unknown'

        return wm

    def update_cursor_theme(self, theme):
        self.mkdir_p(os.path.expanduser('~/.icons/default/'))
        config = ConfigObj()
        config.filename = os.path.expanduser('~/.icons/default/index.theme')
        config['icon theme'] = {}
        config['icon theme']['Inherits'] = theme
        config.write()

    def replace_windowmanager(self, wm, notify):
        # Use this in python < 3.3. Python >= 3.3 has subprocess.DEVNULL
        devnull = open(os.devnull, 'wb')

        if wm == 'compiz' or wm == 'mutter':
            # Make sure Metacity is uses the same themes as Marco. This
            # ensures gtk-window-decorator does not incorrectly change
            # themes when switching from Marco to Compiz.
            mate_theme = self.get_string('org.mate.interface', 'gtk-theme')
            mate_cursor_theme = self.get_string('org.mate.peripherals-mouse', 'cursor-theme')

            schemasource = Gio.SettingsSchemaSource.get_default()
            gnome_desktop_schema = schemasource.lookup('org.gnome.desktop', False)
            if gnome_desktop_schema:
                self.set_string('org.gnome.desktop.wm.preferences', 'theme', mate_theme)
                self.set_string('org.gnome.desktop.interface', 'cursor-theme', mate_cursor_theme)

            self.update_cursor_theme(mate_cursor_theme)

            # metacity >= 3.16
            # The schema may not be installed
            meta_316_schema = schemasource.lookup('org.gnome.metacity', False)
            if meta_316_schema:
                self.set_string('org.gnome.metacity', 'theme', mate_theme)

            # mate-panel needs to be replaced when switching to Compiz/Mutter
            # to avoid rendering screw ups and strut issues.
            subprocess.call(['killall', 'mate-panel'], stdout=devnull, stderr=devnull)
            if wm == 'compiz':
                subprocess.Popen([wm, '--replace', 'ccp'], stdout=devnull, stderr=devnull)
            else:
                subprocess.Popen([wm, '--replace'], stdout=devnull, stderr=devnull)

            # Just give the window manager a second
            time.sleep(1)

            subprocess.Popen(['mate-panel', '--replace'], stdout=devnull, stderr=devnull)
        else:
            # If switching away from Compiz, attempt to kill gtk-window-decorator.
            #subprocess.call(['killall', 'mate-panel'], stdout=devnull, stderr=devnull)
            subprocess.call(['killall', 'gtk-window-decorator'], stdout=devnull, stderr=devnull)
            subprocess.Popen([wm, '--replace'], stdout=devnull, stderr=devnull)
            #subprocess.Popen(['mate-panel', '--replace'], stdout=devnull, stderr=devnull)
        devnull.close()

        if notify:
            Notify.init(_('Window Manager Replaced'))
            replace_windowmanager_notify=Notify.Notification.new (_('Window Manager Replaced'),_('Your window manager has been replaced with ' + wm),'dialog-information')
            replace_windowmanager_notify.show()

    def enable_dock(self, dock):
        self.mkdir_p(os.path.expanduser('~/.config/autostart/'))
        shutil.copy2('/usr/share/applications/' + dock + '.desktop', os.path.expanduser('~/.config/autostart/'))

        devnull = open(os.devnull, 'wb')
        # Docks require compositing
        current_wm = self.get_current_wm()
        if current_wm == 'marco':
            settings = Gio.Settings.new('org.mate.Marco.general')
            settings.set_boolean('compositing-manager', True)
            subprocess.Popen(['marco', '--replace'], stdout=devnull, stderr=devnull)
        elif current_wm == 'metacity':
            settings = Gio.Settings.new('org.gnome.metacity')
            settings.set_boolean('compositing-manager', True)
            subprocess.Popen(['metacity', '--replace'], stdout=devnull, stderr=devnull)

        subprocess.Popen([dock], stdout=devnull, stderr=devnull)
        devnull.close()

    def disable_dock(self, dock):
        if os.path.exists(os.path.expanduser('~/.config/autostart/') + dock + '.desktop'):
            os.remove(os.path.expanduser('~/.config/autostart/') + dock + '.desktop')
        devnull = open(os.devnull, 'wb')
        subprocess.call(['killall', dock], stdout=devnull, stderr=devnull)
        devnull.close()

    def enable_mate_volume_applet(self):
        devnull = open(os.devnull, 'wb')
        subprocess.Popen(['mate-volume-control-applet'], stdout=devnull, stderr=devnull)
        devnull.close()

        # If the system autostart is missing create a user autostart.
        if not os.path.exists('/etc/xdg/autostart/mate-volume-control-applet.desktop'):
            self.mkdir_p(os.path.expanduser('~/.config/autostart/'))
            shutil.copy2('/usr/share/mate-tweak/mate-volume-control-applet.desktop', os.path.expanduser('~/.config/autostart/'))

    def disable_mate_volume_applet(self):
        devnull = open(os.devnull, 'wb')
        subprocess.call(['killall', 'mate-volume-control-applet'], stdout=devnull, stderr=devnull)

        # If a system or user autostart exists, remove it.
        if os.path.exists(os.path.expanduser('~/.config/autostart/') + 'mate-volume-control-applet.desktop'):
            os.remove(os.path.expanduser('~/.config/autostart/') + 'mate-volume-control-applet.desktop')
        if os.path.exists('/etc/xdg/autostart/mate-volume-control-applet.desktop'):
            subprocess.call(['pkexec', '/usr/lib/mate-tweak/disable-mate-volume-applet'], stdout=devnull, stderr=devnull)
        devnull.close()

    def replace_panel_layout(self, panel_layout):
        # If the selected panel layout has MATE Menu and Indicators then
        # make those options visible.
        if self.panel_layout_exists(panel_layout + '-fresh') and \
           self.panel_layout_exists(panel_layout + '-indicators') and \
           self.panel_layout_exists(panel_layout + '-indicators-fresh'):
            self.builder.get_object('frame_panel_features').show()
        else:
            self.builder.get_object('frame_panel_features').hide()

        new_layout = panel_layout
        if self.builder.get_object('checkbutton_indicators').get_active() and \
           self.builder.get_object('checkbutton_advanced_menu').get_active():
            new_layout += '-indicators-fresh'
        elif self.builder.get_object('checkbutton_indicators').get_active():
            new_layout += '-indicators'
        elif self.builder.get_object('checkbutton_advanced_menu').get_active():
            new_layout += '-fresh'

        if not self.panel_layout_exists(new_layout):
            new_layout = panel_layout

        print('Switching to: ' + new_layout)

        # Use this in python < 3.3. Python >= 3.3 has subprocess.DEVNULL
        devnull = open(os.devnull, 'wb')
        subprocess.call(['killall', 'mate-panel'], stdout=devnull, stderr=devnull)
        subprocess.call(['dconf', 'reset', '-f', '/org/mate/panel/objects/'], stdout=devnull, stderr=devnull)
        subprocess.call(['dconf', 'reset', '-f', '/org/mate/panel/toplevels/'], stdout=devnull, stderr=devnull)
        subprocess.call(['mate-panel', '--layout', new_layout, '--reset'], stdout=devnull, stderr=devnull)
        devnull.close()

        if os.path.exists(os.path.join('/','usr','share','mate-panel','layouts', new_layout + '.panel')):
            print('Loading additional panel configuration for ' + panel_layout)
            cmd = 'dconf load /org/mate/panel/ < /usr/share/mate-panel/layouts/' + new_layout + '.panel'
            os.system(cmd)
        else:
            print('No additional panel configuration for ' + new_layout)

        devnull = open(os.devnull, 'wb')
        subprocess.Popen(['mate-panel', '--replace'], stdout=devnull, stderr=devnull)
        devnull.close()

        # Indicator enabled layouts auto-load the sound-indicator.
        # Therefore, make mate-volume-control-applet is killed or
        # started accordingly.
        if 'indicators' in new_layout:
            self.disable_mate_volume_applet()
        else:
            self.enable_mate_volume_applet()

        # Enable/disable the appropriate dock if one of the dock ready
        # panel layouts is selected.
        dock = None
        if self.find_on_path('docky'):
            dock = 'docky'
        elif self.find_on_path('plank'):
            dock = 'plank'

        current_wm = self.get_current_wm()
        if new_layout.startswith('eleven') and dock is not None:
            if 'Compiz' in current_wm:
                # https://bugs.launchpad.net/ubuntu-mate/+bug/1437611
                devnull = open(os.devnull, 'wb')
                subprocess.call(['dconf', 'write', '/org/compiz/profiles/mate/plugins/thumbnail/current-viewport', 'false'], stdout=devnull, stderr=devnull)
                devnull.close()

            if dock is 'docky':
                self.disable_dock('plank')
            elif dock is 'plank':
                self.disable_dock('docky')
            self.enable_dock(dock)
        else:
            if self.get_current_wm() == 'compiz':
                # https://bugs.launchpad.net/ubuntu-mate/+bug/1437611
                devnull = open(os.devnull, 'wb')
                subprocess.call(['dconf', 'write', '/org/compiz/profiles/mate/plugins/thumbnail/current-viewport', 'true'], stdout=devnull, stderr=devnull)
                devnull.close()

            self.disable_dock('docky')
            self.disable_dock('plank')

    def init_panel_features(self):
        # Set the base layout and toggle visible options.
        current_layout = self.get_string('org.mate.panel', 'default-layout')
        base_layout = current_layout.replace('-indicators','').replace('-fresh','')
        print ('Schema layout: ' + current_layout)
        print('Base layout: ' + base_layout)

        if 'indicators' in current_layout:
            self.builder.get_object('checkbutton_indicators').set_active(True)
        else:
            self.builder.get_object('checkbutton_indicators').set_active(False)

        if 'fresh' in current_layout:
            self.builder.get_object('checkbutton_advanced_menu').set_active(True)
        else:
            self.builder.get_object('checkbutton_advanced_menu').set_active(False)

        if not self.panel_layout_exists(base_layout + '-fresh') and \
           not self.panel_layout_exists(base_layout + '-indicators') and \
           not self.panel_layout_exists(base_layout + '-indicators-fresh'):
            self.builder.get_object('frame_panel_features').hide()

        source = Gio.SettingsSchemaSource.get_default()
        if source.lookup('org.mate.panel', True) != None:
            widget = self.builder.get_object('combobox_panels')
            index = 0
            for row in widget.get_model():
                if(base_layout == row[1]):
                    widget.set_active(index)
                    break
                index = index +1
            widget.connect("changed", lambda x: self.combo_fallback('org.mate.panel', 'default-layout', x))

    def toggle_panel_features(self, widget):
        # Set the base layout and and issue a replace
        current_layout = current_layout = self.get_string('org.mate.panel', 'default-layout')
        base_layout = current_layout.replace('-indicators','').replace('-fresh','')
        self.replace_panel_layout(base_layout)

    def panel_layout_exists(self, panel_layout):
        return os.path.exists('/usr/share/mate-panel/layouts/' + panel_layout + '.layout')

    def compiz_capable(self):
        if self.find_on_path('compiz') and self.find_on_path('glxinfo'):
            process = subprocess.Popen(['glxinfo'], stdout=subprocess.PIPE)
            out, err = process.communicate()
            decoded = out.decode('utf-8')

            software_rasterizer = decoded.count("Software Rasterizer")
            texture_from_pixmap = decoded.count("texture_from_pixmap")
            if software_rasterizer == 0 and texture_from_pixmap > 2:
                return True

        return False

    def marco_capable(self):
        return self.find_on_path('marco')

    def metacity_capable(self):
        return self.find_on_path('metacity')

    def mutter_capable(self):
        if self.find_on_path('mutter') and self.find_on_path('glxinfo'):
            process = subprocess.Popen(['glxinfo'], stdout=subprocess.PIPE)
            out, err = process.communicate()
            decoded = out.decode('utf-8')

            software_rasterizer = decoded.count("Software Rasterizer")
            texture_from_pixmap = decoded.count("texture_from_pixmap")
            if software_rasterizer == 0 and texture_from_pixmap > 2:
                return True
        return False

    def additional_tweaks(self, schema, key, value):
        if schema == "org.mate.Marco.general" and key == "button-layout":
            # If the button-layout is changed in MATE reflect that change
            # for GTK3 and GNOME.
            self.set_string("org.mate.interface", "gtk-decoration-layout", value)
            self.set_string("org.gnome.desktop.wm.preferences", "button-layout", value)
        elif schema == "org.mate.session.required-components" and key == "windowmanager":
            wm = value
            # Sanity check
            if wm not in ['compiz', 'marco', 'metacity', 'mutter']:
                wm = 'marco'

            # If the window manager is being changed, replace it now!
            self.replace_windowmanager(wm, True)

            # Update the widget based on the selected window manager.
            if wm == 'marco' or  wm == 'metacity':
                self.builder.get_object('frame_performance').show()
                self.builder.get_object('frame_behaviour').show()
                if wm == 'marco':
                    self.init_checkbox('org.mate.Marco.general', 'reduced-resources', 'checkbox_resources')
                    self.init_checkbox('org.mate.Marco.general', 'compositing-manager', 'checkbox_compositing')
                    self.init_checkbox('org.mate.Marco.general', 'side-by-side-tiling', 'checkbox_snapping')
                elif wm == 'metacity':
                    self.init_checkbox('org.gnome.metacity', 'reduced-resources', 'checkbox_resources')
                    self.init_checkbox('org.gnome.metacity', 'compositing-manager', 'checkbox_compositing')
                    self.init_checkbox('org.gnome.metacity', 'edge-tiling', 'checkbox_snapping')
            else:
                self.builder.get_object('frame_performance').hide()
                self.builder.get_object('frame_behaviour').hide()

            if wm == 'compiz':
               self.builder.get_object('button_compiz_reset').show()
            else:
               self.builder.get_object('button_compiz_reset').hide()

        elif schema == "org.mate.panel" and key == "default-layout":
            panel_layout = value
            # If the panel layout is being changed, replace it now!
            self.replace_panel_layout(panel_layout)

    def combo_fallback(self, schema, key, widget):
        act = widget.get_active()
        value = widget.get_model()[act]
        self.set_string(schema, key, value[1])

        # Process any additional changes required for the schema and key
        self.additional_tweaks(schema, key, value[1])

    # Change pages
    def side_view_nav(self, param):
        treePaths = param.get_selected_items()
        if (len(treePaths) > 0):
            treePath = treePaths[0]
            index = int("%s" % treePath) #Hack to turn treePath into an int
            target = self.sidePages[index].notebook_index
            self.builder.get_object("notebook1").set_current_page(target)

    def maximus_available(self):
        available = False
        if os.path.exists('/usr/bin/mate-maximus') and \
           os.path.exists('/usr/lib/mate-netbook/mate-window-picker-applet'):
            available = True
        return available

    def make_list_of_panel_layouts(self):
        # Determine what capabilities are available
        indicators_available = False
        if os.path.exists('/usr/lib/indicators/7/libapplication.so') and \
           os.path.exists('/usr/lib/indicator-sound-gtk2/indicator-sound-service') and \
           os.path.exists('/usr/share/mate-panel/applets/org.ayatana.panel.IndicatorApplet.mate-panel-applet'):
            indicators_available = True

        mate_menu_available = False
        if os.path.exists('/usr/lib/mate-menu/mate-menu.py'):
            mate_menu_available = True

        mint_menu_available = False
        if os.path.exists('usr/lib/linuxmint/mintMenu/mintMenu.py'):
            mint_menu_available = True

        mageia_cc_available = False
        if os.path.exists('/usr/share/applications/mageia-drakconf.desktop'):
            mageia_cc_available = True

        gnome_menu_available = False
        if os.path.exists('/usr/lib/gnome-main-menu/main-menu'):
            gnome_menu_available = True

        dock = False
        if os.path.exists('/usr/bin/docky') or os.path.exists('/usr/bin/plank'):
            dock = True

        if indicators_available or mate_menu_available:
            self.builder.get_object('frame_panel_features').show()
            if not indicators_available:
                self.builder.get_object('checkbutton_indicators').hide()
            if not mate_menu_available:
                self.builder.get_object('checkbutton_advanced_menu').hide()
        else:
            self.builder.get_object('frame_panel_features').hide()

        # Panel layouts
        panels = Gtk.ListStore(str, str)

        # Add any saved panel layouts first.
        layouts = os.path.join('/','usr','share','mate-panel','layouts','*-tweak.layout')
        for layout in glob.glob(layouts):
            current_layout = layout.replace('.layout', '').replace('/usr/share/mate-panel/layouts/', '');
            panels.append([_('Custom: ') + current_layout, current_layout])

        if dock:
            if self.panel_layout_exists('eleven'):
                panels.append([_("Cupertino"), "eleven"])

        if self.panel_layout_exists('fedora'):
            panels.append([_("Fedora"), "fedora"])

        if self.panel_layout_exists('default'):
            panels.append([_("GNOME2"), "default"])

        if self.panel_layout_exists('linuxmint') and mint_menu_available:
            panels.append([_("Linux Mint"), "linuxmint"])

        if self.panel_layout_exists('mageia') and mageia_cc_available:
            panels.append([_("Mageia"), "mageia"])

        if self.maximus_available():
            if self.panel_layout_exists('netbook'):
                panels.append([_("Netbook"), "netbook"])

        if self.panel_layout_exists('opensuse') and gnome_menu_available:
            panels.append([_("openSUSE"), "opensuse"])

        if self.panel_layout_exists('redmond'):
            panels.append([_("Redmond"), "redmond"])

        if self.panel_layout_exists('ubuntu-mate'):
            panels.append([_("Ubuntu MATE"), "ubuntu-mate"])

        self.builder.get_object("combobox_panels").set_model(panels)

    def save_panels(self, widget):
        layoutname = getpass.getuser()
        devnull = open(os.devnull, 'wb')
        subprocess.call(['/usr/lib/mate-tweak/mate-panel-backup', layoutname], stdout=devnull, stderr=devnull)
        subprocess.call(['pkexec', '/usr/lib/mate-tweak/install-mate-panel-layout', layoutname], stdout=devnull, stderr=devnull)
        devnull.close()
        Notify.init(_('Panel Layout Saved'))
        save_panels_notify=Notify.Notification.new (_('Panel Layout Saved'),_('Your panel layout has been saved as /usr/share/mate-panel/layouts/' + layoutname +'-tweak.layout'),'dialog-information')
        save_panels_notify.show()
        self.set_string('org.mate.panel', 'default-layout', layoutname + '-tweak')
        self.make_list_of_panel_layouts()
        self.update_combobox('org.mate.panel', 'default-layout', 'combobox_panels')

    def compiz_reset(self, widget):
        # Switch to Marco. Purge all Compiz config and cache. Switch to Compiz.
        self.replace_windowmanager('marco', False)
        devnull = open(os.devnull, 'wb')
        subprocess.call(['dconf', 'reset', '-f', '/org/compiz/'], stdout=devnull, stderr=devnull)
        devnull.close()
        config_compiz = os.path.join(os.path.expanduser('~'),'.config','compiz-1')
        cache_compiz = os.path.join(os.path.expanduser('~'),'.cache','compizconfg1')
        if os.path.exists(config_compiz):
            shutil.rmtree(config_compiz)
        if os.path.exists(cache_compiz):
            shutil.rmtree(cache_compiz)
        self.replace_windowmanager('compiz', False)
        Notify.init(_('Compiz Reset'))
        compiz_reset_notify=Notify.Notification.new (_('Compiz Reset'),_('Your Compiz configuration has been reset to factory defaults.'),'dialog-information')
        compiz_reset_notify.show()

    ''' Create the UI '''
    def __init__(self):
        # Load the Glade UI file
        self.builder = Gtk.Builder()
        self.builder.add_from_file('/usr/lib/mate-tweak/mate-tweak.ui')

        self.window = self.builder.get_object( "main_window" )
        self.builder.get_object("main_window").connect("destroy", Gtk.main_quit)
        self.builder.get_object("button_save_panels").connect("clicked", self.save_panels)
        self.builder.get_object("button_compiz_reset").connect("clicked", self.compiz_reset)

        side_desktop_options = SidePage(0, _("Desktop"), "user-desktop")
        side_windows = SidePage(1, _("Windows"), "preferences-system-windows")
        side_interface = SidePage(2, _("Interface"), "preferences-desktop")
        self.sidePages = [side_desktop_options, side_windows, side_interface]

        # create the backing store for the side nav-view.
        theme = Gtk.IconTheme.get_default()
        self.store = Gtk.ListStore(str, GdkPixbuf.Pixbuf)
        for sidePage in self.sidePages:
            img = theme.load_icon(sidePage.icon, 36, 0)
            self.store.append([sidePage.name, img])

        target = self.sidePages[0].notebook_index
        self.builder.get_object("notebook1").set_current_page(target)

        # Determine the currently active window manager
        marco_mode = False
        metacity_mode = False
        mutter_mode = False
        compiz_mode = False

        current_wm = self.get_current_wm()
        # Order is important here because Marco advertises itself as
        # "Marco (Metacity)"
        if current_wm == 'marco':
            marco_mode = True
        elif current_wm == 'metacity':
            metacity_mode = True
        elif current_wm == 'mutter':
            mutter_mode = True
        elif current_wm == 'compiz':
            compiz_mode = True

        # Do not show Performance or Window behaviour configuration
        # options when Marco or Metacity are not currently running.
        if not marco_mode and not metacity_mode:
            self.builder.get_object('frame_performance').hide()
            self.builder.get_object('checkbox_snapping').hide()

        if not compiz_mode:
            self.builder.get_object('button_compiz_reset').hide()

        if not self.maximus_available():
            self.builder.get_object('checkbox_undecorate').hide()
            self.builder.get_object('checkbox_always_maximize').hide()
        else:
            self.init_checkbox("org.mate.maximus", "undecorate", "checkbox_undecorate")
            self.init_checkbox("org.mate.maximus", "no-maximize", "checkbox_always_maximize")

        # set up the side view - navigation.
        self.builder.get_object("side_view").set_text_column(0)
        self.builder.get_object("side_view").set_pixbuf_column(1)
        self.builder.get_object("side_view").set_model(self.store)
        self.builder.get_object("side_view").select_path(Gtk.TreePath.new_first())
        self.builder.get_object("side_view").connect("selection_changed", self.side_view_nav)

        # set up larger components.
        self.builder.get_object("main_window").set_title(_("MATE Tweak"))

        # i18n
        self.builder.get_object("label_desktop_icons").set_markup("<b>" + _("Desktop icons") + "</b>")
        self.builder.get_object("label_performance").set_markup("<b>" + _("Performance") + "</b>")
        self.builder.get_object("label_behaviour").set_markup("<b>" + _("Window Behaviour") + "</b>")
        self.builder.get_object("label_appearance").set_markup("<b>" + _("Appearance") + "</b>")
        self.builder.get_object("label_icons").set_markup("<b>" + _("Icons") + "</b>")
        self.builder.get_object("label_context_menus").set_markup("<b>" + _("Context menus") + "</b>")
        self.builder.get_object("label_toolbars").set_markup("<b>" + _("Toolbars") + "</b>")
        self.builder.get_object("label_window_manager").set_markup("<b>" + _("Window manager") + "</b>")

        self.builder.get_object("caption_desktop_icons").set_markup("<small>" + _("Select the items you want to see on the desktop:") + "</small>")

        self.builder.get_object("checkbox_computer").set_label(_("Computer"))
        self.builder.get_object("checkbox_home").set_label(_("Home"))
        self.builder.get_object("checkbox_network").set_label(_("Network"))
        self.builder.get_object("checkbox_trash").set_label(_("Trash"))
        self.builder.get_object("checkbox_volumes").set_label(_("Mounted Volumes"))

        self.builder.get_object("checkbox_resources").set_label(_("Use less resources"))
        self.builder.get_object("checkbox_compositing").set_label(_("Use compositing"))

        self.builder.get_object("checkbox_undecorate").set_label(_("Undecorate maximized windows"))
        self.builder.get_object("checkbox_always_maximize").set_label(_("Do not auto-maximize new windows"))

        self.builder.get_object("label_window_control").set_markup("<small>" + _("Window control placement.") + "</small>")

        self.builder.get_object("checkbutton_menuicon").set_label(_("Show icons on menus"))
        self.builder.get_object("checkbutton_button_icons").set_label(_("Show icons on buttons"))
        self.builder.get_object("checkbutton_im_menu").set_label(_("Show Input Methods menu in context menus"))
        self.builder.get_object("checkbutton_unicode").set_label(_("Show Unicode Control Character menu in context menus"))

        self.builder.get_object("label_toolbar_style").set_text(_("Style:"))
        self.builder.get_object("label_toolbar_icon_size").set_text(_("Icon size:"))

        # Desktop page
        self.init_checkbox("org.mate.caja.desktop", "computer-icon-visible", "checkbox_computer")
        self.init_checkbox("org.mate.caja.desktop", "home-icon-visible", "checkbox_home")
        self.init_checkbox("org.mate.caja.desktop", "network-icon-visible", "checkbox_network")
        self.init_checkbox("org.mate.caja.desktop", "trash-icon-visible", "checkbox_trash")
        self.init_checkbox("org.mate.caja.desktop", "volumes-visible", "checkbox_volumes")

        # Window Manager page
        if marco_mode:
            self.init_checkbox('org.mate.Marco.general', 'reduced-resources', 'checkbox_resources')
            self.init_checkbox('org.mate.Marco.general', 'compositing-manager', 'checkbox_compositing')
            self.init_checkbox('org.mate.Marco.general', 'side-by-side-tiling', 'checkbox_snapping')
        elif metacity_mode:
            self.init_checkbox('org.gnome.metacity', 'reduced-resources', 'checkbox_resources')
            self.init_checkbox('org.gnome.metacity', 'compositing-manager', 'checkbox_compositing')
            self.init_checkbox('org.gnome.metacity', 'edge-tiling', 'checkbox_snapping')

        # interface page
        self.init_checkbox("org.mate.interface", "menus-have-icons", "checkbutton_menuicon")
        self.init_checkbox("org.mate.interface", "show-input-method-menu","checkbutton_im_menu")
        self.init_checkbox("org.mate.interface", "show-unicode-menu", "checkbutton_unicode")
        self.init_checkbox("org.mate.interface", "buttons-have-icons", "checkbutton_button_icons")

        iconSizes = Gtk.ListStore(str, str)
        iconSizes.append([_("Small"), "small-toolbar"])
        iconSizes.append([_("Large"), "large-toolbar"])
        self.builder.get_object("combobox_toolbar_icon_size").set_model(iconSizes)
        self.init_combobox("org.mate.interface", "toolbar-icons-size", "combobox_toolbar_icon_size")

        # Window control button
        layouts = Gtk.ListStore(str, str)
        layouts.append([_("Traditional (Right)"), "menu:minimize,maximize,close"])
        layouts.append([_("Contemporary (Left)"), "close,minimize,maximize:"])
        self.builder.get_object("combobox_window_control").set_model(layouts)
        self.init_combobox("org.mate.Marco.general", "button-layout", "combobox_window_control")

        # Window manager
        wms = Gtk.ListStore(str, str)

        if self.marco_capable():
            wms.append([_("Marco (Simple desktop effects)"), 'marco'])
        if self.metacity_capable():
            wms.append([_("Metacity (Simple desktop effects)"), 'metacity'])
        if self.mutter_capable():
            wms.append([_("Mutter (Elegant GPU accelerated desktop effects)"), 'mutter'])
        if self.compiz_capable():
            wms.append([_("Compiz (Advanced GPU accelerated desktop effects)"), 'compiz'])

        self.builder.get_object("combobox_window_manager").set_model(wms)
        self.builder.get_object("combobox_window_manager").set_tooltip_text(_("The new window manager will be activated upon selection."))
        self.builder.get_object("caption_window_manager").set_markup("<small>" + _("Select a window manager.") + "</small>")
        self.init_combobox("org.mate.session.required-components", "windowmanager", "combobox_window_manager")

        # Panel layouts
        self.make_list_of_panel_layouts()
        self.builder.get_object("caption_panels").set_markup("<small>" + _("Select a panel layout to change the user interface.") + "</small>")
        self.builder.get_object("combobox_panels").set_tooltip_text(_("The new panel layout will be activated on selection and destroy any customisations you might have made."))
        self.init_panel_features()
        self.builder.get_object("checkbutton_indicators").connect("toggled", self.toggle_panel_features)
        self.builder.get_object("checkbutton_advanced_menu").connect("toggled", self.toggle_panel_features)

        # toolbar icon styles
        iconStyles = Gtk.ListStore(str, str)
        iconStyles.append([_("Text below items"), "both"])
        iconStyles.append([_("Text beside items"), "both-horiz"])
        iconStyles.append([_("Icons only"), "icons"])
        iconStyles.append([_("Text only"), "text"])
        self.builder.get_object("combobox_toolbar_style").set_model(iconStyles)
        self.init_combobox("org.mate.interface", "toolbar-style", "combobox_toolbar_style")
        self.builder.get_object("main_window").show()

if __name__ == "__main__":
    MateTweak()
    Gtk.main()
