Beispiel #1
0
    def load(self, window):
        self.window = window

        self.spices = Spice_Harvester(self.collection_type, self.window)

        self.stack = SettingsStack()
        self.add_widget(self.stack)
        self.stack.expand = True

        manage_extensions_page = ManageDeskletsPage(self, self.spices,
                                                    self.window)
        self.stack.add_titled(manage_extensions_page, 'installed',
                              _("Manage desklets"))

        download_desklets_page = DownloadSpicesPage(self, self.collection_type,
                                                    self.spices, self.window)
        self.stack.add_titled(download_desklets_page, 'more',
                              _("Download desklets"))

        page = SettingsPage()
        self.stack.add_titled(page, 'general', _("General Settings"))

        settings = page.add_section(_("General Desklets Settings"))

        dec = [[0, _("No decoration")], [1, _("Border only")],
               [2, _("Border and header")]]
        widget = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        combo_box = GSettingsComboBox(_("Decoration of desklets"),
                                      "org.cinnamon",
                                      "desklet-decorations",
                                      dec,
                                      valtype="int")
        widget.pack_start(combo_box, False, False, 0)
        line1 = Gtk.Label()
        line1.set_markup("<i><small>%s</small></i>" % _(
            "Note: Some desklets require the border/header to be always present"
        ))
        line1.get_style_context().add_class("dim-label")
        widget.pack_start(line1, True, True, 0)
        line2 = Gtk.Label()
        line2.set_markup(
            "<i><small>%s</small></i>" %
            _("Such requirements override the settings selected here"))
        line2.get_style_context().add_class("dim-label")
        widget.pack_start(line2, True, True, 0)
        settings.add_row(widget)

        settings.add_row(
            GSettingsSwitch(_("Snap desklets to grid"), "org.cinnamon",
                            "desklet-snap"))
        settings.add_reveal_row(
            GSettingsSpinButton(_("Width of desklet snap grid"),
                                "org.cinnamon", "desklet-snap-interval", "", 0,
                                100, 1, 5), "org.cinnamon", "desklet-snap")
Beispiel #2
0
    def load(self, window):
        self.window = window

        self.spices = Spice_Harvester(self.collection_type, self.window)

        self.stack = SettingsStack()
        self.add_widget(self.stack)
        self.stack.expand = True

        manage_extensions_page = ManageAppletsPage(self, self.spices, window)
        self.stack.add_titled(manage_extensions_page, "installed", _("Manage"))

        download_applets_page = DownloadSpicesPage(self, self.collection_type, self.spices, window)
        self.stack.add_titled(download_applets_page, "more", _("Download"))
Beispiel #3
0
    def on_module_selected(self):
        if not self.loaded:
            print("Loading Themes module")

            self.spices = Spice_Harvester('theme', self.window)

            self.sidePage.stack = SettingsStack()
            self.sidePage.add_widget(self.sidePage.stack)

            self.settings = Gio.Settings.new("org.cinnamon.desktop.interface")
            self.wm_settings = Gio.Settings.new(
                "org.cinnamon.desktop.wm.preferences")
            self.cinnamon_settings = Gio.Settings.new("org.cinnamon.theme")

            self.scale = self.window.get_scale_factor()

            self.icon_chooser = self.create_button_chooser(
                self.settings,
                'icon-theme',
                'icons',
                'icons',
                button_picture_size=ICON_SIZE,
                menu_pictures_size=ICON_SIZE,
                num_cols=4)
            self.cursor_chooser = self.create_button_chooser(
                self.settings,
                'cursor-theme',
                'icons',
                'cursors',
                button_picture_size=32,
                menu_pictures_size=32,
                num_cols=4)
            self.theme_chooser = self.create_button_chooser(
                self.settings,
                'gtk-theme',
                'themes',
                'gtk-3.0',
                button_picture_size=35,
                menu_pictures_size=35,
                num_cols=4)
            self.metacity_chooser = self.create_button_chooser(
                self.wm_settings,
                'theme',
                'themes',
                'metacity-1',
                button_picture_size=32,
                menu_pictures_size=32,
                num_cols=4)
            self.cinnamon_chooser = self.create_button_chooser(
                self.cinnamon_settings,
                'name',
                'themes',
                'cinnamon',
                button_picture_size=60,
                menu_pictures_size=60 * self.scale,
                num_cols=4)

            page = SettingsPage()
            self.sidePage.stack.add_titled(page, "themes", _("Themes"))

            settings = page.add_section(_("Themes"))

            widget = self.make_group(_("Window borders"),
                                     self.metacity_chooser)
            settings.add_row(widget)

            widget = self.make_group(_("Icons"), self.icon_chooser)
            settings.add_row(widget)

            widget = self.make_group(_("Controls"), self.theme_chooser)
            settings.add_row(widget)

            widget = self.make_group(_("Mouse Pointer"), self.cursor_chooser)
            settings.add_row(widget)

            widget = self.make_group(_("Desktop"), self.cinnamon_chooser)
            settings.add_row(widget)

            page = DownloadSpicesPage(self, 'theme', self.spices, self.window)
            self.sidePage.stack.add_titled(page, 'download', _("Add/Remove"))

            page = SettingsPage()
            self.sidePage.stack.add_titled(page, "options", _("Settings"))

            settings = page.add_section(_("Miscellaneous options"))

            widget = GSettingsSwitch(
                _("Show icons in menus"),
                "org.cinnamon.settings-daemon.plugins.xsettings",
                "menus-have-icons")
            settings.add_row(widget)

            widget = GSettingsSwitch(
                _("Show icons on buttons"),
                "org.cinnamon.settings-daemon.plugins.xsettings",
                "buttons-have-icons")
            settings.add_row(widget)

            settings = page.add_section(_("Scrollbar behavior"))

            # Translators: The 'trough' is the part of the scrollbar that the 'handle'
            # rides in.  This setting determines whether clicking in that trough somewhere
            # jumps directly to the new position, or if it only scrolls towards it.
            switch = GtkSettingsSwitch(
                _("Jump to position when clicking in a trough"),
                "gtk-primary-button-warps-slider")
            settings.add_row(switch)

            widget = GSettingsSwitch(_("Use overlay scroll bars"),
                                     "org.cinnamon.desktop.interface",
                                     "gtk-overlay-scrollbars")
            settings.add_row(widget)

            self.gtk2_scrollbar_editor = Gtk2ScrollbarSizeEditor(
                widget.get_scale_factor())

            switch = CssOverrideSwitch(
                _("Override the current theme's scrollbar width"))
            settings.add_row(switch)
            self.scrollbar_switch = switch.content_widget

            widget = CssRange(_("Scrollbar width"), "scrollbar slider",
                              ["min-width", "min-height"], 2, 40, "px", None,
                              switch)
            settings.add_reveal_row(widget)
            widget.sync_initial_switch_state()
            self.scrollbar_css_range = widget.content_widget
            self.scrollbar_css_range.get_adjustment().set_page_increment(2.0)

            switch.content_widget.connect("notify::active",
                                          self.on_css_override_active_changed)
            widget.content_widget.connect("value-changed",
                                          self.on_range_slider_value_changed)

            self.on_css_override_active_changed(switch)

            widget = PreviewWidget()
            settings.add_row(widget)

            label_widget = LabelRow(
                _("""Changes will take effect the next time you log in and may not affect all applications."""
                  ))
            settings.add_row(label_widget)

            self.builder = self.sidePage.builder

            for path in [
                    os.path.expanduser("~/.themes"),
                    os.path.expanduser("~/.icons")
            ]:
                try:
                    os.makedirs(path)
                except OSError:
                    pass

            self.monitors = []
            for path in [
                    os.path.expanduser("~/.themes"), "/usr/share/themes",
                    os.path.expanduser("~/.icons"), "/usr/share/icons"
            ]:
                if os.path.exists(path):
                    file_obj = Gio.File.new_for_path(path)
                    try:
                        file_monitor = file_obj.monitor_directory(
                            Gio.FileMonitorFlags.SEND_MOVED, None)
                        file_monitor.connect("changed", self.on_file_changed)
                        self.monitors.append(file_monitor)
                    except Exception as e:
                        # File monitors can fail when the OS runs out of file handles
                        print(e)

            self.refresh()
