fix: dropdown callbacks, singleton about dialog, config-driven settings sidebar, switcher cache eviction

This commit is contained in:
sankalp committed 2026-08-01 20:03:46 +05:45
1 parent 456545e6a6
commit 09f792078f
4 files changed
+63 -200

No files matched your search

+2 -2
View File
@@ -68,9 +68,9 @@ class ModusDropdown:
return item
@staticmethod
def _activate(callback, command, *_):
def _activate(callback, command, *args):
if callback:
callback()
callback(*args)
if command:
thread(run_command, ["sh", "-c", command], timeout=30)
+18 -2
View File
@@ -23,13 +23,29 @@ def has_active_window():
return app_name and app_name != "Modus"
_about_app_window = None
def _reset_about_app_window():
global _about_app_window
_about_app_window = None
def show_about_app(_=None):
global _about_app_window
if not has_active_window():
return
app_name = modus_service.current_active_app_name
wmclass = getattr(modus_service, "current_active_wm_class", "")
about_window = AboutApp(app_name=app_name, wmclass=wmclass)
about_window.toggle(None)
window = _about_app_window
if window is None or getattr(window, "app_name", None) != app_name:
if window is not None:
window.destroy()
window = AboutApp(app_name=app_name, wmclass=wmclass)
window.connect("destroy", lambda *_: _reset_about_app_window())
_about_app_window = window
window.toggle(None)
# Menu factories
+42 -196
View File
@@ -250,6 +250,21 @@ class SettingsPage(ScrolledWindow):
self._container = container
SECTION_ICONS = {
"general": "misc/logo.svg",
"dock": "misc/control.svg",
"panel": "misc/control-center.svg",
"switcher": "screencapture/window.svg",
"notification": "notifications/notification-active.svg",
}
DEFAULT_SECTION_ICON = "misc/logo.svg"
def humanize_key(key):
return " ".join(word.capitalize() for word in key.replace("_", " ").split())
class SettingsWindow(Gtk.Window):
def __init__(self, **kwargs):
super().__init__(title="Modus Settings", **kwargs)
@@ -275,31 +290,15 @@ class SettingsWindow(Gtk.Window):
v_expand=True,
)
self.pages = {
"general": self._create_general_page(),
"dock": self._create_dock_page(),
"panel": self._create_panel_page(),
"notifications": self._create_notifications_page(),
}
for name, page in self.pages.items():
self.stack.add_named(page, name)
self.pages = {}
self.sidebar_buttons = {}
self.sidebar_buttons["general"] = self._create_sidebar_button(
"General", "general", "misc/logo.svg"
)
self.sidebar_buttons["dock"] = self._create_sidebar_button(
"Dock", "dock", "misc/control.svg"
)
self.sidebar_buttons["panel"] = self._create_sidebar_button(
"Panel", "panel", "misc/control-center.svg"
)
self.sidebar_buttons["notifications"] = self._create_sidebar_button(
"Notifications", "notifications", "notifications/notification-active.svg"
)
self.set_page("general")
for section, values in config().get_all().items():
if not isinstance(values, dict):
continue
self._add_section(section, values)
self.set_page(next(iter(self.pages)))
self.sidebar = Box(
name="settings-sidebar",
@@ -349,182 +348,29 @@ class SettingsWindow(Gtk.Window):
else:
btn.remove_style_class("active")
def _create_general_page(self):
return SettingsPage(
"General Settings",
[
SettingsRow(
"Debug Mode",
SettingsSwitch("general.debug"),
"Enable verbose logging for development",
),
SettingsRow(
"Weather Location",
SettingsEntry("general.weather_location"),
"City name for weather updates",
),
SettingsRow(
"Keyboard Layouts",
SettingsList("general.keyboard_layouts"),
"Manage active keyboard input languages",
),
SettingsRow(
"Hide Special Workspace",
SettingsSwitch("panel.hide_special_workspace"),
"Don't show special workspace in indicators",
),
SettingsRow(
"Night Light Temperature",
SettingsEntry("panel.night_light_temperature"),
"Color temperature in Kelvin (e.g. 4500)",
),
SettingsRow(
"Live Preview",
SettingsSwitch("switcher.live_preview"),
"Show live window previews in switcher",
),
SettingsRow(
"Preview Delay (ms)",
SettingsEntry("switcher.live_preview_delay_ms"),
"Delay before live preview appears",
),
],
def _add_section(self, section, values):
page = self._build_page(section, values)
self.pages[section] = page
self.stack.add_named(page, section)
self.sidebar_buttons[section] = self._create_sidebar_button(
humanize_key(section),
section,
SECTION_ICONS.get(section, DEFAULT_SECTION_ICON),
)
def _create_dock_page(self):
return SettingsPage(
"Dock Settings",
[
SettingsRow(
"Enabled",
SettingsSwitch("dock.enabled"),
"Show the application dock",
),
SettingsRow(
"Auto Hide",
SettingsSwitch("dock.auto_hide"),
"Hide dock when not in use",
),
SettingsRow(
"Always Occluded",
SettingsSwitch("dock.always_occluded"),
"Keep dock behind other windows",
),
SettingsRow(
"Icon Size",
SettingsEntry("dock.icon_size"),
"Size of dock icons in pixels",
),
SettingsRow(
"Hide Special Apps",
SettingsSwitch("dock.hide_special_workspace_apps"),
"Hide apps from special workspace in dock",
),
SettingsRow(
"Hover Scale",
SettingsEntry("dock.hover_scale"),
"Icon scale on hover (1.0 = off, 1.6 = default, 2.0 = max)",
),
],
)
def _build_page(self, section, values):
rows = []
for key, value in values.items():
widget = self._infer_widget(f"{section}.{key}", value)
rows.append(SettingsRow(humanize_key(key), widget))
return SettingsPage(f"{humanize_key(section)} Settings", rows)
def _create_panel_page(self):
rows = [
SettingsRow(
"Global Menu",
SettingsSwitch("panel.global_menu"),
"Show application menu in the panel",
),
SettingsRow(
"iMac Button",
SettingsSwitch("panel.imac_button"),
),
SettingsRow(
"Systray",
SettingsSwitch("panel.systray"),
),
SettingsRow(
"Control Center",
SettingsSwitch("panel.control_center"),
),
SettingsRow(
"Search",
SettingsSwitch("panel.search"),
),
SettingsRow(
"Network",
SettingsSwitch("panel.network"),
),
SettingsRow(
"Battery",
SettingsSwitch("panel.battery"),
),
SettingsRow(
"Bluetooth",
SettingsSwitch("panel.bluetooth"),
),
SettingsRow(
"Date & Time",
SettingsSwitch("panel.date_time"),
),
SettingsRow(
"Workspace Indicator",
SettingsSwitch("panel.workspace_indicator"),
),
SettingsRow(
"Notification Center",
SettingsSwitch("panel.notification_center"),
),
SettingsRow(
"Custom Mods",
SettingsSwitch("panel.custom_mods"),
"Enable custom Hyprland mods in panel",
),
SettingsRow(
"Window Switcher",
SettingsSwitch("switcher.window_switcher"),
"Enable Alt+Tab window switcher",
),
SettingsRow(
"OSD",
SettingsSwitch("panel.osd"),
"Enable on-screen display for volume/brightness",
),
SettingsRow(
"Wallpapers Directory",
SettingsEntry("general.wallpapers_dir"),
"Path to wallpapers folder",
),
SettingsRow(
"Systray Ignore",
SettingsList("panel.systray_ignore"),
"Icons to hide from the system tray",
),
]
return SettingsPage("Panel Settings", rows)
def _create_notifications_page(self):
return SettingsPage(
"Notification Settings",
[
SettingsRow(
"Timeout",
SettingsEntry("notification.timeout"),
"How long notifications stay on screen (e.g. 5s)",
),
SettingsRow(
"Ignored Apps",
SettingsList("notification.ignored_apps"),
"Apps that won't show notifications",
),
SettingsRow(
"Limited History",
SettingsList("notification.limited_apps_history"),
"Apps with only the latest notification shown",
),
],
)
def _infer_widget(self, full_key, value):
if isinstance(value, bool):
return SettingsSwitch(full_key)
if isinstance(value, list):
return SettingsList(full_key)
return SettingsEntry(full_key)
def toggle(self):
if getattr(self, "_destroyed", False):
+1
View File
@@ -165,6 +165,7 @@ class ApplicationSwitcher(Window):
def _get_pixbuf(self, class_name: str) -> GdkPixbuf.Pixbuf | None:
key = (class_name, self.icon_size)
if key in self._pixbuf_cache:
self._pixbuf_cache.move_to_end(key)
return self._pixbuf_cache[key]
if len(self._pixbuf_cache) > 128: