-
Notifications
You must be signed in to change notification settings - Fork 808
Add early exit to xlet-settings if no instances exist, handle adding/removing xlets while xlet-settings is open. #13055
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -95,13 +95,21 @@ def __init__(self, args): | |||||
| self.type = args.type | ||||||
| self.uuid = args.uuid | ||||||
| self.tab = 0 | ||||||
| self.instance_info = [] | ||||||
| self.instance_id = str(args.id) | ||||||
| if args.tab is not None: | ||||||
| self.tab = int(args.tab) | ||||||
|
|
||||||
| self.selected_instance = None | ||||||
| self.gsettings = Gio.Settings.new("org.cinnamon") | ||||||
| self.monitors = {} | ||||||
| self.g_directories = [] | ||||||
| self.custom_modules = {} | ||||||
| if self.type == "applet": changed_key = "enabled-applets" | ||||||
| elif self.type == "desklet": changed_key = "enabled-desklets" | ||||||
| else: changed_key = None | ||||||
| if changed_key: | ||||||
| self.gsettings.connect("changed::" + changed_key, lambda *args: self.on_enabled_xlets_changed(changed_key, *args)) | ||||||
|
|
||||||
| self.load_xlet_data() | ||||||
| self.build_window() | ||||||
|
|
@@ -128,7 +136,7 @@ def _on_proxy_ready (self, obj, result, data=None): | |||||
| proxy = None | ||||||
|
|
||||||
| if proxy: | ||||||
| proxy.highlightXlet('(ssb)', self.uuid, self.selected_instance["id"], True) | ||||||
| self.highlight_xlet(self.selected_instance, True) | ||||||
|
|
||||||
| def load_xlet_data (self): | ||||||
| self.xlet_dir = "/usr/share/cinnamon/%ss/%s" % (self.type, self.uuid) | ||||||
|
|
@@ -242,18 +250,22 @@ def check_sizing(widget, data=None): | |||||
| self.next_button.connect("clicked", self.next_instance) | ||||||
|
|
||||||
| def load_instances(self): | ||||||
| self.instance_info = [] | ||||||
| path = Path(os.path.join(settings_dir, self.uuid)) | ||||||
| old_path = Path("%s/.cinnamon/configs/%s" % (home, self.uuid)) | ||||||
| instances = 0 | ||||||
| for p in path, old_path: | ||||||
| if not p.exists(): continue | ||||||
| self.g_directories.append(Gio.File.new_for_path(str(p))) | ||||||
|
|
||||||
| new_items = os.listdir(path) if path.exists() else [] | ||||||
| old_items = os.listdir(old_path) if old_path.exists() else [] | ||||||
| dir_items = sorted(new_items + old_items) | ||||||
|
|
||||||
| try: | ||||||
| multi_instance = int(self.xlet_meta["max-instances"]) != 1 | ||||||
| except (KeyError, ValueError): | ||||||
| multi_instance = False | ||||||
|
|
||||||
| enabled = [x.split(":") for x in self.gsettings.get_strv('enabled-%ss' % self.type)] | ||||||
| for item in dir_items: | ||||||
| # ignore anything that isn't json | ||||||
| if item[-5:] != ".json": | ||||||
|
|
@@ -271,66 +283,82 @@ def load_instances(self): | |||||
| continue # multi-instance should have file names of the form [instance-id].json | ||||||
|
|
||||||
| instance_exists = False | ||||||
| enabled = self.gsettings.get_strv('enabled-%ss' % self.type) | ||||||
| for definition in enabled: | ||||||
| if self.uuid in definition and instance_id in definition.split(':'): | ||||||
| if self.uuid in definition and instance_id in definition: | ||||||
| instance_exists = True | ||||||
| break | ||||||
|
|
||||||
| if not instance_exists: | ||||||
| continue | ||||||
|
|
||||||
| settings = JSONSettingsHandler(os.path.join(path if item in new_items else old_path, item), self.notify_dbus) | ||||||
| settings.instance_id = instance_id | ||||||
| instance_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) | ||||||
| self.instance_stack.add_named(instance_box, instance_id) | ||||||
|
|
||||||
| info = {"settings": settings, "id": instance_id} | ||||||
| self.instance_info.append(info) | ||||||
| config_path = os.path.join(path if item in new_items else old_path, item) | ||||||
| self.create_settings_page(config_path) | ||||||
|
|
||||||
| if not self.instance_info: | ||||||
| print(f"No instances were found for {self.uuid}. Exiting...") | ||||||
| sys.exit() | ||||||
|
|
||||||
| self.next_button.set_no_show_all(True) | ||||||
| self.prev_button.set_no_show_all(True) | ||||||
| self.show_prev_next_buttons() if self.has_multiple_instances() else self.hide_prev_next_buttons() | ||||||
|
|
||||||
| def create_settings_page(self, config_path): | ||||||
| instance_id = os.path.basename(config_path)[:-5] | ||||||
| if self.instance_stack.get_child_by_name(instance_id) is not None: return | ||||||
| settings = JSONSettingsHandler(config_path, self.notify_dbus) | ||||||
| settings.instance_id = instance_id | ||||||
| instance_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) | ||||||
| self.instance_stack.add_named(instance_box, instance_id) | ||||||
| info = {"settings": settings, "id": instance_id} | ||||||
| self.instance_info.append(info) | ||||||
| settings_map = settings.get_settings() | ||||||
| first_key = next(iter(settings_map.values())) | ||||||
|
|
||||||
| settings_map = settings.get_settings() | ||||||
| first_key = next(iter(settings_map.values())) | ||||||
| try: | ||||||
| for setting in settings_map: | ||||||
| if setting == "__md5__": | ||||||
| continue | ||||||
| for key in settings_map[setting]: | ||||||
| if key in ("description", "tooltip", "units"): | ||||||
| try: | ||||||
| settings_map[setting][key] = translate(self.uuid, settings_map[setting][key]) | ||||||
| except (KeyError, ValueError): | ||||||
| traceback.print_exc() | ||||||
| elif key in "options": | ||||||
| new_opt_data = collections.OrderedDict() | ||||||
| opt_data = settings_map[setting][key] | ||||||
| for option in opt_data: | ||||||
| if opt_data[option] == "custom": | ||||||
| continue | ||||||
| new_opt_data[translate(self.uuid, option)] = opt_data[option] | ||||||
| settings_map[setting][key] = new_opt_data | ||||||
| elif key in "columns": | ||||||
| columns_data = settings_map[setting][key] | ||||||
| for column in columns_data: | ||||||
| column["title"] = translate(self.uuid, column["title"]) | ||||||
| finally: | ||||||
| # if a layout is not explicitly defined, generate the settings | ||||||
| # widgets based on the order they occur | ||||||
| if first_key["type"] == "layout": | ||||||
| self.build_with_layout(settings_map, info, instance_box, first_key) | ||||||
| else: | ||||||
| self.build_from_order(settings_map, info, instance_box, first_key) | ||||||
|
|
||||||
| try: | ||||||
| for setting in settings_map: | ||||||
| if setting == "__md5__": | ||||||
| continue | ||||||
| for key in settings_map[setting]: | ||||||
| if key in ("description", "tooltip", "units"): | ||||||
| try: | ||||||
| settings_map[setting][key] = translate(self.uuid, settings_map[setting][key]) | ||||||
| except (KeyError, ValueError): | ||||||
| traceback.print_exc() | ||||||
| elif key in "options": | ||||||
| new_opt_data = collections.OrderedDict() | ||||||
| opt_data = settings_map[setting][key] | ||||||
| for option in opt_data: | ||||||
| if opt_data[option] == "custom": | ||||||
| continue | ||||||
| new_opt_data[translate(self.uuid, option)] = opt_data[option] | ||||||
| settings_map[setting][key] = new_opt_data | ||||||
| elif key in "columns": | ||||||
| columns_data = settings_map[setting][key] | ||||||
| for column in columns_data: | ||||||
| column["title"] = translate(self.uuid, column["title"]) | ||||||
| finally: | ||||||
| # if a layout is not explicitly defined, generate the settings | ||||||
| # widgets based on the order they occur | ||||||
| if first_key["type"] == "layout": | ||||||
| self.build_with_layout(settings_map, info, instance_box, first_key) | ||||||
| else: | ||||||
| self.build_from_order(settings_map, info, instance_box, first_key) | ||||||
| if self.selected_instance is None: | ||||||
| self.selected_instance = info | ||||||
| if "stack" in info: | ||||||
| self.stack_switcher.set_stack(info["stack"]) | ||||||
|
|
||||||
| if self.selected_instance is None: | ||||||
| self.selected_instance = info | ||||||
| if "stack" in info: | ||||||
| self.stack_switcher.set_stack(info["stack"]) | ||||||
| def has_multiple_instances(self): | ||||||
| return len(self.instance_info) > 1 | ||||||
|
|
||||||
| instances += 1 | ||||||
| def hide_prev_next_buttons(self): | ||||||
| self.prev_button.hide() | ||||||
| self.next_button.hide() | ||||||
|
|
||||||
| if instances < 2: | ||||||
| self.prev_button.set_no_show_all(True) | ||||||
| self.next_button.set_no_show_all(True) | ||||||
| def show_prev_next_buttons(self): | ||||||
| self.prev_button.show() | ||||||
| self.next_button.show() | ||||||
|
|
||||||
| def build_with_layout(self, settings_map, info, box, first_key): | ||||||
| layout = first_key | ||||||
|
|
@@ -460,26 +488,95 @@ def set_instance(self, info): | |||||
| else: | ||||||
| info["stack"].set_visible_child(children[0]) | ||||||
| if proxy: | ||||||
| proxy.highlightXlet('(ssb)', self.uuid, self.selected_instance["id"], False) | ||||||
| proxy.highlightXlet('(ssb)', self.uuid, info["id"], True) | ||||||
| old_info = self.selected_instance | ||||||
| new_info = info | ||||||
| self.highlight_xlet(old_info, False) | ||||||
| self.highlight_xlet(new_info, True) | ||||||
| self.selected_instance = info | ||||||
|
|
||||||
| def highlight_xlet(self, info, highlighted): | ||||||
| try: | ||||||
| proxy.highlightXlet('(ssb)', self.uuid, info["id"], highlighted) | ||||||
| except: | ||||||
|
||||||
| except: | |
| except Exception: |
Copilot
AI
Nov 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Parameter default value should not have spaces around the equals sign. Should be positive_direction=True per PEP 8.
| def get_next_instance(self, positive_direction = True): | |
| def get_next_instance(self, positive_direction=True): |
Copilot
AI
Nov 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Logic error in exit condition. This checks if total instances (current + added) equals removed count, which would exit when there are still instances remaining. Should be: if len(current_ids) - len(removed_indices) + len(added_ids) == 0: or equivalently if len(new_ids) == 0:
| if len(current_ids) + len(added_ids) == len(removed_indices): | |
| if len(new_ids) == 0: |
Copilot
AI
Nov 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 'continue' statement after creating a settings page will skip monitoring setup for remaining directories. If the config file exists in the first directory but not others, monitors won't be created. Remove the 'continue' or add 'break' instead to stop checking other directories once file is found.
| continue | |
| break |
Copilot
AI
Nov 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] Unnecessary parentheses around the condition. Python style guide recommends omitting them for simple conditions.
| if (selected_removed_index != -1): | |
| if selected_removed_index != -1: |
Copilot
AI
Nov 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra space before colon. Should be CHANGES_DONE_HINT: without space before the colon.
| if event_type != Gio.FileMonitorEvent.CHANGES_DONE_HINT : return | |
| if event_type != Gio.FileMonitorEvent.CHANGES_DONE_HINT: return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential crash if
settings.get_settings()returns None (when config file doesn't exist). The code doesn't check for None before callingnext(iter(settings_map.values())), which would raise an error. Should add:if settings_map is None: returnafter line 314.