Beispiel #4
0
    def build(self, advanced):
        # Clear all the widgets from the content box
        widgets = self.content_box.get_children()
        for widget in widgets:
            self.content_box.remove(widget)
        
        scrolledWindow = Gtk.ScrolledWindow()   
        scrolledWindow.set_shadow_type(Gtk.ShadowType.ETCHED_IN)   
        scrolledWindow.set_border_width(6) 
        self.notebook = Gtk.Notebook()
        applets_vbox = Gtk.VBox()
        
        self.search_entry = Gtk.Entry()
        self.search_entry.set_icon_from_icon_name(Gtk.EntryIconPosition.PRIMARY, 'edit-find')
        self.search_entry.set_placeholder_text(_("Search applets"))
        self.search_entry.connect('changed', self.on_entry_refilter)

        self.notebook.append_page(applets_vbox, Gtk.Label(_("Installed")))
        
        self.content_box.add(self.notebook)
        self.treeview = Gtk.TreeView()
        
        cr = Gtk.CellRendererToggle()
        cr.connect("toggled", self.toggled, self.treeview)
        column1 = Gtk.TreeViewColumn(_("Enable"), cr)
        column1.set_cell_data_func(cr, self.celldatafunction_checkbox)        
        column1.set_resizable(True)

        column2 = Gtk.TreeViewColumn(_("Icon"), Gtk.CellRendererPixbuf(), pixbuf=4)        
        column2.set_resizable(True)

        column3 = Gtk.TreeViewColumn(_("Description"), Gtk.CellRendererText(), markup=1)        
        column3.set_resizable(True)      
        column3.set_max_width(450)

        cr = Gtk.CellRendererText()
        actionColumn = Gtk.TreeViewColumn(_("Action"), cr)
        actionColumn.set_cell_data_func(cr, self._action_data_func)
        
        self.treeview.append_column(column2)
        self.treeview.append_column(column3)
        self.treeview.append_column(actionColumn)
        self.treeview.set_headers_visible(False)
        
        self.model = Gtk.TreeStore(str, str, int, int, GdkPixbuf.Pixbuf, str, int, bool, str)
        #                          uuid, desc, enabled, max-instances, icon, name, read-only, hide-config-button, ext-setting-app

        self.modelfilter = self.model.filter_new()
        self.onlyActive = True
        self.modelfilter.set_visible_func(self.only_active)
        
        self.treeview.set_model(self.modelfilter)
        self.treeview.set_search_column(5)
        self.treeview.set_search_entry(self.search_entry)
        # Find the enabled applets
        self.settings = Gio.Settings.new("org.cinnamon")
        self.enabled_applets = self.settings.get_strv("enabled-applets")
                         
        self.load_applets()

        self.model.set_sort_column_id(5, Gtk.SortType.ASCENDING) # Sort by name 
        
        self.settings.connect("changed::enabled-applets", lambda x,y: self._enabled_applets_changed())
        
        scrolledWindow.add(self.treeview)
        self.treeview.connect('button_press_event', self.on_button_press_event)

        self.instanceButton = Gtk.Button(_("Add to panel"))
        self.instanceButton.connect("clicked", lambda x: self._add_another_instance())
        self.instanceButton.set_tooltip_text(_("Some applets can be added multiple times.\nUse this to add another instance. Use panel edit mode to remove a single instance."))
        self.instanceButton.set_sensitive(False);

        self.configureButton = Gtk.Button(_("Configure"))
        self.configureButton.connect("clicked", self._configure_applet)
        self.configureButton.set_tooltip_text(_("Configure this applet"))

        self.extConfigureButton = Gtk.Button(_("Configure"))
        self.extConfigureButton.connect("clicked", self._external_configure_launch)
        self.extConfigureButton.set_tooltip_text(_("Configure this applet"))


        restoreButton = Gtk.Button(_("Restore to default"))
        restoreButton.connect("clicked", lambda x: self._restore_default_applets())
        # Installed 
        hbox = Gtk.HBox()
        self.activeButton = Gtk.ToggleButton(_("Active"))
        self.inactiveButton = Gtk.ToggleButton(_("Inactive"))
        self.activeButton.set_active(True)
        self.inactiveButton.set_active(False)
        self.activeHandler = self.activeButton.connect("toggled", self._filter_toggle)
        self.inactiveHandler = self.inactiveButton.connect("toggled", self._filter_toggle)

        buttonbox = Gtk.ButtonBox.new(Gtk.Orientation.HORIZONTAL)
        buttonbox.set_spacing(6)
        buttonbox.pack_start(self.activeButton, False, False, 0)
        buttonbox.pack_start(self.inactiveButton, False, False, 0)
        hbox.pack_start(buttonbox, False, False, 4)

        hbox.pack_end(self.search_entry, False, False, 4)
        applets_vbox.pack_start(hbox, False, False, 4)
        hbox.show()
        self.search_entry.show()

        applets_vbox.pack_start(scrolledWindow, True, True, 0)
        hbox = Gtk.HBox()
        applets_vbox.pack_start(hbox, False, True, 5)

        buttonbox = Gtk.ButtonBox.new(Gtk.Orientation.HORIZONTAL)
        buttonbox.set_layout(Gtk.ButtonBoxStyle.START);
        buttonbox.set_spacing(5)
        hbox.pack_start(buttonbox, True, True, 5)
        hbox.xalign = 1.0

        img = Gtk.Image.new_from_stock("gtk-add", Gtk.IconSize.BUTTON)
        self.instanceButton.set_image(img)
        img = Gtk.Image.new_from_stock("gtk-properties", Gtk.IconSize.BUTTON)
        self.configureButton.set_image(img)
        img = Gtk.Image.new_from_stock("gtk-properties", Gtk.IconSize.BUTTON)
        self.extConfigureButton.set_image(img)

        buttonbox.pack_start(self.instanceButton, False, False, 0)
        buttonbox.pack_start(self.configureButton, False, False, 0)
        buttonbox.pack_start(self.extConfigureButton, False, False, 0)

        rightbuttonbox = Gtk.ButtonBox.new(Gtk.Orientation.HORIZONTAL);
        rightbuttonbox.set_layout(Gtk.ButtonBoxStyle.END);
        rightbuttonbox.pack_start(restoreButton, False, False, 0)

        hbox.pack_end(rightbuttonbox, False, False, 5)

        self.configureButton.hide()
        self.configureButton.set_no_show_all(True)
        self.extConfigureButton.hide()
        self.extConfigureButton.set_no_show_all(True)

        # Get More - Variables prefixed with "gm_" where necessary
        gm_scrolled_window = Gtk.ScrolledWindow()
        gm_scrolled_window.set_shadow_type(Gtk.ShadowType.ETCHED_IN)
        gm_scrolled_window.set_border_width(6)
        getmore_vbox = Gtk.VBox()
        getmore_vbox.set_border_width(0)

        getmore_label = Gtk.Label(_("Get more online"))
        self.notebook.append_page(getmore_vbox, getmore_label)
        self.notebook.connect("switch-page", self.on_page_changed)

        self.gm_combosort = Gtk.ComboBox()
        renderer_text = Gtk.CellRendererText()
        self.gm_combosort.pack_start(renderer_text, True)
        sortTypes=Gtk.ListStore(int, str)
        sortTypes.append([self.SORT_NAME, _("Name")])
        sortTypes.append([self.SORT_RATING, _("Most popular")])
        sortTypes.append([self.SORT_DATE_EDITED, _("Latest")])
        self.gm_combosort.set_model(sortTypes)
        self.gm_combosort.set_entry_text_column(1)
        self.gm_combosort.set_active(1) #Rating
        self.gm_combosort.connect('changed', self.gm_changed_sorting)
        self.gm_combosort.add_attribute(renderer_text, "text", 1)
        self.gm_combosort.show()

        hbox = Gtk.HBox()
        #hbox.set_margin_bottom(2)
        sortLabel = Gtk.Label()
        sortLabel.set_text("Sort by")
        sortLabel.show()
        hbox.pack_start(sortLabel, False, False, 4)
        hbox.pack_start(self.gm_combosort, False, False, 2)
        hbox.show()

        self.gm_search_entry = Gtk.Entry()
        self.gm_search_entry.connect('changed', self.gm_on_entry_refilter)
        self.gm_search_entry.set_icon_from_icon_name(Gtk.EntryIconPosition.PRIMARY, 'edit-find')
        self.gm_search_entry.set_placeholder_text(_("Search applets"))
        hbox.pack_end(self.gm_search_entry, False, False, 4)
        self.search_entry.show()
        
        getmore_vbox.pack_start(hbox, False, False, 4)

        # MODEL
        self.gm_model = Gtk.TreeStore(str, str, int, GdkPixbuf.Pixbuf, int, str, int)
        #                            uuid, name, install, icon, score
        self.gm_model.set_sort_column_id(4, Gtk.SortType.DESCENDING)

        # TREE
        self.gm_modelfilter = self.gm_model.filter_new()
        self.gm_modelfilter.set_visible_func(self.gm_match_func)
        self.gm_treeview = Gtk.TreeView()
        
        gm_cr = Gtk.CellRendererToggle()
        gm_cr.connect("toggled", self.gm_toggled, self.gm_treeview)
        gm_column1 = Gtk.TreeViewColumn(_("Install"), gm_cr)
        gm_column1.set_cell_data_func(gm_cr, self.gm_celldatafunction_checkbox)
        gm_column1.set_resizable(True)

        gm_column2 = Gtk.TreeViewColumn(_("Icon"), Gtk.CellRendererPixbuf(), pixbuf=3)
        gm_column2.set_resizable(True)

        gm_column3 = Gtk.TreeViewColumn(_("Description"), Gtk.CellRendererText(), markup=1)
        gm_column3.set_resizable(True)
        gm_column3.set_max_width(400)
        
        cr = Gtk.CellRendererText()
        actionColumn = Gtk.TreeViewColumn(_("Action"), cr)
        actionColumn.set_cell_data_func(cr, self._gm_action_data_func)
        actionColumn.set_max_width(70)

        right = Gtk.CellRendererText()
        right.set_property('xalign', 1.0)
        gm_column4 = Gtk.TreeViewColumn(_("Score"), right, markup=4)
        gm_column4.set_resizable(True)
        gm_column4.set_alignment(1.0)

        self.gm_treeview.append_column(gm_column1)
        self.gm_treeview.append_column(gm_column2)
        self.gm_treeview.append_column(gm_column3)
        self.gm_treeview.append_column(actionColumn)
        self.gm_treeview.append_column(gm_column4)
        self.gm_treeview.set_headers_visible(False)

        self.gm_treeview.set_model(self.gm_modelfilter)
        self.gm_treeview.set_search_column(5)
        self.gm_treeview.set_search_entry(self.gm_search_entry)

        gm_scrolled_window.add(self.gm_treeview)
        self.gm_treeview.connect('motion_notify_event', self.gm_on_motion_notify_event)
        self.gm_treeview.connect('button_press_event', self.gm_on_button_press_event)

        getmore_vbox.add(gm_scrolled_window)

        hbox = Gtk.HBox()
        buttonbox = Gtk.ButtonBox.new(Gtk.Orientation.HORIZONTAL)
        buttonbox.set_spacing(6)
        self.install_button = Gtk.Button(_("Install selected"))
        reload_button = Gtk.Button(_("Refresh list"))
        buttonbox.pack_start(self.install_button, False, False, 2)
        buttonbox.pack_end(reload_button, False, False, 2)
        hbox.pack_start(buttonbox, True, True, 5)
        getmore_vbox.pack_end(hbox, False, True, 5)

        reload_button.connect("clicked", lambda x: self.load_spices(True))
        self.install_button.connect("clicked", lambda x: self.install_applets())
        self.content_box.show_all()   
        self.treeview.get_selection().connect("changed", lambda x: self._selection_changed());
        self.install_list = []
        
        self.spices = Spice_Harvester('applets', self.window, self.builder, self.on_enable_new_applet)
        if not self.spices.get_webkit_enabled():
            getmore_label.set_sensitive(False)
            reload_button.set_sensitive(False)

        self.spices.scrubConfigDirs(self.enabled_applets)

        if len(sys.argv) > 2:
            for row in self.model:
                uuid = self.model.get_value(row.iter, 0)
                if uuid == sys.argv[2]:
                    path = self.model.get_path(row.iter)
                    filtered = self.treeview.get_model().convert_child_path_to_path(path)
                    if filtered is not None:
                        self.treeview.get_selection().select_path(filtered)
                        self.treeview.scroll_to_cell(filtered, None, False, 0, 0)
                        if self.configureButton.get_visible() and self.configureButton.get_sensitive():
                            self.configureButton.clicked()
                        elif self.extConfigureButton.get_visible() and self.extConfigureButton.get_sensitive():
                            self.extConfigureButton.clicked()
