🔧 chore(dock): refactor DockSystemTray to DockComponents and update related changes for consistent naming and structure

This commit is contained in:
sankalp committed 2025-06-07 16:11:30 +05:45
1 parent e1a85413c2
commit a6f47cc548
7 files changed
+550 -863

No files matched your search

-564
View File
@@ -1,564 +0,0 @@
import json
import os
from fabric.hyprland.service import HyprlandEvent
from fabric.hyprland.widgets import (
Language,
WorkspaceButton,
Workspaces,
get_hyprland_connection,
)
from fabric.utils.helpers import exec_shell_command_async
from fabric.widgets.box import Box
from fabric.widgets.button import Button
from fabric.widgets.centerbox import CenterBox
from fabric.widgets.datetime import DateTime
from fabric.widgets.label import Label
from fabric.widgets.revealer import Revealer
from gi.repository import Gdk, Gtk
import config.data as data
import modules.icons as icons
from modules.controls import ControlSmall
from modules.dock import Dock
from modules.metrics import Battery, MetricsSmall, NetworkApplet
from modules.systemtray import SystemTray
from modules.weather import Weather
from widgets.wayland import WaylandWindow as Window
CHINESE_NUMERALS = ["一", "二", "三", "四", "五", "六", "七", "八", "九", "〇"]
# Tooltips
tooltip_apps = f"""<b><u>Launcher</u></b>
<b>• Apps:</b> Type to search.
<b>• Calculator [Prefix "="]:</b> Solve a math expression.
e.g. "=2+2"
<b>• Converter [Prefix ";"]:</b> Convert between units.
e.g. ";100 USD to EUR", ";10 km to miles"
<b>• Special Commands [Prefix ":"]:</b>
:update - Open {data.APP_NAME_CAP}'s updater.
:d - Open Dashboard.
:w - Open Wallpapers."""
tooltip_power = """<b>Power Menu</b>"""
tooltip_tools = """<b>Toolbox</b>"""
tooltip_overview = """<b>Overview</b>"""
class Bar(Window):
def __init__(self, **kwargs):
super().__init__(
name="bar",
layer="top",
exclusivity="auto",
visible=True,
all_visible=True,
)
self.anchor_var = ""
self.margin_var = ""
match data.BAR_POSITION:
case "Top":
self.anchor_var = "left top right"
case "Bottom":
self.anchor_var = "left bottom right"
case "Left":
self.anchor_var = "left" if data.CENTERED_BAR else "left top bottom"
case "Right":
self.anchor_var = "right" if data.CENTERED_BAR else "top right bottom"
case _:
self.anchor_var = "left top right"
if data.VERTICAL:
match data.BAR_THEME:
case "Edge":
self.margin_var = "-8px -8px -8px -8px"
case _:
self.margin_var = "-4px -8px -4px -4px"
else:
match data.BAR_THEME:
case "Edge":
self.margin_var = "-8px -8px -8px -8px"
case _:
if data.BAR_POSITION == "Bottom":
self.margin_var = "-8px -4px -4px -4px"
else:
self.margin_var = "-4px -4px -8px -4px"
self.set_anchor(self.anchor_var)
self.set_margin(self.margin_var)
self.notch = kwargs.get("notch", None)
self.component_visibility = data.BAR_COMPONENTS_VISIBILITY
self.dock_instance = None
self.integrated_dock_widget = None
self.workspaces = Workspaces(
name="workspaces",
invert_scroll=True,
empty_scroll=True,
v_align="fill",
orientation="h" if not data.VERTICAL else "v",
spacing=8,
buttons=[
WorkspaceButton(
h_expand=False,
v_expand=False,
h_align="center",
v_align="center",
id=i,
label=None,
style_classes=["vertical"] if data.VERTICAL else None,
)
for i in range(1, 11)
],
)
self.workspaces_num = Workspaces(
name="workspaces-num",
invert_scroll=True,
empty_scroll=True,
v_align="fill",
orientation="h" if not data.VERTICAL else "v",
spacing=0 if not data.BAR_WORKSPACE_USE_CHINESE_NUMERALS else 4,
buttons=[
WorkspaceButton(
h_expand=False,
v_expand=False,
h_align="center",
v_align="center",
id=i,
label=CHINESE_NUMERALS[i - 1]
if data.BAR_WORKSPACE_USE_CHINESE_NUMERALS
and 1 <= i <= len(CHINESE_NUMERALS)
else str(i),
)
for i in range(1, 11)
],
)
self.ws_container = Box(
name="workspaces-container",
children=self.workspaces
if not data.BAR_WORKSPACE_SHOW_NUMBER
else self.workspaces_num,
)
self.button_tools = Button(
name="button-bar",
tooltip_markup=tooltip_tools,
on_clicked=lambda *_: self.tools_menu(),
child=Label(name="button-bar-label", markup=icons.toolbox),
)
self.connection = get_hyprland_connection()
self.button_tools.connect("enter_notify_event", self.on_button_enter)
self.button_tools.connect("leave_notify_event", self.on_button_leave)
self.systray = SystemTray()
self.weather = Weather()
self.network = NetworkApplet()
self.lang_label = Label(name="lang-label")
self.language = Button(
name="language", h_align="center", v_align="center", child=self.lang_label
)
self.on_language_switch()
self.connection.connect("event::activelayout", self.on_language_switch)
self.date_time = DateTime(
name="date-time",
formatters=["%H:%M"] if not data.VERTICAL else ["%H\n%M"],
h_align="center" if not data.VERTICAL else "fill",
v_align="center",
h_expand=True,
v_expand=True,
)
self.button_apps = Button(
name="button-bar",
tooltip_markup=tooltip_apps,
on_clicked=lambda *_: self.search_apps(),
child=Label(name="button-bar-label", markup=icons.apps),
)
self.button_apps.connect("enter_notify_event", self.on_button_enter)
self.button_apps.connect("leave_notify_event", self.on_button_leave)
self.button_power = Button(
name="button-bar",
tooltip_markup=tooltip_power,
on_clicked=lambda *_: self.power_menu(),
child=Label(name="button-bar-label", markup=icons.shutdown),
)
self.button_power.connect("enter_notify_event", self.on_button_enter)
self.button_power.connect("leave_notify_event", self.on_button_leave)
self.button_overview = Button(
name="button-bar",
tooltip_markup=tooltip_overview,
on_clicked=lambda *_: self.overview(),
child=Label(name="button-bar-label", markup=icons.windows),
)
self.button_overview.connect("enter_notify_event", self.on_button_enter)
self.button_overview.connect("leave_notify_event", self.on_button_leave)
self.control = ControlSmall()
self.metrics = MetricsSmall()
self.battery = Battery()
self.apply_component_props()
self.rev_right = [
self.metrics,
self.control,
]
self.revealer_right = Revealer(
name="bar-revealer",
transition_type="slide-left",
child_revealed=True,
child=Box(
name="bar-revealer-box",
orientation="h",
spacing=4,
children=self.rev_right if not data.VERTICAL else None,
),
)
self.boxed_revealer_right = Box(
name="boxed-revealer",
children=[
self.revealer_right,
],
)
self.rev_left = [
self.weather,
self.network,
]
self.revealer_left = Revealer(
name="bar-revealer",
transition_type="slide-right",
child_revealed=True,
child=Box(
name="bar-revealer-box",
orientation="h",
spacing=4,
children=self.rev_left if not data.VERTICAL else None,
),
)
self.boxed_revealer_left = Box(
name="boxed-revealer",
children=[
self.revealer_left,
],
)
self.h_start_children = [
self.button_apps,
self.ws_container,
self.button_overview,
self.boxed_revealer_left,
]
self.h_end_children = [
self.boxed_revealer_right,
self.battery,
self.systray,
self.button_tools,
self.language,
self.date_time,
self.button_power,
]
self.v_start_children = [
self.button_apps,
self.systray,
self.control,
self.network,
self.button_tools,
]
self.v_center_children = [
self.button_overview,
self.ws_container,
self.weather,
]
self.v_end_children = [
self.battery,
self.metrics,
self.language,
self.date_time,
self.button_power,
]
self.v_all_children = []
self.v_all_children.extend(self.v_start_children)
self.v_all_children.extend(self.v_center_children)
self.v_all_children.extend(self.v_end_children)
if (
data.DOCK_ENABLED
and data.BAR_POSITION == "Bottom"
or data.PANEL_THEME == "Panel"
and data.BAR_POSITION in ["Top", "Bottom"]
):
if not data.VERTICAL:
self.dock_instance = Dock(integrated_mode=True)
self.integrated_dock_widget = self.dock_instance.wrapper
is_centered_bar = data.VERTICAL and getattr(data, "CENTERED_BAR", False)
bar_center_actual_children = None
if self.integrated_dock_widget is not None:
bar_center_actual_children = self.integrated_dock_widget
elif data.VERTICAL:
bar_center_actual_children = Box(
orientation=Gtk.Orientation.VERTICAL,
spacing=4,
children=self.v_all_children
if is_centered_bar
else self.v_center_children,
)
self.bar_inner = CenterBox(
name="bar-inner",
orientation=Gtk.Orientation.HORIZONTAL
if not data.VERTICAL
else Gtk.Orientation.VERTICAL,
h_align="fill",
v_align="fill",
start_children=None
if is_centered_bar
else Box(
name="start-container",
spacing=4,
orientation=Gtk.Orientation.HORIZONTAL
if not data.VERTICAL
else Gtk.Orientation.VERTICAL,
children=self.h_start_children
if not data.VERTICAL
else self.v_start_children,
),
center_children=bar_center_actual_children,
end_children=None
if is_centered_bar
else Box(
name="end-container",
spacing=4,
orientation=Gtk.Orientation.HORIZONTAL
if not data.VERTICAL
else Gtk.Orientation.VERTICAL,
children=self.h_end_children
if not data.VERTICAL
else self.v_end_children,
),
)
self.children = self.bar_inner
self.hidden = False
self.themed_children = [
self.button_apps,
self.button_overview,
self.button_power,
self.button_tools,
self.language,
self.date_time,
self.ws_container,
self.weather,
self.network,
self.battery,
self.metrics,
self.systray,
self.control,
]
if self.integrated_dock_widget:
self.themed_children.append(self.integrated_dock_widget)
current_theme = data.BAR_THEME
theme_classes = ["pills", "dense", "edge", "edgecenter"]
for tc in theme_classes:
self.bar_inner.remove_style_class(tc)
self.style = None
match current_theme:
case "Pills":
self.style = "pills"
case "Dense":
self.style = "dense"
case "Edge":
if data.VERTICAL and data.CENTERED_BAR:
self.style = "edgecenter"
else:
self.style = "edge"
case _:
self.style = "pills"
self.bar_inner.add_style_class(self.style)
if self.integrated_dock_widget and hasattr(
self.integrated_dock_widget, "add_style_class"
):
for theme_class_to_remove in ["pills", "dense", "edge"]:
style_context = self.integrated_dock_widget.get_style_context()
if style_context.has_class(theme_class_to_remove):
self.integrated_dock_widget.remove_style_class(
theme_class_to_remove
)
self.integrated_dock_widget.add_style_class(self.style)
if data.BAR_THEME == "Dense" or data.BAR_THEME == "Edge":
for child in self.themed_children:
if hasattr(child, "add_style_class"):
child.add_style_class("invert")
match data.BAR_POSITION:
case "Top":
self.bar_inner.add_style_class("top")
case "Bottom":
self.bar_inner.add_style_class("bottom")
case "Left":
self.bar_inner.add_style_class("left")
case "Right":
self.bar_inner.add_style_class("right")
case _:
self.bar_inner.add_style_class("top")
if data.VERTICAL:
self.bar_inner.add_style_class("vertical")
self.systray._update_visibility()
self.chinese_numbers()
def apply_component_props(self):
components = {
"button_apps": self.button_apps,
"systray": self.systray,
"control": self.control,
"network": self.network,
"button_tools": self.button_tools,
"button_overview": self.button_overview,
"ws_container": self.ws_container,
"weather": self.weather,
"battery": self.battery,
"metrics": self.metrics,
"language": self.language,
"date_time": self.date_time,
"button_power": self.button_power,
}
for component_name, widget in components.items():
if component_name in self.component_visibility:
widget.set_visible(self.component_visibility[component_name])
def toggle_component_visibility(self, component_name):
components = {
"button_apps": self.button_apps,
"systray": self.systray,
"control": self.control,
"network": self.network,
"button_tools": self.button_tools,
"button_overview": self.button_overview,
"ws_container": self.ws_container,
"weather": self.weather,
"battery": self.battery,
"metrics": self.metrics,
"language": self.language,
"date_time": self.date_time,
"button_power": self.button_power,
}
if component_name in components and component_name in self.component_visibility:
self.component_visibility[component_name] = not self.component_visibility[
component_name
]
components[component_name].set_visible(
self.component_visibility[component_name]
)
config_file = os.path.expanduser(
f"~/.config/{data.APP_NAME}/config/config.json"
)
if os.path.exists(config_file):
try:
with open(config_file, "r") as f:
config = json.load(f)
config[f"bar_{component_name}_visible"] = self.component_visibility[
component_name
]
with open(config_file, "w") as f:
json.dump(config, f, indent=4)
except Exception as e:
print(f"Error updating config file: {e}")
return self.component_visibility[component_name]
return None
def on_button_enter(self, widget, event):
window = widget.get_window()
if window:
window.set_cursor(Gdk.Cursor.new_from_name(widget.get_display(), "hand2"))
def on_button_leave(self, widget, event):
window = widget.get_window()
if window:
window.set_cursor(None)
def on_button_clicked(self, *args):
exec_shell_command_async("notify-send 'Botón presionado' '¡Funciona!'")
def search_apps(self):
if self.notch:
self.notch.open_notch("launcher")
def overview(self):
if self.notch:
self.notch.open_notch("overview")
def power_menu(self):
if self.notch:
self.notch.open_notch("power")
def tools_menu(self):
if self.notch:
self.notch.open_notch("tools")
def on_language_switch(self, _=None, event: HyprlandEvent = None):
lang_data = (
event.data[1]
if event and event.data and len(event.data) > 1
else Language().get_label()
)
self.language.set_tooltip_text(lang_data)
if not data.VERTICAL:
self.lang_label.set_label(lang_data[:3].upper())
else:
self.lang_label.add_style_class("icon")
self.lang_label.set_markup(icons.keyboard)
def toggle_hidden(self):
self.hidden = not self.hidden
if self.hidden:
self.bar_inner.add_style_class("hidden")
else:
self.bar_inner.remove_style_class("hidden")
def chinese_numbers(self):
if data.BAR_WORKSPACE_USE_CHINESE_NUMERALS:
self.workspaces_num.add_style_class("chinese")
else:
self.workspaces_num.remove_style_class("chinese")
+7 -8
View File
@@ -45,13 +45,12 @@
"corners_visible": false,
"dock_theme": "Pills",
"notif_pos": "Top",
"bar_workspace_visible": true,
"bar_metrics_visible": true,
"bar_date_time_visible": true,
"bar_battery_visible": true,
"bar_controls_visible": true,
"bar_indicators_visible": true,
"bar_systray_visible": true,
"dock_workspace_visible": true,
"dock_metrics_visible": true,
"dock_date_time_visible": true,
"dock_battery_visible": true,
"dock_controls_visible": true,
"dock_indicators_visible": true,
"metrics_visible": {
"cpu": true,
"ram": true,
@@ -60,4 +59,4 @@
"gpu": false
},
"metrics_disks": []
}
}
+11 -4
View File
@@ -34,7 +34,6 @@ MATUGEN_STATE_FILE = os.path.join(CONFIG_DIR, "matugen")
DOCK_THEME = "Pills"
def load_config():
"""Load the configuration from config.json"""
config_path = os.path.expanduser(f"~/{APP_NAME_CAP}/config/config.json")
@@ -74,7 +73,10 @@ if os.path.exists(CONFIG_FILE):
}
METRICS_DISKS = config.get("metrics_disks", ["/"])
METRICS_VISIBLE = config.get("metrics_visible", {"cpu": True, "ram": True, "disk": True, "swap": True, "gpu": False})
METRICS_VISIBLE = config.get(
"metrics_visible",
{"cpu": True, "ram": True, "disk": True, "swap": True, "gpu": False},
)
else:
WALLPAPERS_DIR = WALLPAPERS_DIR_DEFAULT
DOCK_POSITION = "Bottom"
@@ -87,7 +89,6 @@ else:
NOTIF_POS = NOTIF_POS_DEFAULT
DOCK_COMPONENTS_VISIBILITY = {
"workspaces": True,
"metrics": True,
@@ -98,4 +99,10 @@ else:
}
METRICS_DISKS = ["/"]
METRICS_VISIBLE = {"cpu": True, "ram": True, "disk": True, "swap": True, "gpu": False}
METRICS_VISIBLE = {
"cpu": True,
"ram": True,
"disk": True,
"swap": True,
"gpu": False,
}
+2 -11
View File
@@ -1,12 +1,3 @@
{
"pinned_apps": [
{
"name": "Brave",
"display_name": "Brave",
"window_class": "brave-browser",
"executable": "brave",
"command_line": "brave %U",
"icon_name": "brave-desktop"
}
]
}
"pinned_apps": []
}
+493 -241
View File
File diff suppressed because it is too large. Load diff
+19 -14
View File
@@ -1,23 +1,21 @@
import os
import json
import os
import config.data as data
from fabric.widgets.box import Box
from fabric.widgets.button import Button
from fabric.widgets.datetime import DateTime
from modules.dock.battery import Battery
from modules.dock.metrics import Metrics
from modules.dock.controls import Controls
from modules.dock.workspaces import create_workspace_widget
from modules.dock.indicators import Indicators
from modules.dock.metrics import Metrics
from modules.dock.workspaces import create_workspace_widget
class DockSystemTray(Box):
class DockComponents(Box):
def __init__(self, orientation_val="h", **kwargs):
super().__init__(
name="system-tray",
orientation=orientation_val,
spacing=4,
**kwargs
name="dock-components", orientation=orientation_val, spacing=4, **kwargs
)
# Initialize component visibility from data
@@ -57,7 +55,6 @@ class DockSystemTray(Box):
self.add(self.battery)
self.add(self.date_time)
# Apply initial visibility
self.apply_component_props()
@@ -86,16 +83,24 @@ class DockSystemTray(Box):
}
if component_name in components and component_name in self.component_visibility:
self.component_visibility[component_name] = not self.component_visibility[component_name]
components[component_name].set_visible(self.component_visibility[component_name])
self.component_visibility[component_name] = not self.component_visibility[
component_name
]
components[component_name].set_visible(
self.component_visibility[component_name]
)
config_file = os.path.expanduser(f"~/.config/{data.APP_NAME}/config/config.json")
config_file = os.path.expanduser(
f"~/.config/{data.APP_NAME}/config/config.json"
)
if os.path.exists(config_file):
try:
with open(config_file, "r") as f:
config = json.load(f)
config[f"dock_{component_name}_visible"] = self.component_visibility[component_name]
config[f"dock_{component_name}_visible"] = (
self.component_visibility[component_name]
)
with open(config_file, "w") as f:
json.dump(config, f, indent=4)
@@ -104,4 +109,4 @@ class DockSystemTray(Box):
return self.component_visibility[component_name]
return None
return None
+18 -21
View File
@@ -19,7 +19,7 @@ from fabric.widgets.image import Image
from fabric.widgets.revealer import Revealer
from gi.repository import Gdk, GLib, Gtk
from modules.corners import MyCorner
from modules.dock.components import DockSystemTray
from modules.dock.components import DockComponents
from utils.icon_resolver import IconResolver
from utils.occlusion import check_occlusion
from utils.wayland import WaylandWindow as Window
@@ -146,24 +146,20 @@ class Dock(Window):
self.dock_eventbox.connect("enter-notify-event", self._on_dock_enter)
self.dock_eventbox.connect("leave-notify-event", self._on_dock_leave)
# Create system tray section
# Create components section
separator_orientation = (
Gtk.Orientation.VERTICAL
if self.view.get_orientation() == Gtk.Orientation.HORIZONTAL
else Gtk.Orientation.HORIZONTAL
)
# Initialize system tray with proper orientation
self.system_tray = DockSystemTray(
orientation_val=dock_wrapper_orientation_val
)
# Initialize system tray with proper orientation
self.system_tray = DockSystemTray(
orientation_val=dock_wrapper_orientation_val
)
# Initialize components with proper orientation
self.components = DockComponents(orientation_val=dock_wrapper_orientation_val)
# Add system tray to dock
# Initialize components with proper orientation
self.components = DockComponents(orientation_val=dock_wrapper_orientation_val)
# Add components to dock
if data.DOCK_POSITION == "Right":
self.view.add(
Box(
@@ -175,9 +171,9 @@ class Dock(Window):
name="dock-separator",
)
)
self.view.add(self.system_tray)
self.view.add(self.components)
else:
self.view.pack_start(self.system_tray, False, False, 0)
self.view.pack_start(self.components, False, False, 0)
self.view.add(
Box(
orientation=separator_orientation,
@@ -765,9 +761,9 @@ class Dock(Window):
name="dock-separator",
)
)
children.append(self.system_tray)
children.append(self.components)
else: # Bottom or Left position
children.append(self.system_tray)
children.append(self.components)
if pinned_buttons or open_buttons:
children.append(
Box(
@@ -917,16 +913,15 @@ class Dock(Window):
seat = display.get_default_seat()
pointer = seat.get_pointer()
window = self.get_window()
if window:
screen, x, y = pointer.get_position() # Fix: Unpack all three values
win_x, win_y = window.get_position()
win_w = window.get_width()
win_h = window.get_height()
# If pointer is outside dock window bounds
if (x < win_x or x > win_x + win_w or
y < win_y or y > win_y + win_h):
if x < win_x or x > win_x + win_w or y < win_y or y > win_y + win_h:
app_id_dragged = widget.app_identifier
instances_dragged = widget.instances
@@ -935,7 +930,9 @@ class Dock(Window):
if isinstance(app_id_dragged, dict) and isinstance(
pinned_app_item, dict
):
if app_id_dragged.get("name") == pinned_app_item.get("name"):
if app_id_dragged.get("name") == pinned_app_item.get(
"name"
):
app_index_dragged = i
break
elif app_id_dragged == pinned_app_item: