def build_single(self): self.nb = None self.view = SectionBg() self.content_box = Gtk.VBox() self.view.add(self.content_box) self.content_box.set_border_width(5) for instance_key in self.applet_settings.keys(): for setting_key in self.applet_settings[instance_key].keys(): if setting_key == "__md5__" or self.applet_settings[ instance_key][setting_key]["type"] == "generic": continue self.setting_factories[instance_key].create( setting_key, self.applet_settings[instance_key][setting_key]["type"], self.uuid) widgets = self.setting_factories[instance_key].widgets for widget_key in widgets.keys(): if widgets[widget_key].get_indented(): indent = XletSettingsWidgets.IndentedHBox() indent.add_fill(widgets[widget_key]) self.content_box.pack_start(indent, False, False, 2) else: self.content_box.pack_start(widgets[widget_key], False, False, 2) if len(widgets[widget_key].dependents) > 0: widgets[widget_key].update_dependents() self.content.pack_start(self.view, True, True, 2) self.current_id = instance_key
def build_single(self): self.nb = None self.view = SectionBg() self.content_box = Gtk.VBox() self.view.add(self.content_box) self.content_box.set_border_width(5) for instance_key in self.applet_settings.keys(): for setting_key in self.applet_settings[instance_key].keys(): if setting_key == "__md5__" or self.applet_settings[instance_key][setting_key]["type"] == "generic": continue self.setting_factories[instance_key].create(setting_key, self.applet_settings[instance_key][setting_key]["type"], self.uuid) widgets = self.setting_factories[instance_key].widgets for widget_key in widgets.keys(): if widgets[widget_key].get_indented(): indent = XletSettingsWidgets.IndentedHBox() indent.add_fill(widgets[widget_key]) self.content_box.pack_start(indent, False, False, 2) else: self.content_box.pack_start(widgets[widget_key], False, False, 2) if len(widgets[widget_key].dependents) > 0: widgets[widget_key].update_dependents() self.current_id = instance_key self.content.pack_start(self.view, True, True, 2)
class XletSetting: def __init__(self, uuid, parent, _type): self.parent = parent self.type = _type self.current_id = None self.builder = Gtk.Builder() self.builder.add_from_file( "/usr/lib/cinnamon-settings/bin/xlet-settings.ui") self.content = self.builder.get_object("content") self.back_to_list_button = self.builder.get_object("back_to_list") self.highlight_button = self.builder.get_object("highlight_button") self.more_button = self.builder.get_object("more_button") self.remove_button = self.builder.get_object("remove_xlet") self.uuid = uuid self.content.connect("hide", self.on_hide) self.applet_meta = {} self.applet_settings = collections.OrderedDict() self.setting_factories = collections.OrderedDict() self.load_applet_data(self.uuid) if "icon" in self.applet_meta: image = Gtk.Image().new_from_icon_name(self.applet_meta["icon"], Gtk.IconSize.BUTTON) self.back_to_list_button.set_image(image) self.back_to_list_button.get_property('image').set_padding(5, 0) self.back_to_list_button.set_label(self.applet_meta["name"]) self.back_to_list_button.set_tooltip_text(_("Back to list")) self.more_button.set_tooltip_text(_("More actions...")) self.remove_button.set_tooltip_text( _("Remove the current instance of this %s") % self.type) self.highlight_button.set_tooltip_text( _("Momentarily highlight the %s on your desktop") % self.type) if len(self.applet_settings.keys()) > 1: self.build_notebook() else: self.build_single() self.back_to_list_button.connect("clicked", self.on_back_to_list_button_clicked) if self.type != "extension": self.highlight_button.connect("clicked", self.on_highlight_button_clicked) self.highlight_button.show() else: self.highlight_button.hide() self.more_button.connect("clicked", self.on_more_button_clicked) self.remove_button.connect("clicked", self.on_remove_button_clicked) def show(self): self.content.show_all() try: self.back_to_list_button.get_property('image').show() except: pass def on_hide(self, widget): self.content.hide() self.content.destroy() self.applet_meta = None self.applet_settings = None for _id in self.setting_factories.keys(): self.setting_factories[_id].pause_monitor() self.setting_factories = None def load_applet_data(self, uuid): found = self.get_meta_data_for_applet("/usr/share/cinnamon/%ss/%s" % (self.type, uuid)) if not found: found = self.get_meta_data_for_applet( "%s/.local/share/cinnamon/%ss/%s" % (home, self.type, uuid)) if not found: print( "Could not find %s metadata - are you sure it's installed correctly?" % self.type) return found = self.get_settings_for_applet("%s/.cinnamon/configs/%s" % (home, uuid)) if not found: print( "Could not find any instance settings data for this %s - are you sure it is loaded, and supports settings?" % self.type) def get_meta_data_for_applet(self, path): if os.path.exists(path) and os.path.isdir(path): if os.path.exists("%s/metadata.json" % path): raw_data = open("%s/metadata.json" % path).read() self.applet_meta = json.loads(raw_data.decode('utf-8')) return True return False def get_settings_for_applet(self, path): if "max-instances" in self.applet_meta: self.multi_instance = int(self.applet_meta["max-instances"]) > 1 else: self.multi_instance = False if os.path.exists(path) and os.path.isdir(path): instances = os.listdir(path) if len(instances) != 0: for instance in instances: raw_data = open("%s/%s" % (path, instance)).read() try: js = json.loads( raw_data.decode('utf-8'), object_pairs_hook=collections.OrderedDict) except: raise Exception( "Failed to parse settings JSON data for %s %s" % (self.type, self.uuid)) instance_id = instance.split(".json")[0] self.applet_settings[instance_id] = js self.setting_factories[ instance_id] = XletSettingsWidgets.Factory( "%s/%s" % (path, instance), instance_id, self.multi_instance, self.uuid) return True else: raise Exception( "Could not find any active setting files for %s %s" % (self.type, self.uuid)) return False def build_single(self): self.nb = None self.view = SectionBg() self.content_box = Gtk.VBox() self.view.add(self.content_box) self.content_box.set_border_width(5) for instance_key in self.applet_settings.keys(): for setting_key in self.applet_settings[instance_key].keys(): if setting_key == "__md5__" or self.applet_settings[ instance_key][setting_key]["type"] == "generic": continue self.setting_factories[instance_key].create( setting_key, self.applet_settings[instance_key][setting_key]["type"], self.uuid) widgets = self.setting_factories[instance_key].widgets for widget_key in widgets.keys(): if widgets[widget_key].get_indented(): indent = XletSettingsWidgets.IndentedHBox() indent.add_fill(widgets[widget_key]) self.content_box.pack_start(indent, False, False, 2) else: self.content_box.pack_start(widgets[widget_key], False, False, 2) if len(widgets[widget_key].dependents) > 0: widgets[widget_key].update_dependents() self.content.pack_start(self.view, True, True, 2) self.current_id = instance_key def build_notebook(self): self.nb = Gtk.Notebook() i = 0 target_instance = -1 target_page = -1 if len(sys.argv) > 3: target_instance = sys.argv[3] for instance_key in self.applet_settings.keys(): view = Gtk.ScrolledWindow() content_box = Gtk.VBox() view.add_with_viewport(content_box) content_box.set_border_width(5) for setting_key in self.applet_settings[instance_key].keys(): if setting_key == "__md5__" or self.applet_settings[ instance_key][setting_key]["type"] == "generic": continue self.setting_factories[instance_key].create( setting_key, self.applet_settings[instance_key][setting_key]["type"], self.uuid) widgets = self.setting_factories[instance_key].widgets for widget_key in widgets.keys(): if widgets[widget_key].get_indented(): indent = XletSettingsWidgets.IndentedHBox() indent.add_fill(widgets[widget_key]) content_box.pack_start(indent, False, False, 2) else: content_box.pack_start(widgets[widget_key], False, False, 2) if len(widgets[widget_key].dependents) > 0: widgets[widget_key].update_dependents() view.show() self.nb.append_page(view, Gtk.Label.new(_("Instance %d") % (i + 1))) view.key = instance_key if view.key == target_instance: target_page = i i += 1 self.content.pack_start(self.nb, True, True, 2) self.nb.set_scrollable(True) if target_page != -1: self.nb.set_current_page(target_page) self.nb.connect("switch-page", self.on_page_changed) def on_page_changed(self, nb, page, num): self.current_id = page.key def on_highlight_button_clicked(self, widget): session_bus = dbus.SessionBus() cinnamon_dbus = session_bus.get_object("org.Cinnamon", "/org/Cinnamon") highlight_applet = cinnamon_dbus.get_dbus_method( 'highlightApplet', 'org.Cinnamon') highlight_applet(self.current_id, self.multi_instance) def on_back_to_list_button_clicked(self, widget): self.parent._close_configure(self) def on_remove_button_clicked(self, widget): settings = Gio.Settings.new("org.cinnamon") if self.type == "applet": enabled_xlets = settings.get_strv("enabled-applets") elif self.type == "desklet": enabled_xlets = settings.get_strv("enabled-desklets") elif self.type == "extension": enabled_xlets = settings.get_strv("enabled-extensions") else: return new_enabled = [] for xlet in enabled_xlets: if self.uuid not in xlet: new_enabled.append(xlet) elif self.multi_instance and self.current_id not in xlet: new_enabled.append(xlet) if self.nb is None or (self.nb is not None and self.nb.get_n_pages() == 1): self.parent._close_configure(self) else: current_index = self.nb.get_current_page() tab = self.nb.get_nth_page(current_index) self.setting_factories[self.current_id].pause_monitor() self.nb.remove_page(current_index) tab.destroy() self.nb.set_current_page(0) if self.type == "applet": settings.set_strv("enabled-applets", new_enabled) elif self.type == "desklet": settings.set_strv("enabled-desklets", new_enabled) elif self.type == "extension": settings.set_strv("enabled-extensions", new_enabled) def on_more_button_clicked(self, widget): popup = Gtk.Menu() popup.attach_to_widget(widget, None) reset_option = Gtk.MenuItem(_("Reset to defaults")) popup.append(reset_option) reset_option.connect("activate", self.on_reset_defaults) reset_option.show() import_option = Gtk.MenuItem(_("Import from a file")) popup.append(import_option) import_option.connect("activate", self.on_import) import_option.show() export_option = Gtk.MenuItem(_("Export to a file")) popup.append(export_option) export_option.connect("activate", self.on_export) export_option.show() popup.popup(None, None, None, None, 0, 0) def on_reset_defaults(self, popup): self.setting_factories[self.current_id].reset_to_defaults() def on_import(self, popup): dialog = Gtk.FileChooserDialog( _("Select a JSON file to import"), None, Gtk.FileChooserAction.OPEN, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) filter_text = Gtk.FileFilter() filter_text.add_pattern("*.json") filter_text.set_name(_("JSON files")) dialog.add_filter(filter_text) response = dialog.run() if response == Gtk.ResponseType.OK: filename = dialog.get_filename() self.setting_factories[self.current_id].load_from_file(filename) dialog.destroy() def on_export(self, popup): dialog = Gtk.FileChooserDialog( _("Select or enter file to export to"), None, Gtk.FileChooserAction.SAVE, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_SAVE, Gtk.ResponseType.ACCEPT)) dialog.set_do_overwrite_confirmation(True) filter_text = Gtk.FileFilter() filter_text.add_pattern("*.json") filter_text.set_name(_("JSON files")) dialog.add_filter(filter_text) response = dialog.run() if response == Gtk.ResponseType.ACCEPT: filename = dialog.get_filename() if ".json" not in filename: filename = filename + ".json" self.setting_factories[self.current_id].export_to_file(filename) dialog.destroy()
class XletSetting: def __init__(self, uuid, parent, _type): self.parent = parent self.type = _type self.current_id = None self.builder = Gtk.Builder() self.builder.add_from_file("/usr/lib/cinnamon-settings/bin/xlet-settings.ui") self.content = self.builder.get_object("content") self.back_to_list_button = self.builder.get_object("back_to_list") self.highlight_button = self.builder.get_object("highlight_button") self.more_button = self.builder.get_object("more_button") self.remove_button = self.builder.get_object("remove_xlet") self.uuid = uuid self.content.connect("hide", self.on_hide) self.applet_meta = {} self.applet_settings = collections.OrderedDict() self.setting_factories = collections.OrderedDict() self.load_applet_data (self.uuid) if "icon" in self.applet_meta: image = Gtk.Image().new_from_icon_name(self.applet_meta["icon"], Gtk.IconSize.BUTTON) self.back_to_list_button.set_image(image) self.back_to_list_button.get_property('image').set_padding(5, 0) self.back_to_list_button.set_label(self.applet_meta["name"]) self.back_to_list_button.set_tooltip_text(_("Back to list")) self.more_button.set_tooltip_text(_("More actions...")) self.remove_button.set_tooltip_text(_("Remove the current instance of this %s") % self.type) self.highlight_button.set_tooltip_text(_("Momentarily highlight the %s on your desktop") % self.type) if len(self.applet_settings.keys()) > 1: self.build_notebook() else: self.build_single() self.back_to_list_button.connect("clicked", self.on_back_to_list_button_clicked) if self.type != "extension": self.highlight_button.connect("clicked", self.on_highlight_button_clicked) self.highlight_button.show() else: self.highlight_button.hide() self.more_button.connect("clicked", self.on_more_button_clicked) self.remove_button.connect("clicked", self.on_remove_button_clicked) def show (self): self.content.show_all() try: self.back_to_list_button.get_property('image').show() except: pass def on_hide (self, widget): self.content.hide() self.content.destroy() self.applet_meta = None self.applet_settings = None for _id in self.setting_factories.keys(): self.setting_factories[_id].pause_monitor() self.setting_factories = None def load_applet_data (self, uuid): found = self.get_meta_data_for_applet("/usr/share/cinnamon/%ss/%s" % (self.type, uuid)) if not found: found = self.get_meta_data_for_applet("%s/.local/share/cinnamon/%ss/%s" % (home, self.type, uuid)) if not found: print("Could not find %s metadata - are you sure it's installed correctly?" % self.type) return found = self.get_settings_for_applet("%s/.cinnamon/configs/%s" % (home, uuid)) if not found: print("Could not find any instance settings data for this %s - are you sure it is loaded, and supports settings?" % self.type) def get_meta_data_for_applet(self, path): if os.path.exists(path) and os.path.isdir(path): if os.path.exists("%s/metadata.json" % path): raw_data = open("%s/metadata.json" % path).read() self.applet_meta = json.loads(raw_data.decode('utf-8')) return True return False def get_settings_for_applet(self, path): if "max-instances" in self.applet_meta: self.multi_instance = int(self.applet_meta["max-instances"]) > 1 else: self.multi_instance = False if os.path.exists(path) and os.path.isdir(path): instances = os.listdir(path) if len(instances) != 0: for instance in instances: raw_data = open("%s/%s" % (path, instance)).read() try: js = json.loads(raw_data.decode('utf-8'), object_pairs_hook=collections.OrderedDict) except: raise Exception("Failed to parse settings JSON data for %s %s" % (self.type, self.uuid)) instance_id = instance.split(".json")[0] self.applet_settings[instance_id] = js self.setting_factories[instance_id] = XletSettingsWidgets.Factory("%s/%s" % (path, instance), instance_id, self.multi_instance, self.uuid) return True else: raise Exception("Could not find any active setting files for %s %s" % (self.type, self.uuid)) return False def build_single(self): self.nb = None self.view = SectionBg() self.content_box = Gtk.VBox() self.view.add(self.content_box) self.content_box.set_border_width(5) for instance_key in self.applet_settings.keys(): for setting_key in self.applet_settings[instance_key].keys(): if setting_key == "__md5__" or self.applet_settings[instance_key][setting_key]["type"] == "generic": continue self.setting_factories[instance_key].create(setting_key, self.applet_settings[instance_key][setting_key]["type"], self.uuid) widgets = self.setting_factories[instance_key].widgets for widget_key in widgets.keys(): if widgets[widget_key].get_indented(): indent = XletSettingsWidgets.IndentedHBox() indent.add_fill(widgets[widget_key]) self.content_box.pack_start(indent, False, False, 2) else: self.content_box.pack_start(widgets[widget_key], False, False, 2) if len(widgets[widget_key].dependents) > 0: widgets[widget_key].update_dependents() self.current_id = instance_key self.content.pack_start(self.view, True, True, 2) def build_notebook(self): self.nb = Gtk.Notebook() i = 0 target_instance = -1 target_page = -1 if len(sys.argv) > 3: target_instance = sys.argv[3] for instance_key in self.applet_settings.keys(): view = Gtk.ScrolledWindow() content_box = Gtk.VBox() view.add_with_viewport(content_box) content_box.set_border_width(5) for setting_key in self.applet_settings[instance_key].keys(): if setting_key == "__md5__" or self.applet_settings[instance_key][setting_key]["type"] == "generic": continue self.setting_factories[instance_key].create(setting_key, self.applet_settings[instance_key][setting_key]["type"], self.uuid) widgets = self.setting_factories[instance_key].widgets for widget_key in widgets.keys(): if widgets[widget_key].get_indented(): indent = XletSettingsWidgets.IndentedHBox() indent.add_fill(widgets[widget_key]) content_box.pack_start(indent, False, False, 2) else: content_box.pack_start(widgets[widget_key], False, False, 2) if len(widgets[widget_key].dependents) > 0: widgets[widget_key].update_dependents() view.show() self.nb.append_page(view, Gtk.Label.new(_("Instance %d") % (i + 1))) view.key = instance_key if view.key == target_instance: target_page = i i += 1 self.content.pack_start(self.nb, True, True, 2) self.nb.set_scrollable(True) if target_page != -1: self.nb.set_current_page(target_page) self.nb.connect("switch-page", self.on_page_changed) def on_page_changed(self, nb, page, num): self.current_id = page.key def on_highlight_button_clicked(self, widget): session_bus = dbus.SessionBus() cinnamon_dbus = session_bus.get_object("org.Cinnamon", "/org/Cinnamon") highlight_applet = cinnamon_dbus.get_dbus_method('highlightApplet', 'org.Cinnamon') highlight_applet(self.current_id, self.multi_instance) def on_back_to_list_button_clicked(self, widget): self.parent._close_configure(self) def on_remove_button_clicked(self, widget): settings = Gio.Settings.new("org.cinnamon") if self.type == "applet": enabled_xlets = settings.get_strv("enabled-applets") elif self.type == "desklet": enabled_xlets = settings.get_strv("enabled-desklets") elif self.type == "extension": enabled_xlets = settings.get_strv("enabled-extensions") else: return new_enabled = [] for xlet in enabled_xlets: if self.uuid not in xlet: new_enabled.append(xlet) elif self.multi_instance and self.current_id not in xlet: new_enabled.append(xlet) if self.nb is None or (self.nb is not None and self.nb.get_n_pages() == 1): self.parent._close_configure(self) else: current_index = self.nb.get_current_page() tab = self.nb.get_nth_page(current_index) self.setting_factories[self.current_id].pause_monitor() self.nb.remove_page(current_index) tab.destroy() self.nb.set_current_page(0) if self.type == "applet": settings.set_strv("enabled-applets", new_enabled) elif self.type == "desklet": settings.set_strv("enabled-desklets", new_enabled) elif self.type == "extension": settings.set_strv("enabled-extensions", new_enabled) def on_more_button_clicked(self, widget): popup = Gtk.Menu() popup.attach_to_widget(widget, None) reset_option = Gtk.MenuItem(_("Reset to defaults")) popup.append(reset_option) reset_option.connect("activate", self.on_reset_defaults) reset_option.show() import_option = Gtk.MenuItem(_("Import from a file")) popup.append(import_option) import_option.connect("activate", self.on_import) import_option.show() export_option = Gtk.MenuItem(_("Export to a file")) popup.append(export_option) export_option.connect("activate", self.on_export) export_option.show() popup.popup(None, None, None, None, 0, 0) def on_reset_defaults(self, popup): self.setting_factories[self.current_id].reset_to_defaults() def on_import(self, popup): dialog = Gtk.FileChooserDialog(_("Select a JSON file to import"), None, Gtk.FileChooserAction.OPEN, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) filter_text = Gtk.FileFilter() filter_text.add_pattern("*.json") filter_text.set_name(_("JSON files")) dialog.add_filter(filter_text) response = dialog.run() if response == Gtk.ResponseType.OK: filename = dialog.get_filename() self.setting_factories[self.current_id].load_from_file(filename) dialog.destroy() def on_export(self, popup): dialog = Gtk.FileChooserDialog(_("Select or enter file to export to"), None, Gtk.FileChooserAction.SAVE, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_SAVE, Gtk.ResponseType.ACCEPT)) dialog.set_do_overwrite_confirmation(True) filter_text = Gtk.FileFilter() filter_text.add_pattern("*.json") filter_text.set_name(_("JSON files")) dialog.add_filter(filter_text) response = dialog.run() if response == Gtk.ResponseType.ACCEPT: filename = dialog.get_filename() if ".json" not in filename: filename = filename + ".json" self.setting_factories[self.current_id].export_to_file(filename) dialog.destroy()