Beispiel #5
0
class AppletViewSidePage (SidePage):
    SORT_NAME = 0
    SORT_RATING = 1
    SORT_DATE_EDITED = 2
    SORT_ENABLED = 3
    SORT_REMOVABLE = 4

    def __init__(self, name, icon, keywords, advanced, content_box):
        SidePage.__init__(self, name, icon, keywords, advanced, content_box)
        self.icons = []

    def build(self, advanced):
        # Clear all the widgets from the content box
        widgets = self.content_box.get_children()
        for widget in widgets:
            self.content_box.remove(widget)
        
        scrolledWindow = Gtk.ScrolledWindow()   
        scrolledWindow.set_shadow_type(Gtk.ShadowType.ETCHED_IN)   
        scrolledWindow.set_border_width(6) 
        self.notebook = Gtk.Notebook()
        applets_vbox = Gtk.VBox()
        
        self.search_entry = Gtk.Entry()
        self.search_entry.set_icon_from_icon_name(Gtk.EntryIconPosition.PRIMARY, 'edit-find')
        self.search_entry.set_placeholder_text(_("Search applets"))
        self.search_entry.connect('changed', self.on_entry_refilter)

        self.notebook.append_page(applets_vbox, Gtk.Label(_("Installed")))
        
        self.content_box.add(self.notebook)
        self.treeview = Gtk.TreeView()
        
        cr = Gtk.CellRendererToggle()
        cr.connect("toggled", self.toggled, self.treeview)
        column1 = Gtk.TreeViewColumn(_("Enable"), cr)
        column1.set_cell_data_func(cr, self.celldatafunction_checkbox)        
        column1.set_resizable(True)

        column2 = Gtk.TreeViewColumn(_("Icon"), Gtk.CellRendererPixbuf(), pixbuf=4)        
        column2.set_resizable(True)

        column3 = Gtk.TreeViewColumn(_("Description"), Gtk.CellRendererText(), markup=1)        
        column3.set_resizable(True)      
        column3.set_max_width(450)

        cr = Gtk.CellRendererText()
        actionColumn = Gtk.TreeViewColumn(_("Action"), cr)
        actionColumn.set_cell_data_func(cr, self._action_data_func)
        
        self.treeview.append_column(column2)
        self.treeview.append_column(column3)
        self.treeview.append_column(actionColumn)
        self.treeview.set_headers_visible(False)
        
        self.model = Gtk.TreeStore(str, str, int, int, GdkPixbuf.Pixbuf, str, int, bool, str)
        #                          uuid, desc, enabled, max-instances, icon, name, read-only, hide-config-button, ext-setting-app

        self.modelfilter = self.model.filter_new()
        self.onlyActive = True
        self.modelfilter.set_visible_func(self.only_active)
        
        self.treeview.set_model(self.modelfilter)
        self.treeview.set_search_column(5)
        self.treeview.set_search_entry(self.search_entry)
        # Find the enabled applets
        self.settings = Gio.Settings.new("org.cinnamon")
        self.enabled_applets = self.settings.get_strv("enabled-applets")
                         
        self.load_applets()

        self.model.set_sort_column_id(5, Gtk.SortType.ASCENDING) # Sort by name 
        
        self.settings.connect("changed::enabled-applets", lambda x,y: self._enabled_applets_changed())
        
        scrolledWindow.add(self.treeview)
        self.treeview.connect('button_press_event', self.on_button_press_event)

        self.instanceButton = Gtk.Button(_("Add to panel"))
        self.instanceButton.connect("clicked", lambda x: self._add_another_instance())
        self.instanceButton.set_tooltip_text(_("Some applets can be added multiple times.\nUse this to add another instance. Use panel edit mode to remove a single instance."))
        self.instanceButton.set_sensitive(False);

        self.configureButton = Gtk.Button(_("Configure"))
        self.configureButton.connect("clicked", self._configure_applet)
        self.configureButton.set_tooltip_text(_("Configure this applet"))

        self.extConfigureButton = Gtk.Button(_("Configure"))
        self.extConfigureButton.connect("clicked", self._external_configure_launch)
        self.extConfigureButton.set_tooltip_text(_("Configure this applet"))


        restoreButton = Gtk.Button(_("Restore to default"))
        restoreButton.connect("clicked", lambda x: self._restore_default_applets())
        # Installed 
        hbox = Gtk.HBox()
        self.activeButton = Gtk.ToggleButton(_("Active"))
        self.inactiveButton = Gtk.ToggleButton(_("Inactive"))
        self.activeButton.set_active(True)
        self.inactiveButton.set_active(False)
        self.activeHandler = self.activeButton.connect("toggled", self._filter_toggle)
        self.inactiveHandler = self.inactiveButton.connect("toggled", self._filter_toggle)

        buttonbox = Gtk.ButtonBox.new(Gtk.Orientation.HORIZONTAL)
        buttonbox.set_spacing(6)
        buttonbox.pack_start(self.activeButton, False, False, 0)
        buttonbox.pack_start(self.inactiveButton, False, False, 0)
        hbox.pack_start(buttonbox, False, False, 4)

        hbox.pack_end(self.search_entry, False, False, 4)
        applets_vbox.pack_start(hbox, False, False, 4)
        hbox.show()
        self.search_entry.show()

        applets_vbox.pack_start(scrolledWindow, True, True, 0)
        hbox = Gtk.HBox()
        applets_vbox.pack_start(hbox, False, True, 5)

        buttonbox = Gtk.ButtonBox.new(Gtk.Orientation.HORIZONTAL)
        buttonbox.set_layout(Gtk.ButtonBoxStyle.START);
        buttonbox.set_spacing(5)
        hbox.pack_start(buttonbox, True, True, 5)
        hbox.xalign = 1.0

        img = Gtk.Image.new_from_stock("gtk-add", Gtk.IconSize.BUTTON)
        self.instanceButton.set_image(img)
        img = Gtk.Image.new_from_stock("gtk-properties", Gtk.IconSize.BUTTON)
        self.configureButton.set_image(img)
        img = Gtk.Image.new_from_stock("gtk-properties", Gtk.IconSize.BUTTON)
        self.extConfigureButton.set_image(img)

        buttonbox.pack_start(self.instanceButton, False, False, 0)
        buttonbox.pack_start(self.configureButton, False, False, 0)
        buttonbox.pack_start(self.extConfigureButton, False, False, 0)

        rightbuttonbox = Gtk.ButtonBox.new(Gtk.Orientation.HORIZONTAL);
        rightbuttonbox.set_layout(Gtk.ButtonBoxStyle.END);
        rightbuttonbox.pack_start(restoreButton, False, False, 0)

        hbox.pack_end(rightbuttonbox, False, False, 5)

        self.configureButton.hide()
        self.configureButton.set_no_show_all(True)
        self.extConfigureButton.hide()
        self.extConfigureButton.set_no_show_all(True)

        # Get More - Variables prefixed with "gm_" where necessary
        gm_scrolled_window = Gtk.ScrolledWindow()
        gm_scrolled_window.set_shadow_type(Gtk.ShadowType.ETCHED_IN)
        gm_scrolled_window.set_border_width(6)
        getmore_vbox = Gtk.VBox()
        getmore_vbox.set_border_width(0)

        getmore_label = Gtk.Label(_("Get more online"))
        self.notebook.append_page(getmore_vbox, getmore_label)
        self.notebook.connect("switch-page", self.on_page_changed)

        self.gm_combosort = Gtk.ComboBox()
        renderer_text = Gtk.CellRendererText()
        self.gm_combosort.pack_start(renderer_text, True)
        sortTypes=Gtk.ListStore(int, str)
        sortTypes.append([self.SORT_NAME, _("Name")])
        sortTypes.append([self.SORT_RATING, _("Most popular")])
        sortTypes.append([self.SORT_DATE_EDITED, _("Latest")])
        self.gm_combosort.set_model(sortTypes)
        self.gm_combosort.set_entry_text_column(1)
        self.gm_combosort.set_active(1) #Rating
        self.gm_combosort.connect('changed', self.gm_changed_sorting)
        self.gm_combosort.add_attribute(renderer_text, "text", 1)
        self.gm_combosort.show()

        hbox = Gtk.HBox()
        #hbox.set_margin_bottom(2)
        sortLabel = Gtk.Label()
        sortLabel.set_text("Sort by")
        sortLabel.show()
        hbox.pack_start(sortLabel, False, False, 4)
        hbox.pack_start(self.gm_combosort, False, False, 2)
        hbox.show()

        self.gm_search_entry = Gtk.Entry()
        self.gm_search_entry.connect('changed', self.gm_on_entry_refilter)
        self.gm_search_entry.set_icon_from_icon_name(Gtk.EntryIconPosition.PRIMARY, 'edit-find')
        self.gm_search_entry.set_placeholder_text(_("Search applets"))
        hbox.pack_end(self.gm_search_entry, False, False, 4)
        self.search_entry.show()
        
        getmore_vbox.pack_start(hbox, False, False, 4)

        # MODEL
        self.gm_model = Gtk.TreeStore(str, str, int, GdkPixbuf.Pixbuf, int, str, int)
        #                            uuid, name, install, icon, score
        self.gm_model.set_sort_column_id(4, Gtk.SortType.DESCENDING)

        # TREE
        self.gm_modelfilter = self.gm_model.filter_new()
        self.gm_modelfilter.set_visible_func(self.gm_match_func)
        self.gm_treeview = Gtk.TreeView()
        
        gm_cr = Gtk.CellRendererToggle()
        gm_cr.connect("toggled", self.gm_toggled, self.gm_treeview)
        gm_column1 = Gtk.TreeViewColumn(_("Install"), gm_cr)
        gm_column1.set_cell_data_func(gm_cr, self.gm_celldatafunction_checkbox)
        gm_column1.set_resizable(True)

        gm_column2 = Gtk.TreeViewColumn(_("Icon"), Gtk.CellRendererPixbuf(), pixbuf=3)
        gm_column2.set_resizable(True)

        gm_column3 = Gtk.TreeViewColumn(_("Description"), Gtk.CellRendererText(), markup=1)
        gm_column3.set_resizable(True)
        gm_column3.set_max_width(400)
        
        cr = Gtk.CellRendererText()
        actionColumn = Gtk.TreeViewColumn(_("Action"), cr)
        actionColumn.set_cell_data_func(cr, self._gm_action_data_func)
        actionColumn.set_max_width(70)

        right = Gtk.CellRendererText()
        right.set_property('xalign', 1.0)
        gm_column4 = Gtk.TreeViewColumn(_("Score"), right, markup=4)
        gm_column4.set_resizable(True)
        gm_column4.set_alignment(1.0)

        self.gm_treeview.append_column(gm_column1)
        self.gm_treeview.append_column(gm_column2)
        self.gm_treeview.append_column(gm_column3)
        self.gm_treeview.append_column(actionColumn)
        self.gm_treeview.append_column(gm_column4)
        self.gm_treeview.set_headers_visible(False)

        self.gm_treeview.set_model(self.gm_modelfilter)
        self.gm_treeview.set_search_column(5)
        self.gm_treeview.set_search_entry(self.gm_search_entry)

        gm_scrolled_window.add(self.gm_treeview)
        self.gm_treeview.connect('motion_notify_event', self.gm_on_motion_notify_event)
        self.gm_treeview.connect('button_press_event', self.gm_on_button_press_event)

        getmore_vbox.add(gm_scrolled_window)

        hbox = Gtk.HBox()
        buttonbox = Gtk.ButtonBox.new(Gtk.Orientation.HORIZONTAL)
        buttonbox.set_spacing(6)
        self.install_button = Gtk.Button(_("Install selected"))
        reload_button = Gtk.Button(_("Refresh list"))
        buttonbox.pack_start(self.install_button, False, False, 2)
        buttonbox.pack_end(reload_button, False, False, 2)
        hbox.pack_start(buttonbox, True, True, 5)
        getmore_vbox.pack_end(hbox, False, True, 5)

        reload_button.connect("clicked", lambda x: self.load_spices(True))
        self.install_button.connect("clicked", lambda x: self.install_applets())
        self.content_box.show_all()   
        self.treeview.get_selection().connect("changed", lambda x: self._selection_changed());
        self.install_list = []
        
        self.spices = Spice_Harvester('applets', self.window, self.builder, self.on_enable_new_applet)
        if not self.spices.get_webkit_enabled():
            getmore_label.set_sensitive(False)
            reload_button.set_sensitive(False)

        self.spices.scrubConfigDirs(self.enabled_applets)

        if len(sys.argv) > 2:
            for row in self.model:
                uuid = self.model.get_value(row.iter, 0)
                if uuid == sys.argv[2]:
                    path = self.model.get_path(row.iter)
                    filtered = self.treeview.get_model().convert_child_path_to_path(path)
                    if filtered is not None:
                        self.treeview.get_selection().select_path(filtered)
                        self.treeview.scroll_to_cell(filtered, None, False, 0, 0)
                        if self.configureButton.get_visible() and self.configureButton.get_sensitive():
                            self.configureButton.clicked()
                        elif self.extConfigureButton.get_visible() and self.extConfigureButton.get_sensitive():
                            self.extConfigureButton.clicked()

    def _filter_toggle(self, widget):
        if widget == self.activeButton:
            self.activeButton.handler_block(self.activeHandler)
            self.activeButton.set_active(True)
            self.activeButton.handler_unblock(self.activeHandler)

            self.inactiveButton.handler_block(self.inactiveHandler)
            self.inactiveButton.set_active(False)
            self.inactiveButton.handler_unblock(self.inactiveHandler)

            self.onlyActive = True
        else:
            self.inactiveButton.handler_block(self.inactiveHandler)
            self.inactiveButton.set_active(True)
            self.inactiveButton.handler_unblock(self.inactiveHandler)

            self.activeButton.handler_block(self.activeHandler)
            self.activeButton.set_active(False)
            self.activeButton.handler_unblock(self.activeHandler)

            self.onlyActive = False

        self.modelfilter.refilter()
        return False

    def on_button_press_event(self, widget, event):
        if event.button == 3:
            data = widget.get_path_at_pos(int(event.x),int(event.y))
            res = False
            if data:
                sel=[]
                path, col, cx, cy=data
                indices = path.get_indices()
                iter = self.modelfilter.get_iter(path)

                for i in self.treeview.get_selection().get_selected_rows()[1]:
                    sel.append(i.get_indices()[0])

                if sel:
                    popup = Gtk.Menu()
                    popup.attach_to_widget(self.treeview, None)

                    uuid = self.modelfilter.get_value(iter, 0)
                    name = self.modelfilter.get_value(iter, 5)

                    if self.modelfilter.get_value(iter, 2) > 0:
                        item = Gtk.MenuItem(_("Remove all from panel"))
                        item.connect('activate', lambda x: self.disable_applet(uuid))
                        popup.add(item)

                        checked = self.modelfilter.get_value(iter, 2)
                        max_instances = self.modelfilter.get_value(iter, 3);
                        can_instance = max_instances == -1 or ((max_instances > 0) and (max_instances > checked))
                        if can_instance:
                            item = Gtk.MenuItem(_("Add to panel"))
                            item.connect('activate', lambda x: self.instance_applet(uuid))
                            popup.add(item)
                    else:
                        item = Gtk.MenuItem(_("Add to panel"))
                        item.connect('activate', lambda x: self.enable_applet(uuid))
                        popup.add(item)
                        
                    
                    item = Gtk.MenuItem(_("Uninstall"))
                    if self.modelfilter.get_value(iter, 6):
                        item.connect('activate', lambda x: self.uninstall_applet(uuid, name))
                        item.set_sensitive(True)
                    else:
                        item.set_sensitive(False)
                    popup.add(item)

                    #popup.add(item)
                    popup.show_all()
                    popup.popup(None, None, None, None, event.button, event.time)

                # Only allow context menu for currently selected item
                if indices[0] not in sel:
                    return False

            return True

    def _action_data_func(self, column,cell, model, iter, data=None):
        readonly = model.get_value(iter, 6)
        label = '(System)' if not readonly else ''
        cell.set_property('markup',"<span color='#999999'>%s</span>" % label)

    def gm_view_details(self, uuid):
        self.spices.show_detail(uuid, lambda x: self.gm_mark(uuid, True))

    def gm_mark(self, uuid, shouldMark=True):
        for row in self.gm_model:
            if uuid == self.gm_model.get_value(row.iter, 0):
                self.gm_model.set_value(row.iter, 2, 1 if shouldMark else 0)

        if not shouldMark:
            newApplets = []
            for i_uuid in self.install_list:
                if uuid != i_uuid:
                    newApplets += [i_uuid]
            self.install_list = newApplets
        else:
            if uuid not in self.install_list:
                self.install_list += [uuid]

        if len(self.install_list) > 0:
            self.install_button.set_sensitive(True)
        else:
            self.install_button.set_sensitive(False)

    def gm_on_motion_notify_event(self, widget, event):
        data = widget.get_path_at_pos(int(event.x),int(event.y))
        if data:
            path, column, x, y=data
            iter = self.gm_modelfilter.get_iter(path)

            if column.get_property('title')==_("Action") and iter != None:
                self.gm_treeview.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.HAND2))
                return
        self.gm_treeview.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.ARROW))

    def gm_on_button_press_event(self, widget, event):
        if event.button == 1:
            data=widget.get_path_at_pos(int(event.x),int(event.y))
            if data:
                path, column, x, y = data
                if column.get_property('title')==_("Action"):
                    iter = self.gm_modelfilter.get_iter(path)
                    uuid = self.gm_modelfilter.get_value(iter, 0)
                    self.gm_view_details(uuid)
                    return False


        if event.button == 3:
            data = widget.get_path_at_pos(int(event.x),int(event.y))
            res = False
            if data:
                sel=[]
                path, col, cx, cy=data
                indices = path.get_indices()
                iter = self.gm_modelfilter.get_iter(path)

                for i in self.gm_treeview.get_selection().get_selected_rows()[1]:
                    sel.append(i.get_indices()[0])

                if sel:
                    popup = Gtk.Menu()
                    popup.attach_to_widget(self.treeview, None)

                    uuid = self.gm_modelfilter.get_value(iter, 0)
                    name = self.gm_modelfilter.get_value(iter, 5)
                    marked = self.gm_modelfilter.get_value(iter, 2)

                    if (marked):
                        item = Gtk.MenuItem(_("Unmark"))
                        popup.add(item)
                        item.connect('activate', lambda x: self.gm_mark(uuid, False))
                    else:
                        item = Gtk.MenuItem(_("Mark for installation"))
                        popup.add(item)
                        item.connect('activate', lambda x: self.gm_mark(uuid, True))
                    

                    item = Gtk.MenuItem(_("More info"))
                    item.connect('activate', lambda x: self.gm_view_details(uuid))
                    popup.add(item)

                    #item = Gtk.MenuItem(_("Homepage.."))
                    #item.connect('activate', lambda x: self.gm_launch_homepage(uuid))
                    #popup.add(item)

                    #item = Gtk.MenuItem(_("Review.."))
                    #item.connect('activate', lambda x: self.gm_view_on_spices(uuid))
                    #popup.add(item)

                    popup.show_all()
                    popup.popup(None, None, None, None, event.button, event.time)

                # Only allow context menu for currently selected item
                if indices[0] not in sel:
                    return False

            return True

    def _gm_action_data_func(self, column,cell, model, iter, data=None):
        cell.set_property('markup',"<span color='#0000FF'>More info</span>")


    def gm_toggled(self, renderer, path, treeview):
        iter = self.gm_model.get_iter(path)
        if (iter != None):
            uuid = self.gm_model.get_value(iter, 0)
            checked = self.gm_model.get_value(iter, 2)

            
            if checked == True:
                self.gm_mark(uuid, False)
            else:
                self.gm_mark(uuid, True)

    def gm_celldatafunction_checkbox(self, column, cell, model, iter, data=None):
        cell.set_property("activatable", True)
        checked = model.get_value(iter, 2)

        if (checked > 0):
            cell.set_property("active", True)
        else:
            cell.set_property("active", False)

    def only_active(self, model, iterr, data=None):
        query = self.search_entry.get_buffer().get_text()
        appletName = model.get_value(iterr, 5)
        
        enabled = model.get_value(iterr, 2)

        if appletName == None:
            return False

        if self.onlyActive == True:
            return enabled > 0 and (query == "" or query in appletName.lower())
        else:
            return enabled == 0 and (query == "" or query in appletName.lower())


    def match_func(self, model, iterr, data=None):
        query = self.search_entry.get_buffer().get_text()
        value = model.get_value(iterr, 5)
        
        if query == "":
            return True
        elif query in value.lower():
            return True
        return False

    def on_entry_refilter(self, widget, data=None):
        self.modelfilter.refilter()

    def gm_changed_sorting(self, widget):
        tree_iter = widget.get_active_iter()
        if tree_iter != None:
            model = widget.get_model()
            value = model[tree_iter][0]

            if value == self.SORT_NAME:
                self.gm_model.set_sort_column_id(5, Gtk.SortType.ASCENDING)
            elif value == self.SORT_RATING:
                self.gm_model.set_sort_column_id(4, Gtk.SortType.DESCENDING)
            elif value == self.SORT_DATE_EDITED:
                self.gm_model.set_sort_column_id(6, Gtk.SortType.DESCENDING)

    def gm_match_func(self, model, iterr, data=None):
        query = self.gm_search_entry.get_buffer().get_text()
        value = model.get_value(iterr, 5)

        if query == "":
            return True
        elif query.lower() in value.lower():
            return True
        return False

    def gm_on_entry_refilter(self, widget, data=None):
        self.gm_modelfilter.refilter()

    def on_enable_new_applet(self, uuid):
        self.enable_applet(uuid)

    def load_spices(self, force=False):
        if self.spices.get_webkit_enabled():
            self.spices.load(self.on_spice_load, force)

    def install_applets(self):
        if len(self.install_list) > 0:
            self.spices.install_all(self.install_list, self.install_finished)
    
    def install_finished(self):
        for row in self.gm_model:
            uuid = self.gm_model.get_value(row.iter, 0)
            if uuid in self.install_list:
                self.gm_model.set_value(row.iter, 2, 0)

        self.install_list = []
        self.load_applets()

    def on_spice_load(self, spicesData):
        #print "total spices loaded: %d" % len(spicesData)
        self.gm_model.clear()
        self.install_button.set_sensitive(False)
        for uuid in spicesData:
            appletData = spicesData[uuid]
            appletName = appletData['name'].replace('&', '&amp;')
            iter = self.gm_model.insert_before(None, None)
            self.gm_model.set_value(iter, 0, uuid)
            self.gm_model.set_value(iter, 1, '<b>%s</b>\n<b><span foreground="#333333" size="xx-small">%s</span></b>\n<i><span foreground="#555555" size="x-small">%s</span></i>' % (appletName, uuid, "Description not implemented"))
            self.gm_model.set_value(iter, 2, 0)
            
            icon_filename = os.path.basename(appletData['icon'])
            
            if not os.path.exists(os.path.join(self.spices.get_cache_folder(), icon_filename)):
                img = GdkPixbuf.Pixbuf.new_from_file_at_size( "/usr/lib/cinnamon-settings/data/icons/applets.svg", 32, 32)
            else:
                img = GdkPixbuf.Pixbuf.new_from_file_at_size(os.path.join(self.spices.get_cache_folder(), icon_filename), 32, 32)
            self.gm_model.set_value(iter, 3, img)
            self.gm_model.set_value(iter, 4, int(appletData['score']))
            self.gm_model.set_value(iter, 5, appletData['name'])
            self.gm_model.set_value(iter, 6, int(appletData['last_edited']))

    def enable_applet(self, uuid):
        applet_id = self.settings.get_int("next-applet-id");
        self.settings.set_int("next-applet-id", (applet_id+1));
        self.enabled_applets.append("panel1:right:0:%s:%d" % (uuid, applet_id))
        self.settings.set_strv("enabled-applets", self.enabled_applets)

    def disable_applet(self, uuid):
        newApplets = []
        for enabled_applet in self.enabled_applets:
            if uuid not in enabled_applet:
                newApplets.append(enabled_applet)
        self.enabled_applets = newApplets
        self.settings.set_strv("enabled-applets", self.enabled_applets)

    def uninstall_applet(self, uuid, name):
        self.disable_applet(uuid)
        self.spices.uninstall(uuid, name, self.on_uninstall_finished)
    
    def on_uninstall_finished(self, uuid):
        self.load_applets()

    def instance_applet(self, uuid):
        applet_id = self.settings.get_int("next-applet-id");
        self.settings.set_int("next-applet-id", (applet_id+1));
        self.enabled_applets.append("panel1:right:0:%s:%d" % (uuid, applet_id))
        self.settings.set_strv("enabled-applets", self.enabled_applets)

    def on_page_changed(self, notebook, page, page_num):
        if page_num == 1 and len(self.gm_model) == 0:
            self.load_spices()

        return True

    def _enabled_applets_changed(self):
        last_selection = ''
        model, treeiter = self.treeview.get_selection().get_selected()

        self.enabled_applets = self.settings.get_strv("enabled-applets")
        
        uuidCount = {}
        for enabled_applet in self.enabled_applets:
            try:
                panel, align, order, uuid, id = enabled_applet.split(":")
                if uuid in uuidCount:
                    uuidCount[uuid] += 1
                else:
                    uuidCount[uuid] = 1
            except:
                pass

        for row in self.model:
            uuid = self.model.get_value(row.iter, 0)
            if(uuid in uuidCount):
                self.model.set_value(row.iter, 2, uuidCount[uuid])
            else:
                self.model.set_value(row.iter, 2, 0)
        
    def _add_another_instance(self):
        model, treeiter = self.treeview.get_selection().get_selected()
        if treeiter:
            self._add_another_instance_iter(treeiter)
        
    def _add_another_instance_iter(self, treeiter):
        uuid = self.modelfilter.get_value(treeiter, 0);
        self.instance_applet(uuid)
        
    def _selection_changed(self):
        model, treeiter = self.treeview.get_selection().get_selected()
        enabled = False;
        
        tip = _("Some applets can be added multiple times.\nUse this to add another instance. Use panel edit mode to remove a single instance.")
        if treeiter:
            checked = model.get_value(treeiter, 2);
            max_instances = model.get_value(treeiter, 3);
            enabled = max_instances > checked
            if max_instances == 1:
                tip += _("\nThis applet does not support multiple instances.")
            else:
                tip += _("\nThis applet supports max %d instances.") % max_instances
        self.instanceButton.set_sensitive(enabled);
        self.instanceButton.set_tooltip_text(tip)
        if treeiter:
            hide_override = model.get_value(treeiter, 7)
            ext_override = model.get_value(treeiter, 8)
            if hide_override:
                self.configureButton.hide()
                self.extConfigureButton.hide()
                return
            if ext_override != "":
                self.configureButton.hide()
                self.extConfigureButton.show()
                if checked:
                    self.extConfigureButton.set_sensitive(True)
                else:
                    self.extConfigureButton.set_sensitive(False)
                return
        if treeiter and self._has_settings(model.get_value(treeiter, 0)):
            self.extConfigureButton.hide()
            self.configureButton.show()
            if checked:
                self.configureButton.set_sensitive(True)
            else:
                self.configureButton.set_sensitive(False)
        else:
            self.configureButton.hide()
            self.extConfigureButton.hide()

    def _has_settings(self, uuid):
        if os.path.exists("%s/.cinnamon/configs/%s" % (home, uuid)):
            if len(os.listdir("%s/.cinnamon/configs/%s" % (home, uuid))) > 0:
                return True
        return False

    def _configure_applet(self, widget):
        model, treeiter = self.treeview.get_selection().get_selected()
        if treeiter:
            uuid = model.get_value(treeiter, 0)
            settingContainer = XletSettings.XletSetting(uuid, self, "applet")
            self.content_box.pack_start(settingContainer.content, True, True, 2)
            self.notebook.hide()
            settingContainer.show()

    def _external_configure_launch(self, widget):
        model, treeiter = self.treeview.get_selection().get_selected()
        if treeiter:
            app = model.get_value(treeiter, 8)
            if app is not None:
                subprocess.Popen([app])

    def _close_configure(self, settingContainer):
        settingContainer.content.hide()
        self.notebook.show_all()

    def _restore_default_applets(self):
        os.system('gsettings reset org.cinnamon next-applet-id')
        os.system('gsettings reset org.cinnamon enabled-applets')
    
    def load_applets(self):
        self.model.clear()
        self.load_applets_in('/usr/share/cinnamon/applets')
        self.load_applets_in('%s/.local/share/cinnamon/applets' % home)

    def load_applets_in(self, directory):
        if os.path.exists(directory) and os.path.isdir(directory):
            applets = os.listdir(directory)
            applets.sort()
            for applet in applets:
                try:           
                    if os.path.exists("%s/%s/metadata.json" % (directory, applet)):
                        json_data=open("%s/%s/metadata.json" % (directory, applet)).read()
                        data = json.loads(json_data)  
                        applet_uuid = data["uuid"]
                        applet_name = data["name"]                                        
                        applet_description = data["description"]                          
                        try: applet_max_instances = int(data["max-instances"])
                        except KeyError: applet_max_instances = 1
                        except ValueError: applet_max_instances = 1

                        try: applet_role = data["role"]
                        except KeyError: applet_role = None
                        except ValueError: applet_role = None

                        try: hide_config_button = data["hide-configuration"]
                        except KeyError: hide_config_button = False
                        except ValueError: hide_config_button = False

                        try: ext_config_app = os.path.join(directory, applet, data["external-configuration-app"])
                        except KeyError: ext_config_app = ""
                        except ValueError: ext_config_app = ""

                        if ext_config_app != "" and not os.path.exists(ext_config_app):
                            ext_config_app = ""

                        if applet_max_instances < -1:
                            applet_max_instances = 1
                            
                        if self.search_entry.get_text().upper() in (applet_name + applet_description).upper():
                            iter = self.model.insert_before(None, None)
                            found = 0
                            for enabled_applet in self.enabled_applets:
                                if applet_uuid in enabled_applet:
                                    found += 1

                            self.model.set_value(iter, 0, applet_uuid)                
                            self.model.set_value(iter, 1, '<b>%s</b>\n<b><span foreground="#333333" size="xx-small">%s</span></b>\n<i><span foreground="#555555" size="x-small">%s</span></i>' % (applet_name, applet_uuid, applet_description))                                  
                            self.model.set_value(iter, 2, found)
                            self.model.set_value(iter, 3, applet_max_instances)
                            img = None                            
                            if "icon" in data:
                                applet_icon = data["icon"]
                                theme = Gtk.IconTheme.get_default()                                                    
                                if theme.has_icon(applet_icon):
                                    img = theme.load_icon(applet_icon, 32, 0)
                            elif os.path.exists("%s/%s/icon.png" % (directory, applet)):
                                img = GdkPixbuf.Pixbuf.new_from_file_at_size("%s/%s/icon.png" % (directory, applet), 32, 32)                            
                            
                            if img is None:                                                
                                img = GdkPixbuf.Pixbuf.new_from_file_at_size( "/usr/lib/cinnamon-settings/data/icons/applets.svg", 32, 32)
                                
                            self.model.set_value(iter, 4, img)
                            self.model.set_value(iter, 5, applet_name)
                            self.model.set_value(iter, 6, os.access(directory, os.W_OK))
                            self.model.set_value(iter, 7, hide_config_button)
                            self.model.set_value(iter, 8, ext_config_app)

                except Exception, detail:
                    print "Failed to load applet %s: %s" % (applet, detail)
Beispiel #6
0
    def on_module_selected(self):
        if not self.loaded:
            print("Loading Themes module")

            self.spices = Spice_Harvester('theme', self.window)

            self.sidePage.stack = SettingsStack()
            self.sidePage.add_widget(self.sidePage.stack)

            self.settings = Gio.Settings.new("org.cinnamon.desktop.interface")
            self.wm_settings = Gio.Settings.new(
                "org.cinnamon.desktop.wm.preferences")
            self.cinnamon_settings = Gio.Settings.new("org.cinnamon.theme")

            self.icon_chooser = self.create_button_chooser(
                self.settings,
                'icon-theme',
                'icons',
                'icons',
                button_picture_size=ICON_SIZE,
                menu_pictures_size=ICON_SIZE,
                num_cols=4)
            self.cursor_chooser = self.create_button_chooser(
                self.settings,
                'cursor-theme',
                'icons',
                'cursors',
                button_picture_size=32,
                menu_pictures_size=32,
                num_cols=4)
            self.theme_chooser = self.create_button_chooser(
                self.settings,
                'gtk-theme',
                'themes',
                'gtk-3.0',
                button_picture_size=35,
                menu_pictures_size=35,
                num_cols=4)
            self.metacity_chooser = self.create_button_chooser(
                self.wm_settings,
                'theme',
                'themes',
                'metacity-1',
                button_picture_size=32,
                menu_pictures_size=32,
                num_cols=4)
            self.cinnamon_chooser = self.create_button_chooser(
                self.cinnamon_settings,
                'name',
                'themes',
                'cinnamon',
                button_picture_size=60,
                menu_pictures_size=60,
                num_cols=4)

            page = SettingsPage()
            self.sidePage.stack.add_titled(page, "themes", _("Themes"))

            settings = page.add_section(_("Themes"))

            widget = self.make_group(_("Window borders"),
                                     self.metacity_chooser)
            settings.add_row(widget)

            widget = self.make_group(_("Icons"), self.icon_chooser)
            settings.add_row(widget)

            widget = self.make_group(_("Controls"), self.theme_chooser)
            settings.add_row(widget)

            widget = self.make_group(_("Mouse Pointer"), self.cursor_chooser)
            settings.add_row(widget)

            widget = self.make_group(_("Desktop"), self.cinnamon_chooser)
            settings.add_row(widget)

            page = DownloadSpicesPage(self, 'theme', self.spices, self.window)
            self.sidePage.stack.add_titled(page, 'download', _("Add/Remove"))

            page = SettingsPage()
            self.sidePage.stack.add_titled(page, "options", _("Settings"))

            settings = page.add_section(_("Miscellaneous options"))

            widget = GSettingsSwitch(
                _("Show icons in menus"),
                "org.cinnamon.settings-daemon.plugins.xsettings",
                "menus-have-icons")
            settings.add_row(widget)

            widget = GSettingsSwitch(
                _("Show icons on buttons"),
                "org.cinnamon.settings-daemon.plugins.xsettings",
                "buttons-have-icons")
            settings.add_row(widget)

            widget = GSettingsSpinButton(
                _("Size of symbolic icons when icons are 16px"),
                "org.cinnamon.theme",
                "symbolic-size-16",
                mini=1,
                maxi=64,
                step=1)
            settings.add_row(widget)

            widget = GSettingsSpinButton(
                _("Size of symbolic icons when icons are 22px"),
                "org.cinnamon.theme",
                "symbolic-size-22",
                mini=1,
                maxi=64,
                step=1)
            settings.add_row(widget)

            widget = GSettingsSpinButton(
                _("Size of symbolic icons when icons are 24px"),
                "org.cinnamon.theme",
                "symbolic-size-24",
                mini=1,
                maxi=64,
                step=1)
            settings.add_row(widget)

            widget = GSettingsSpinButton(
                _("Size of symbolic icons when icons are 32px"),
                "org.cinnamon.theme",
                "symbolic-size-32",
                mini=1,
                maxi=64,
                step=1)
            settings.add_row(widget)

            widget = GSettingsSpinButton(
                _("Size of symbolic icons when icons are 48px"),
                "org.cinnamon.theme",
                "symbolic-size-48",
                mini=1,
                maxi=64,
                step=1)
            settings.add_row(widget)

            self.builder = self.sidePage.builder

            for path in [
                    os.path.expanduser("~/.themes"),
                    os.path.expanduser("~/.icons")
            ]:
                try:
                    os.makedirs(path)
                except OSError:
                    pass

            self.monitors = []
            for path in [
                    os.path.expanduser("~/.themes"), "/usr/share/themes",
                    os.path.expanduser("~/.icons"), "/usr/share/icons"
            ]:
                if os.path.exists(path):
                    file_obj = Gio.File.new_for_path(path)
                    try:
                        file_monitor = file_obj.monitor_directory(
                            Gio.FileMonitorFlags.SEND_MOVED, None)
                        file_monitor.connect("changed", self.on_file_changed)
                        self.monitors.append(file_monitor)
                    except Exception as e:
                        # File monitors can fail when the OS runs out of file handles
                        print(e)

            self.refresh()
Beispiel #7
0
    def on_module_selected(self):
        if not self.loaded:
            print("Loading Themes module")

            self.spices = Spice_Harvester('theme', self.window)

            self.sidePage.stack = SettingsStack()
            self.sidePage.add_widget(self.sidePage.stack)

            self.settings = Gio.Settings.new("org.cinnamon.desktop.interface")
            self.wm_settings = Gio.Settings.new(
                "org.cinnamon.desktop.wm.preferences")
            self.cinnamon_settings = Gio.Settings.new("org.cinnamon.theme")

            self.icon_chooser = self.create_button_chooser(
                self.settings,
                'icon-theme',
                'icons',
                'icons',
                button_picture_size=ICON_SIZE,
                menu_pictures_size=ICON_SIZE,
                num_cols=4)
            self.cursor_chooser = self.create_button_chooser(
                self.settings,
                'cursor-theme',
                'icons',
                'cursors',
                button_picture_size=32,
                menu_pictures_size=32,
                num_cols=4)
            self.theme_chooser = self.create_button_chooser(
                self.settings,
                'gtk-theme',
                'themes',
                'gtk-3.0',
                button_picture_size=35,
                menu_pictures_size=35,
                num_cols=4)
            self.metacity_chooser = self.create_button_chooser(
                self.wm_settings,
                'theme',
                'themes',
                'metacity-1',
                button_picture_size=32,
                menu_pictures_size=32,
                num_cols=4)
            self.cinnamon_chooser = self.create_button_chooser(
                self.cinnamon_settings,
                'name',
                'themes',
                'cinnamon',
                button_picture_size=60,
                menu_pictures_size=60,
                num_cols=4)

            page = SettingsPage()
            self.sidePage.stack.add_titled(page, "themes", _("Themes"))

            settings = page.add_section(_("Themes"))

            widget = self.make_group(_("Window borders"),
                                     self.metacity_chooser)
            settings.add_row(widget)

            widget = self.make_group(_("Icons"), self.icon_chooser)
            settings.add_row(widget)

            widget = self.make_group(_("Controls"), self.theme_chooser)
            settings.add_row(widget)

            widget = self.make_group(_("Mouse Pointer"), self.cursor_chooser)
            settings.add_row(widget)

            widget = self.make_group(_("Desktop"), self.cinnamon_chooser)
            settings.add_row(widget)

            page = DownloadSpicesPage(self, 'theme', self.spices, self.window)
            self.sidePage.stack.add_titled(page, 'download', _("Add/Remove"))

            page = SettingsPage()
            self.sidePage.stack.add_titled(page, "options", _("Settings"))

            settings = page.add_section(_("Miscellaneous options"))

            widget = GSettingsSwitch(
                _("Show icons in menus"),
                "org.cinnamon.settings-daemon.plugins.xsettings",
                "menus-have-icons")
            settings.add_row(widget)

            widget = GSettingsSwitch(
                _("Show icons on buttons"),
                "org.cinnamon.settings-daemon.plugins.xsettings",
                "buttons-have-icons")
            settings.add_row(widget)

            dark_text = _(
                "Use a dark theme variant when available in certain applications"
            )
            dark_italic = _(
                "(Applications must be restarted for this change to take effect)"
            )

            widget = GtkSettingsSwitch(
                "%s\n<i><small>%s</small></i>" % (dark_text, dark_italic),
                "gtk-application-prefer-dark-theme")
            settings.add_row(widget)

            self.builder = self.sidePage.builder

            for path in [
                    os.path.expanduser("~/.themes"),
                    os.path.expanduser("~/.icons")
            ]:
                try:
                    os.makedirs(path)
                except OSError:
                    pass

            self.monitors = []
            for path in [
                    os.path.expanduser("~/.themes"), "/usr/share/themes",
                    os.path.expanduser("~/.icons"), "/usr/share/icons"
            ]:
                if os.path.exists(path):
                    file_obj = Gio.File.new_for_path(path)
                    file_monitor = file_obj.monitor_directory(
                        Gio.FileMonitorFlags.SEND_MOVED, None)
                    file_monitor.connect("changed", self.on_file_changed)
                    self.monitors.append(file_monitor)

            self.refresh()
Beispiel #8
0
    def build(self, advanced):
        # Clear all the widgets from the content box
        widgets = self.content_box.get_children()
        for widget in widgets:
            self.content_box.remove(widget)
        
        scrolledWindow = Gtk.ScrolledWindow()   
        scrolledWindow.set_shadow_type(Gtk.ShadowType.ETCHED_IN)   
        scrolledWindow.set_border_width(6) 
        self.notebook = Gtk.Notebook()
        applets_vbox = Gtk.VBox()
        
        self.search_entry = Gtk.Entry()
        self.search_entry.set_icon_from_icon_name(Gtk.EntryIconPosition.PRIMARY, 'edit-find')
        self.search_entry.set_placeholder_text(_("Search applets"))
        self.search_entry.connect('changed', self.on_entry_refilter)

        self.notebook.append_page(applets_vbox, Gtk.Label(_("Installed")))
        
        self.content_box.add(self.notebook)
        self.treeview = Gtk.TreeView()
        
        cr = Gtk.CellRendererToggle()
        cr.connect("toggled", self.toggled, self.treeview)
        column1 = Gtk.TreeViewColumn(_("Enable"), cr)
        column1.set_cell_data_func(cr, self.celldatafunction_checkbox)        
        column1.set_resizable(True)

        column2 = Gtk.TreeViewColumn(_("Icon"), Gtk.CellRendererPixbuf(), pixbuf=4)        
        column2.set_resizable(True)

        column3 = Gtk.TreeViewColumn(_("Description"), Gtk.CellRendererText(), markup=1)        
        column3.set_resizable(True)      
        column3.set_max_width(450)

        cr = Gtk.CellRendererText()
        actionColumn = Gtk.TreeViewColumn(_("Action"), cr)
        actionColumn.set_cell_data_func(cr, self._action_data_func)
        
        self.treeview.append_column(column2)
        self.treeview.append_column(column3)
        self.treeview.append_column(actionColumn)
        self.treeview.set_headers_visible(False)
        
        self.model = Gtk.TreeStore(str, str, int, int, GdkPixbuf.Pixbuf, str, int, bool, str)
        #                          uuid, desc, enabled, max-instances, icon, name, read-only, hide-config-button, ext-setting-app

        self.modelfilter = self.model.filter_new()
        self.onlyActive = True
        self.modelfilter.set_visible_func(self.only_active)
        
        self.treeview.set_model(self.modelfilter)
        self.treeview.set_search_column(5)
        self.treeview.set_search_entry(self.search_entry)
        # Find the enabled applets
        self.settings = Gio.Settings.new("org.cinnamon")
        self.enabled_applets = self.settings.get_strv("enabled-applets")
                         
        self.load_applets()

        self.model.set_sort_column_id(5, Gtk.SortType.ASCENDING) # Sort by name 
        
        self.settings.connect("changed::enabled-applets", lambda x,y: self._enabled_applets_changed())
        
        scrolledWindow.add(self.treeview)
        self.treeview.connect('button_press_event', self.on_button_press_event)

        self.instanceButton = Gtk.Button(_("Add to panel"))
        self.instanceButton.connect("clicked", lambda x: self._add_another_instance())
        self.instanceButton.set_tooltip_text(_("Some applets can be added multiple times.\nUse this to add another instance. Use panel edit mode to remove a single instance."))
        self.instanceButton.set_sensitive(False);

        self.configureButton = Gtk.Button(_("Configure"))
        self.configureButton.connect("clicked", self._configure_applet)
        self.configureButton.set_tooltip_text(_("Configure this applet"))

        self.extConfigureButton = Gtk.Button(_("Configure"))
        self.extConfigureButton.connect("clicked", self._external_configure_launch)
        self.extConfigureButton.set_tooltip_text(_("Configure this applet"))


        restoreButton = Gtk.Button(_("Restore to default"))
        restoreButton.connect("clicked", lambda x: self._restore_default_applets())
        # Installed 
        hbox = Gtk.HBox()
        self.activeButton = Gtk.ToggleButton(_("Active"))
        self.inactiveButton = Gtk.ToggleButton(_("Inactive"))
        self.activeButton.set_active(True)
        self.inactiveButton.set_active(False)
        self.activeHandler = self.activeButton.connect("toggled", self._filter_toggle)
        self.inactiveHandler = self.inactiveButton.connect("toggled", self._filter_toggle)

        buttonbox = Gtk.ButtonBox.new(Gtk.Orientation.HORIZONTAL)
        buttonbox.set_spacing(6)
        buttonbox.pack_start(self.activeButton, False, False, 0)
        buttonbox.pack_start(self.inactiveButton, False, False, 0)
        hbox.pack_start(buttonbox, False, False, 4)

        hbox.pack_end(self.search_entry, False, False, 4)
        applets_vbox.pack_start(hbox, False, False, 4)
        hbox.show()
        self.search_entry.show()

        applets_vbox.pack_start(scrolledWindow, True, True, 0)
        hbox = Gtk.HBox()
        applets_vbox.pack_start(hbox, False, True, 5)

        buttonbox = Gtk.ButtonBox.new(Gtk.Orientation.HORIZONTAL)
        buttonbox.set_layout(Gtk.ButtonBoxStyle.START);
        buttonbox.set_spacing(5)
        hbox.pack_start(buttonbox, True, True, 5)
        hbox.xalign = 1.0

        img = Gtk.Image.new_from_stock("gtk-add", Gtk.IconSize.BUTTON)
        self.instanceButton.set_image(img)
        img = Gtk.Image.new_from_stock("gtk-properties", Gtk.IconSize.BUTTON)
        self.configureButton.set_image(img)
        img = Gtk.Image.new_from_stock("gtk-properties", Gtk.IconSize.BUTTON)
        self.extConfigureButton.set_image(img)

        buttonbox.pack_start(self.instanceButton, False, False, 0)
        buttonbox.pack_start(self.configureButton, False, False, 0)
        buttonbox.pack_start(self.extConfigureButton, False, False, 0)

        rightbuttonbox = Gtk.ButtonBox.new(Gtk.Orientation.HORIZONTAL);
        rightbuttonbox.set_layout(Gtk.ButtonBoxStyle.END);
        rightbuttonbox.pack_start(restoreButton, False, False, 0)

        hbox.pack_end(rightbuttonbox, False, False, 5)

        self.configureButton.hide()
        self.configureButton.set_no_show_all(True)
        self.extConfigureButton.hide()
        self.extConfigureButton.set_no_show_all(True)

        # Get More - Variables prefixed with "gm_" where necessary
        gm_scrolled_window = Gtk.ScrolledWindow()
        gm_scrolled_window.set_shadow_type(Gtk.ShadowType.ETCHED_IN)
        gm_scrolled_window.set_border_width(6)
        getmore_vbox = Gtk.VBox()
        getmore_vbox.set_border_width(0)

        getmore_label = Gtk.Label(_("Get more online"))
        self.notebook.append_page(getmore_vbox, getmore_label)
        self.notebook.connect("switch-page", self.on_page_changed)

        self.gm_combosort = Gtk.ComboBox()
        renderer_text = Gtk.CellRendererText()
        self.gm_combosort.pack_start(renderer_text, True)
        sortTypes=Gtk.ListStore(int, str)
        sortTypes.append([self.SORT_NAME, _("Name")])
        sortTypes.append([self.SORT_RATING, _("Most popular")])
        sortTypes.append([self.SORT_DATE_EDITED, _("Latest")])
        self.gm_combosort.set_model(sortTypes)
        self.gm_combosort.set_entry_text_column(1)
        self.gm_combosort.set_active(1) #Rating
        self.gm_combosort.connect('changed', self.gm_changed_sorting)
        self.gm_combosort.add_attribute(renderer_text, "text", 1)
        self.gm_combosort.show()

        hbox = Gtk.HBox()
        #hbox.set_margin_bottom(2)
        sortLabel = Gtk.Label()
        sortLabel.set_text("Sort by")
        sortLabel.show()
        hbox.pack_start(sortLabel, False, False, 4)
        hbox.pack_start(self.gm_combosort, False, False, 2)
        hbox.show()

        self.gm_search_entry = Gtk.Entry()
        self.gm_search_entry.connect('changed', self.gm_on_entry_refilter)
        self.gm_search_entry.set_icon_from_icon_name(Gtk.EntryIconPosition.PRIMARY, 'edit-find')
        self.gm_search_entry.set_placeholder_text(_("Search applets"))
        hbox.pack_end(self.gm_search_entry, False, False, 4)
        self.search_entry.show()
        
        getmore_vbox.pack_start(hbox, False, False, 4)

        # MODEL
        self.gm_model = Gtk.TreeStore(str, str, int, GdkPixbuf.Pixbuf, int, str, int)
        #                            uuid, name, install, icon, score
        self.gm_model.set_sort_column_id(4, Gtk.SortType.DESCENDING)

        # TREE
        self.gm_modelfilter = self.gm_model.filter_new()
        self.gm_modelfilter.set_visible_func(self.gm_match_func)
        self.gm_treeview = Gtk.TreeView()
        
        gm_cr = Gtk.CellRendererToggle()
        gm_cr.connect("toggled", self.gm_toggled, self.gm_treeview)
        gm_column1 = Gtk.TreeViewColumn(_("Install"), gm_cr)
        gm_column1.set_cell_data_func(gm_cr, self.gm_celldatafunction_checkbox)
        gm_column1.set_resizable(True)

        gm_column2 = Gtk.TreeViewColumn(_("Icon"), Gtk.CellRendererPixbuf(), pixbuf=3)
        gm_column2.set_resizable(True)

        gm_column3 = Gtk.TreeViewColumn(_("Description"), Gtk.CellRendererText(), markup=1)
        gm_column3.set_resizable(True)
        gm_column3.set_max_width(400)
        
        cr = Gtk.CellRendererText()
        actionColumn = Gtk.TreeViewColumn(_("Action"), cr)
        actionColumn.set_cell_data_func(cr, self._gm_action_data_func)
        actionColumn.set_max_width(70)

        right = Gtk.CellRendererText()
        right.set_property('xalign', 1.0)
        gm_column4 = Gtk.TreeViewColumn(_("Score"), right, markup=4)
        gm_column4.set_resizable(True)
        gm_column4.set_alignment(1.0)

        self.gm_treeview.append_column(gm_column1)
        self.gm_treeview.append_column(gm_column2)
        self.gm_treeview.append_column(gm_column3)
        self.gm_treeview.append_column(actionColumn)
        self.gm_treeview.append_column(gm_column4)
        self.gm_treeview.set_headers_visible(False)

        self.gm_treeview.set_model(self.gm_modelfilter)
        self.gm_treeview.set_search_column(5)
        self.gm_treeview.set_search_entry(self.gm_search_entry)

        gm_scrolled_window.add(self.gm_treeview)
        self.gm_treeview.connect('motion_notify_event', self.gm_on_motion_notify_event)
        self.gm_treeview.connect('button_press_event', self.gm_on_button_press_event)

        getmore_vbox.add(gm_scrolled_window)

        hbox = Gtk.HBox()
        buttonbox = Gtk.ButtonBox.new(Gtk.Orientation.HORIZONTAL)
        buttonbox.set_spacing(6)
        self.install_button = Gtk.Button(_("Install selected"))
        reload_button = Gtk.Button(_("Refresh list"))
        buttonbox.pack_start(self.install_button, False, False, 2)
        buttonbox.pack_end(reload_button, False, False, 2)
        hbox.pack_start(buttonbox, True, True, 5)
        getmore_vbox.pack_end(hbox, False, True, 5)

        reload_button.connect("clicked", lambda x: self.load_spices(True))
        self.install_button.connect("clicked", lambda x: self.install_applets())
        self.content_box.show_all()   
        self.treeview.get_selection().connect("changed", lambda x: self._selection_changed());
        self.install_list = []
        
        self.spices = Spice_Harvester('applets', self.window, self.builder, self.on_enable_new_applet)
        if not self.spices.get_webkit_enabled():
            getmore_label.set_sensitive(False)
            reload_button.set_sensitive(False)

        self.spices.scrubConfigDirs(self.enabled_applets)

        if len(sys.argv) > 2:
            for row in self.model:
                uuid = self.model.get_value(row.iter, 0)
                if uuid == sys.argv[2]:
                    path = self.model.get_path(row.iter)
                    filtered = self.treeview.get_model().convert_child_path_to_path(path)
                    if filtered is not None:
                        self.treeview.get_selection().select_path(filtered)
                        self.treeview.scroll_to_cell(filtered, None, False, 0, 0)
                        if self.configureButton.get_visible() and self.configureButton.get_sensitive():
                            self.configureButton.clicked()
                        elif self.extConfigureButton.get_visible() and self.extConfigureButton.get_sensitive():
                            self.extConfigureButton.clicked()
Beispiel #9
0
class AppletViewSidePage (SidePage):
    SORT_NAME = 0
    SORT_RATING = 1
    SORT_DATE_EDITED = 2
    SORT_ENABLED = 3
    SORT_REMOVABLE = 4

    def __init__(self, name, icon, keywords, advanced, content_box):
        SidePage.__init__(self, name, icon, keywords, advanced, content_box, True)
        self.icons = []

    def build(self, advanced):
        # Clear all the widgets from the content box
        widgets = self.content_box.get_children()
        for widget in widgets:
            self.content_box.remove(widget)
        
        scrolledWindow = Gtk.ScrolledWindow()   
        scrolledWindow.set_shadow_type(Gtk.ShadowType.ETCHED_IN)   
        scrolledWindow.set_border_width(6) 
        self.notebook = Gtk.Notebook()
        applets_vbox = Gtk.VBox()
        
        self.search_entry = Gtk.Entry()
        self.search_entry.set_icon_from_icon_name(Gtk.EntryIconPosition.PRIMARY, 'edit-find')
        self.search_entry.set_placeholder_text(_("Search applets"))
        self.search_entry.connect('changed', self.on_entry_refilter)

        self.notebook.append_page(applets_vbox, Gtk.Label(_("Installed")))
        
        self.content_box.add(self.notebook)
        self.treeview = Gtk.TreeView()
        
        cr = Gtk.CellRendererToggle()
        cr.connect("toggled", self.toggled, self.treeview)
        column1 = Gtk.TreeViewColumn(_("Enable"), cr)
        column1.set_cell_data_func(cr, self.celldatafunction_checkbox)        
        column1.set_resizable(True)

        column2 = Gtk.TreeViewColumn(_("Icon"), Gtk.CellRendererPixbuf(), pixbuf=4)        
        column2.set_resizable(True)

        column3 = Gtk.TreeViewColumn(_("Description"), Gtk.CellRendererText(), markup=1)        
        column3.set_resizable(True)      
        column3.set_max_width(450)

        cr = Gtk.CellRendererText()
        actionColumn = Gtk.TreeViewColumn(_("Action"), cr)
        actionColumn.set_cell_data_func(cr, self._action_data_func)
        
        self.treeview.append_column(column2)
        self.treeview.append_column(column3)
        self.treeview.append_column(actionColumn)
        self.treeview.set_headers_visible(False)
        
        self.model = Gtk.TreeStore(str, str, int, int, GdkPixbuf.Pixbuf, str, int, bool, str)
        #                          uuid, desc, enabled, max-instances, icon, name, read-only, hide-config-button, ext-setting-app

        self.modelfilter = self.model.filter_new()
        self.onlyActive = True
        self.modelfilter.set_visible_func(self.only_active)
        
        self.treeview.set_model(self.modelfilter)
        self.treeview.set_search_column(5)
        self.treeview.set_search_entry(self.search_entry)
        # Find the enabled applets
        self.settings = Gio.Settings.new("org.cinnamon")
        self.enabled_applets = self.settings.get_strv("enabled-applets")
                         
        self.load_applets()

        self.model.set_sort_column_id(5, Gtk.SortType.ASCENDING) # Sort by name 
        
        self.settings.connect("changed::enabled-applets", lambda x,y: self._enabled_applets_changed())
        
        scrolledWindow.add(self.treeview)
        self.treeview.connect('button_press_event', self.on_button_press_event)

        self.instanceButton = Gtk.Button(_("Add to panel"))
        self.instanceButton.connect("clicked", lambda x: self._add_another_instance())
        self.instanceButton.set_tooltip_text(_("Some applets can be added multiple times.\nUse this to add another instance. Use panel edit mode to remove a single instance."))
        self.instanceButton.set_sensitive(False);

        self.configureButton = Gtk.Button(_("Configure"))
        self.configureButton.connect("clicked", self._configure_applet)
        self.configureButton.set_tooltip_text(_("Configure this applet"))

        self.extConfigureButton = Gtk.Button(_("Configure"))
        self.extConfigureButton.connect("clicked", self._external_configure_launch)
        self.extConfigureButton.set_tooltip_text(_("Configure this applet"))


        restoreButton = Gtk.Button(_("Restore to default"))
        restoreButton.connect("clicked", lambda x: self._restore_default_applets())
        # Installed 
        hbox = Gtk.HBox()
        self.activeButton = Gtk.ToggleButton(_("Active"))
        self.inactiveButton = Gtk.ToggleButton(_("Inactive"))
        self.activeButton.set_active(True)
        self.inactiveButton.set_active(False)
        self.activeHandler = self.activeButton.connect("toggled", self._filter_toggle)
        self.inactiveHandler = self.inactiveButton.connect("toggled", self._filter_toggle)

        buttonbox = Gtk.ButtonBox.new(Gtk.Orientation.HORIZONTAL)
        buttonbox.set_spacing(6)
        buttonbox.pack_start(self.activeButton, False, False, 0)
        buttonbox.pack_start(self.inactiveButton, False, False, 0)
        hbox.pack_start(buttonbox, False, False, 4)

        hbox.pack_end(self.search_entry, False, False, 4)
        applets_vbox.pack_start(hbox, False, False, 4)
        hbox.show()
        self.search_entry.show()

        applets_vbox.pack_start(scrolledWindow, True, True, 0)
        hbox = Gtk.HBox()
        applets_vbox.pack_start(hbox, False, True, 5)

        buttonbox = Gtk.ButtonBox.new(Gtk.Orientation.HORIZONTAL)
        buttonbox.set_layout(Gtk.ButtonBoxStyle.START);
        buttonbox.set_spacing(5)
        hbox.pack_start(buttonbox, True, True, 5)
        hbox.xalign = 1.0

        img = Gtk.Image.new_from_stock("gtk-add", Gtk.IconSize.BUTTON)
        self.instanceButton.set_image(img)
        img = Gtk.Image.new_from_stock("gtk-properties", Gtk.IconSize.BUTTON)
        self.configureButton.set_image(img)
        img = Gtk.Image.new_from_stock("gtk-properties", Gtk.IconSize.BUTTON)
        self.extConfigureButton.set_image(img)

        buttonbox.pack_start(self.instanceButton, False, False, 0)
        buttonbox.pack_start(self.configureButton, False, False, 0)
        buttonbox.pack_start(self.extConfigureButton, False, False, 0)

        rightbuttonbox = Gtk.ButtonBox.new(Gtk.Orientation.HORIZONTAL);
        rightbuttonbox.set_layout(Gtk.ButtonBoxStyle.END);
        rightbuttonbox.pack_start(restoreButton, False, False, 0)

        hbox.pack_end(rightbuttonbox, False, False, 5)

        self.configureButton.hide()
        self.configureButton.set_no_show_all(True)
        self.extConfigureButton.hide()
        self.extConfigureButton.set_no_show_all(True)

        # Get More - Variables prefixed with "gm_" where necessary
        gm_scrolled_window = Gtk.ScrolledWindow()
        gm_scrolled_window.set_shadow_type(Gtk.ShadowType.ETCHED_IN)
        gm_scrolled_window.set_border_width(6)
        getmore_vbox = Gtk.VBox()
        getmore_vbox.set_border_width(0)

        getmore_label = Gtk.Label(_("Get more online"))
        self.notebook.append_page(getmore_vbox, getmore_label)
        self.notebook.connect("switch-page", self.on_page_changed)

        self.gm_combosort = Gtk.ComboBox()
        renderer_text = Gtk.CellRendererText()
        self.gm_combosort.pack_start(renderer_text, True)
        sortTypes=Gtk.ListStore(int, str)
        sortTypes.append([self.SORT_NAME, _("Name")])
        sortTypes.append([self.SORT_RATING, _("Most popular")])
        sortTypes.append([self.SORT_DATE_EDITED, _("Latest")])
        self.gm_combosort.set_model(sortTypes)
        self.gm_combosort.set_entry_text_column(1)
        self.gm_combosort.set_active(1) #Rating
        self.gm_combosort.connect('changed', self.gm_changed_sorting)
        self.gm_combosort.add_attribute(renderer_text, "text", 1)
        self.gm_combosort.show()

        hbox = Gtk.HBox()
        #hbox.set_margin_bottom(2)
        sortLabel = Gtk.Label()
        sortLabel.set_text("Sort by")
        sortLabel.show()
        hbox.pack_start(sortLabel, False, False, 4)
        hbox.pack_start(self.gm_combosort, False, False, 2)
        hbox.show()

        self.gm_search_entry = Gtk.Entry()
        self.gm_search_entry.connect('changed', self.gm_on_entry_refilter)
        self.gm_search_entry.set_icon_from_icon_name(Gtk.EntryIconPosition.PRIMARY, 'edit-find')
        self.gm_search_entry.set_placeholder_text(_("Search applets"))
        hbox.pack_end(self.gm_search_entry, False, False, 4)
        self.search_entry.show()
        
        getmore_vbox.pack_start(hbox, False, False, 4)

        # MODEL
        self.gm_model = Gtk.TreeStore(str, str, int, GdkPixbuf.Pixbuf, int, str, int)
        #                            uuid, name, install, icon, score
        self.gm_model.set_sort_column_id(4, Gtk.SortType.DESCENDING)

        # TREE
        self.gm_modelfilter = self.gm_model.filter_new()
        self.gm_modelfilter.set_visible_func(self.gm_match_func)
        self.gm_treeview = Gtk.TreeView()
        
        gm_cr = Gtk.CellRendererToggle()
        gm_cr.connect("toggled", self.gm_toggled, self.gm_treeview)
        gm_column1 = Gtk.TreeViewColumn(_("Install"), gm_cr)
        gm_column1.set_cell_data_func(gm_cr, self.gm_celldatafunction_checkbox)
        gm_column1.set_resizable(True)

        gm_column2 = Gtk.TreeViewColumn(_("Icon"), Gtk.CellRendererPixbuf(), pixbuf=3)
        gm_column2.set_resizable(True)

        gm_column3 = Gtk.TreeViewColumn(_("Description"), Gtk.CellRendererText(), markup=1)
        gm_column3.set_resizable(True)
        gm_column3.set_max_width(400)
        
        cr = Gtk.CellRendererText()
        actionColumn = Gtk.TreeViewColumn(_("Action"), cr)
        actionColumn.set_cell_data_func(cr, self._gm_action_data_func)
        actionColumn.set_max_width(70)

        right = Gtk.CellRendererText()
        right.set_property('xalign', 1.0)
        gm_column4 = Gtk.TreeViewColumn(_("Score"), right, markup=4)
        gm_column4.set_resizable(True)
        gm_column4.set_alignment(1.0)

        self.gm_treeview.append_column(gm_column1)
        self.gm_treeview.append_column(gm_column2)
        self.gm_treeview.append_column(gm_column3)
        self.gm_treeview.append_column(actionColumn)
        self.gm_treeview.append_column(gm_column4)
        self.gm_treeview.set_headers_visible(False)

        self.gm_treeview.set_model(self.gm_modelfilter)
        self.gm_treeview.set_search_column(5)
        self.gm_treeview.set_search_entry(self.gm_search_entry)

        gm_scrolled_window.add(self.gm_treeview)
        self.gm_treeview.connect('motion_notify_event', self.gm_on_motion_notify_event)
        self.gm_treeview.connect('button_press_event', self.gm_on_button_press_event)

        getmore_vbox.add(gm_scrolled_window)

        hbox = Gtk.HBox()
        buttonbox = Gtk.ButtonBox.new(Gtk.Orientation.HORIZONTAL)
        buttonbox.set_spacing(6)
        self.install_button = Gtk.Button(_("Install selected"))
        reload_button = Gtk.Button(_("Refresh list"))
        buttonbox.pack_start(self.install_button, False, False, 2)
        buttonbox.pack_end(reload_button, False, False, 2)
        hbox.pack_start(buttonbox, True, True, 5)
        getmore_vbox.pack_end(hbox, False, True, 5)

        reload_button.connect("clicked", lambda x: self.load_spices(True))
        self.install_button.connect("clicked", lambda x: self.install_applets())
        self.content_box.show_all()   
        self.treeview.get_selection().connect("changed", lambda x: self._selection_changed());
        self.install_list = []
        
        self.spices = Spice_Harvester('applets', self.window, self.builder, self.on_enable_new_applet)
        if not self.spices.get_webkit_enabled():
            getmore_label.set_sensitive(False)
            reload_button.set_sensitive(False)

        self.spices.scrubConfigDirs(self.enabled_applets)

        if len(sys.argv) > 2:
            for row in self.model:
                uuid = self.model.get_value(row.iter, 0)
                if uuid == sys.argv[2]:
                    path = self.model.get_path(row.iter)
                    filtered = self.treeview.get_model().convert_child_path_to_path(path)
                    if filtered is not None:
                        self.treeview.get_selection().select_path(filtered)
                        self.treeview.scroll_to_cell(filtered, None, False, 0, 0)
                        if self.configureButton.get_visible() and self.configureButton.get_sensitive():
                            self.configureButton.clicked()
                        elif self.extConfigureButton.get_visible() and self.extConfigureButton.get_sensitive():
                            self.extConfigureButton.clicked()

    def _filter_toggle(self, widget):
        if widget == self.activeButton:
            self.activeButton.handler_block(self.activeHandler)
            self.activeButton.set_active(True)
            self.activeButton.handler_unblock(self.activeHandler)

            self.inactiveButton.handler_block(self.inactiveHandler)
            self.inactiveButton.set_active(False)
            self.inactiveButton.handler_unblock(self.inactiveHandler)

            self.onlyActive = True
        else:
            self.inactiveButton.handler_block(self.inactiveHandler)
            self.inactiveButton.set_active(True)
            self.inactiveButton.handler_unblock(self.inactiveHandler)

            self.activeButton.handler_block(self.activeHandler)
            self.activeButton.set_active(False)
            self.activeButton.handler_unblock(self.activeHandler)

            self.onlyActive = False

        self.modelfilter.refilter()
        return False

    def on_button_press_event(self, widget, event):
        if event.button == 3:
            data = widget.get_path_at_pos(int(event.x),int(event.y))
            res = False
            if data:
                sel=[]
                path, col, cx, cy=data
                indices = path.get_indices()
                iter = self.modelfilter.get_iter(path)

                for i in self.treeview.get_selection().get_selected_rows()[1]:
                    sel.append(i.get_indices()[0])

                if sel:
                    popup = Gtk.Menu()
                    popup.attach_to_widget(self.treeview, None)

                    uuid = self.modelfilter.get_value(iter, 0)
                    name = self.modelfilter.get_value(iter, 5)

                    if self.modelfilter.get_value(iter, 2) > 0:
                        item = Gtk.MenuItem(_("Remove all from panel"))
                        item.connect('activate', lambda x: self.disable_applet(uuid))
                        popup.add(item)

                        checked = self.modelfilter.get_value(iter, 2)
                        max_instances = self.modelfilter.get_value(iter, 3);
                        can_instance = max_instances == -1 or ((max_instances > 0) and (max_instances > checked))
                        if can_instance:
                            item = Gtk.MenuItem(_("Add to panel"))
                            item.connect('activate', lambda x: self.instance_applet(uuid))
                            popup.add(item)
                    else:
                        item = Gtk.MenuItem(_("Add to panel"))
                        item.connect('activate', lambda x: self.enable_applet(uuid))
                        popup.add(item)
                        
                    
                    item = Gtk.MenuItem(_("Uninstall"))
                    if self.modelfilter.get_value(iter, 6):
                        item.connect('activate', lambda x: self.uninstall_applet(uuid, name))
                        item.set_sensitive(True)
                    else:
                        item.set_sensitive(False)
                    popup.add(item)

                    #popup.add(item)
                    popup.show_all()
                    popup.popup(None, None, None, None, event.button, event.time)

                # Only allow context menu for currently selected item
                if indices[0] not in sel:
                    return False

            return True

    def _action_data_func(self, column,cell, model, iter, data=None):
        readonly = model.get_value(iter, 6)
        label = '(System)' if not readonly else ''
        cell.set_property('markup',"<span color='#999999'>%s</span>" % label)

    def gm_view_details(self, uuid):
        self.spices.show_detail(uuid, lambda x: self.gm_mark(uuid, True))

    def gm_mark(self, uuid, shouldMark=True):
        for row in self.gm_model:
            if uuid == self.gm_model.get_value(row.iter, 0):
                self.gm_model.set_value(row.iter, 2, 1 if shouldMark else 0)

        if not shouldMark:
            newApplets = []
            for i_uuid in self.install_list:
                if uuid != i_uuid:
                    newApplets += [i_uuid]
            self.install_list = newApplets
        else:
            if uuid not in self.install_list:
                self.install_list += [uuid]

        if len(self.install_list) > 0:
            self.install_button.set_sensitive(True)
        else:
            self.install_button.set_sensitive(False)

    def gm_on_motion_notify_event(self, widget, event):
        data = widget.get_path_at_pos(int(event.x),int(event.y))
        if data:
            path, column, x, y=data
            iter = self.gm_modelfilter.get_iter(path)

            if column.get_property('title')==_("Action") and iter != None:
                self.gm_treeview.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.HAND2))
                return
        self.gm_treeview.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.ARROW))

    def gm_on_button_press_event(self, widget, event):
        if event.button == 1:
            data=widget.get_path_at_pos(int(event.x),int(event.y))
            if data:
                path, column, x, y = data
                if column.get_property('title')==_("Action"):
                    iter = self.gm_modelfilter.get_iter(path)
                    uuid = self.gm_modelfilter.get_value(iter, 0)
                    self.gm_view_details(uuid)
                    return False


        if event.button == 3:
            data = widget.get_path_at_pos(int(event.x),int(event.y))
            res = False
            if data:
                sel=[]
                path, col, cx, cy=data
                indices = path.get_indices()
                iter = self.gm_modelfilter.get_iter(path)

                for i in self.gm_treeview.get_selection().get_selected_rows()[1]:
                    sel.append(i.get_indices()[0])

                if sel:
                    popup = Gtk.Menu()
                    popup.attach_to_widget(self.treeview, None)

                    uuid = self.gm_modelfilter.get_value(iter, 0)
                    name = self.gm_modelfilter.get_value(iter, 5)
                    marked = self.gm_modelfilter.get_value(iter, 2)

                    if (marked):
                        item = Gtk.MenuItem(_("Unmark"))
                        popup.add(item)
                        item.connect('activate', lambda x: self.gm_mark(uuid, False))
                    else:
                        item = Gtk.MenuItem(_("Mark for installation"))
                        popup.add(item)
                        item.connect('activate', lambda x: self.gm_mark(uuid, True))
                    

                    item = Gtk.MenuItem(_("More info"))
                    item.connect('activate', lambda x: self.gm_view_details(uuid))
                    popup.add(item)

                    #item = Gtk.MenuItem(_("Homepage.."))
                    #item.connect('activate', lambda x: self.gm_launch_homepage(uuid))
                    #popup.add(item)

                    #item = Gtk.MenuItem(_("Review.."))
                    #item.connect('activate', lambda x: self.gm_view_on_spices(uuid))
                    #popup.add(item)

                    popup.show_all()
                    popup.popup(None, None, None, None, event.button, event.time)

                # Only allow context menu for currently selected item
                if indices[0] not in sel:
                    return False

            return True

    def _gm_action_data_func(self, column,cell, model, iter, data=None):
        cell.set_property('markup',"<span color='#0000FF'>More info</span>")


    def gm_toggled(self, renderer, path, treeview):
        iter = self.gm_model.get_iter(path)
        if (iter != None):
            uuid = self.gm_model.get_value(iter, 0)
            checked = self.gm_model.get_value(iter, 2)

            
            if checked == True:
                self.gm_mark(uuid, False)
            else:
                self.gm_mark(uuid, True)

    def gm_celldatafunction_checkbox(self, column, cell, model, iter, data=None):
        cell.set_property("activatable", True)
        checked = model.get_value(iter, 2)

        if (checked > 0):
            cell.set_property("active", True)
        else:
            cell.set_property("active", False)

    def only_active(self, model, iterr, data=None):
        query = self.search_entry.get_buffer().get_text()
        appletName = model.get_value(iterr, 5)
        
        enabled = model.get_value(iterr, 2)

        if appletName == None:
            return False

        if self.onlyActive == True:
            return enabled > 0 and (query == "" or query in appletName.lower())
        else:
            return enabled == 0 and (query == "" or query in appletName.lower())


    def match_func(self, model, iterr, data=None):
        query = self.search_entry.get_buffer().get_text()
        value = model.get_value(iterr, 5)
        
        if query == "":
            return True
        elif query in value.lower():
            return True
        return False

    def on_entry_refilter(self, widget, data=None):
        self.modelfilter.refilter()

    def gm_changed_sorting(self, widget):
        tree_iter = widget.get_active_iter()
        if tree_iter != None:
            model = widget.get_model()
            value = model[tree_iter][0]

            if value == self.SORT_NAME:
                self.gm_model.set_sort_column_id(5, Gtk.SortType.ASCENDING)
            elif value == self.SORT_RATING:
                self.gm_model.set_sort_column_id(4, Gtk.SortType.DESCENDING)
            elif value == self.SORT_DATE_EDITED:
                self.gm_model.set_sort_column_id(6, Gtk.SortType.DESCENDING)

    def gm_match_func(self, model, iterr, data=None):
        query = self.gm_search_entry.get_buffer().get_text()
        value = model.get_value(iterr, 5)

        if query == "":
            return True
        elif query.lower() in value.lower():
            return True
        return False

    def gm_on_entry_refilter(self, widget, data=None):
        self.gm_modelfilter.refilter()

    def on_enable_new_applet(self, uuid):
        self.enable_applet(uuid)

    def load_spices(self, force=False):
        if self.spices.get_webkit_enabled():
            self.spices.load(self.on_spice_load, force)

    def install_applets(self):
        if len(self.install_list) > 0:
            self.spices.install_all(self.install_list, self.install_finished)
    
    def install_finished(self):
        for row in self.gm_model:
            uuid = self.gm_model.get_value(row.iter, 0)
            if uuid in self.install_list:
                self.gm_model.set_value(row.iter, 2, 0)

        self.install_list = []
        self.load_applets()

    def on_spice_load(self, spicesData):
        #print "total spices loaded: %d" % len(spicesData)
        self.gm_model.clear()
        self.install_button.set_sensitive(False)
        for uuid in spicesData:
            appletData = spicesData[uuid]
            appletName = appletData['name'].replace('&', '&amp;')
            iter = self.gm_model.insert_before(None, None)
            self.gm_model.set_value(iter, 0, uuid)
            self.gm_model.set_value(iter, 1, '<b>%s</b>\n<b><span foreground="#333333" size="xx-small">%s</span></b>\n<i><span foreground="#555555" size="x-small">%s</span></i>' % (appletName, uuid, "Description not implemented"))
            self.gm_model.set_value(iter, 2, 0)
            
            icon_filename = os.path.basename(appletData['icon'])
            
            if not os.path.exists(os.path.join(self.spices.get_cache_folder(), icon_filename)):
                img = GdkPixbuf.Pixbuf.new_from_file_at_size( "/usr/lib/cinnamon-settings/data/icons/applets.svg", 32, 32)
            else:
                img = GdkPixbuf.Pixbuf.new_from_file_at_size(os.path.join(self.spices.get_cache_folder(), icon_filename), 32, 32)
            self.gm_model.set_value(iter, 3, img)
            self.gm_model.set_value(iter, 4, int(appletData['score']))
            self.gm_model.set_value(iter, 5, appletData['name'])
            self.gm_model.set_value(iter, 6, int(appletData['last_edited']))

    def enable_applet(self, uuid):
        applet_id = self.settings.get_int("next-applet-id");
        self.settings.set_int("next-applet-id", (applet_id+1));
        self.enabled_applets.append("panel1:right:0:%s:%d" % (uuid, applet_id))
        self.settings.set_strv("enabled-applets", self.enabled_applets)

    def disable_applet(self, uuid):
        newApplets = []
        for enabled_applet in self.enabled_applets:
            if uuid not in enabled_applet:
                newApplets.append(enabled_applet)
        self.enabled_applets = newApplets
        self.settings.set_strv("enabled-applets", self.enabled_applets)

    def uninstall_applet(self, uuid, name):
        self.disable_applet(uuid)
        self.spices.uninstall(uuid, name, self.on_uninstall_finished)
    
    def on_uninstall_finished(self, uuid):
        self.load_applets()

    def instance_applet(self, uuid):
        applet_id = self.settings.get_int("next-applet-id");
        self.settings.set_int("next-applet-id", (applet_id+1));
        self.enabled_applets.append("panel1:right:0:%s:%d" % (uuid, applet_id))
        self.settings.set_strv("enabled-applets", self.enabled_applets)

    def on_page_changed(self, notebook, page, page_num):
        if page_num == 1 and len(self.gm_model) == 0:
            self.load_spices()

        return True

    def _enabled_applets_changed(self):
        last_selection = ''
        model, treeiter = self.treeview.get_selection().get_selected()

        self.enabled_applets = self.settings.get_strv("enabled-applets")
        
        uuidCount = {}
        for enabled_applet in self.enabled_applets:
            try:
                panel, align, order, uuid, id = enabled_applet.split(":")
                if uuid in uuidCount:
                    uuidCount[uuid] += 1
                else:
                    uuidCount[uuid] = 1
            except:
                pass

        for row in self.model:
            uuid = self.model.get_value(row.iter, 0)
            if(uuid in uuidCount):
                self.model.set_value(row.iter, 2, uuidCount[uuid])
            else:
                self.model.set_value(row.iter, 2, 0)
        
    def _add_another_instance(self):
        model, treeiter = self.treeview.get_selection().get_selected()
        if treeiter:
            self._add_another_instance_iter(treeiter)
        
    def _add_another_instance_iter(self, treeiter):
        uuid = self.modelfilter.get_value(treeiter, 0);
        self.instance_applet(uuid)
        
    def _selection_changed(self):
        model, treeiter = self.treeview.get_selection().get_selected()
        enabled = False;
        
        tip = _("Some applets can be added multiple times.\nUse this to add another instance. Use panel edit mode to remove a single instance.")
        if treeiter:
            checked = model.get_value(treeiter, 2);
            max_instances = model.get_value(treeiter, 3);
            enabled = max_instances > checked
            if max_instances == 1:
                tip += _("\nThis applet does not support multiple instances.")
            else:
                tip += _("\nThis applet supports max %d instances.") % max_instances
        self.instanceButton.set_sensitive(enabled);
        self.instanceButton.set_tooltip_text(tip)
        if treeiter:
            hide_override = model.get_value(treeiter, 7)
            ext_override = model.get_value(treeiter, 8)
            if hide_override:
                self.configureButton.hide()
                self.extConfigureButton.hide()
                return
            if ext_override != "":
                self.configureButton.hide()
                self.extConfigureButton.show()
                if checked:
                    self.extConfigureButton.set_sensitive(True)
                else:
                    self.extConfigureButton.set_sensitive(False)
                return
        if treeiter and self._has_settings(model.get_value(treeiter, 0)):
            self.extConfigureButton.hide()
            self.configureButton.show()
            if checked:
                self.configureButton.set_sensitive(True)
            else:
                self.configureButton.set_sensitive(False)
        else:
            self.configureButton.hide()
            self.extConfigureButton.hide()

    def _has_settings(self, uuid):
        if os.path.exists("%s/.cinnamon/configs/%s" % (home, uuid)):
            if len(os.listdir("%s/.cinnamon/configs/%s" % (home, uuid))) > 0:
                return True
        return False

    def _configure_applet(self, widget):
        model, treeiter = self.treeview.get_selection().get_selected()
        if treeiter:
            uuid = model.get_value(treeiter, 0)
            settingContainer = XletSettings.XletSetting(uuid, self, "applet")
            self.content_box.pack_start(settingContainer.content, True, True, 2)
            self.notebook.hide()
            settingContainer.show()

    def _external_configure_launch(self, widget):
        model, treeiter = self.treeview.get_selection().get_selected()
        if treeiter:
            app = model.get_value(treeiter, 8)
            if app is not None:
                subprocess.Popen([app])

    def _close_configure(self, settingContainer):
        settingContainer.content.hide()
        self.notebook.show_all()

    def _restore_default_applets(self):
        os.system('gsettings reset org.cinnamon next-applet-id')
        os.system('gsettings reset org.cinnamon enabled-applets')
    
    def load_applets(self):
        self.model.clear()
        self.load_applets_in('/usr/share/cinnamon/applets')
        self.load_applets_in('%s/.local/share/cinnamon/applets' % home)

    def load_applets_in(self, directory):
        if os.path.exists(directory) and os.path.isdir(directory):
            applets = os.listdir(directory)
            applets.sort()
            for applet in applets:
                try:           
                    if os.path.exists("%s/%s/metadata.json" % (directory, applet)):
                        json_data=open("%s/%s/metadata.json" % (directory, applet)).read()
                        data = json.loads(json_data)  
                        applet_uuid = data["uuid"]
                        applet_name = data["name"]                                        
                        applet_description = data["description"]                          
                        try: applet_max_instances = int(data["max-instances"])
                        except KeyError: applet_max_instances = 1
                        except ValueError: applet_max_instances = 1

                        try: applet_role = data["role"]
                        except KeyError: applet_role = None
                        except ValueError: applet_role = None

                        try: hide_config_button = data["hide-configuration"]
                        except KeyError: hide_config_button = False
                        except ValueError: hide_config_button = False

                        try: ext_config_app = os.path.join(directory, applet, data["external-configuration-app"])
                        except KeyError: ext_config_app = ""
                        except ValueError: ext_config_app = ""

                        if ext_config_app != "" and not os.path.exists(ext_config_app):
                            ext_config_app = ""

                        if applet_max_instances < -1:
                            applet_max_instances = 1
                            
                        if self.search_entry.get_text().upper() in (applet_name + applet_description).upper():
                            iter = self.model.insert_before(None, None)
                            found = 0
                            for enabled_applet in self.enabled_applets:
                                if applet_uuid in enabled_applet:
                                    found += 1

                            self.model.set_value(iter, 0, applet_uuid)                
                            self.model.set_value(iter, 1, '<b>%s</b>\n<b><span foreground="#333333" size="xx-small">%s</span></b>\n<i><span foreground="#555555" size="x-small">%s</span></i>' % (applet_name, applet_uuid, applet_description))                                  
                            self.model.set_value(iter, 2, found)
                            self.model.set_value(iter, 3, applet_max_instances)
                            img = None                            
                            if "icon" in data:
                                applet_icon = data["icon"]
                                theme = Gtk.IconTheme.get_default()                                                    
                                if theme.has_icon(applet_icon):
                                    img = theme.load_icon(applet_icon, 32, 0)
                            elif os.path.exists("%s/%s/icon.png" % (directory, applet)):
                                img = GdkPixbuf.Pixbuf.new_from_file_at_size("%s/%s/icon.png" % (directory, applet), 32, 32)                            
                            
                            if img is None:                                                
                                img = GdkPixbuf.Pixbuf.new_from_file_at_size( "/usr/lib/cinnamon-settings/data/icons/applets.svg", 32, 32)
                                
                            self.model.set_value(iter, 4, img)
                            self.model.set_value(iter, 5, applet_name)
                            self.model.set_value(iter, 6, os.access(directory, os.W_OK))
                            self.model.set_value(iter, 7, hide_config_button)
                            self.model.set_value(iter, 8, ext_config_app)

                except Exception, detail:
                    print "Failed to load applet %s: %s" % (applet, detail)