Files
Modus/modules/panel/main.py
T
2025-08-14 13:26:24 +05:30

244 lines
8.1 KiB
Python

from fabric.system_tray.widgets import SystemTray
from fabric.utils import get_relative_path
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.revealer import Revealer
from fabric.widgets.svg import Svg
from modules.controlcenter.main import ModusControlCenter
from modules.notification.notification_center import NotificationCenter
from modules.panel.components.enhanced_system_tray import apply_enhanced_system_tray
from modules.panel.components.indicators import (
BatteryIndicator,
BluetoothIndicator,
NetworkIndicator,
)
from modules.panel.components.menubar import MenuBar
from modules.panel.components.recording_indicator import RecordingIndicator
from modules.panel.components.workspace import WorkspaceIndicator
from modules.todo.todo_widget import TodoListCapture
from utils.roam import modus_service
from widgets.mousecapture import MouseCapture
from widgets.wayland import WaylandWindow as Window
from services.modus import notification_service
# Apply enhanced system tray icon handling
apply_enhanced_system_tray()
class Panel(Window):
def __init__(self, **kwargs):
super().__init__(
name="bar",
title="modus",
layer="top",
anchor="left top right",
exclusivity="auto",
visible=False,
)
self.launcher = kwargs.get("launcher", None)
self.menubar = MenuBar(parent_window=self)
self.imac = Button(
name="panel-button",
child=Svg(
size=16,
svg_file=get_relative_path("../../config/assets/icons/misc/logo.svg"),
),
on_clicked=lambda *_: self.menubar.show_system_dropdown(self.imac),
)
# DND indicator - REMOVED
self.tray = SystemTray(name="system-tray", spacing=4, icon_size=20)
self.tray_revealer = Revealer(
name="tray-revealer",
child=self.tray,
child_revealed=False,
transition_type="slide-left",
transition_duration=300,
)
self.chevron_button = Button(
name="panel-button",
child=Svg(
size=16,
svg_file=get_relative_path(
"../../config/assets/icons/misc/chevron-right.svg"
),
),
on_clicked=self.toggle_tray,
)
self.indicators = Box(
name="indicators",
orientation="h",
spacing=4,
children=[
BatteryIndicator(),
NetworkIndicator(),
BluetoothIndicator(),
],
)
self.search = Button(
name="panel-button",
on_clicked=lambda *_: self.search_apps(),
child=Svg(
size=22,
svg_file=get_relative_path("../../config/assets/icons/misc/search.svg"),
),
)
self.control_center = MouseCapture(
layer="top", child_window=ModusControlCenter()
)
self.control_center_button = Button(
name="control-center-button",
style_classes="button",
on_clicked=self.control_center.toggle_mousecapture,
child=Svg(
size=22,
svg_file=get_relative_path(
"../../config/assets/icons/misc/control-center.svg"
),
),
)
# Notification Center with MouseCapture
self.notification_center = MouseCapture(
layer="overlay", child_window=NotificationCenter()
)
# Todo List with MouseCapture
self.todo_list = TodoListCapture()
# Notification Center Icon
self.notification_icon = Svg(
size=22,
svg_file=get_relative_path(
"../../config/assets/icons/notifications/notification-inactive.svg"
),
)
self.notification_center_icon_button = Button(
name="notification-center-icon-button",
child=self.notification_icon,
on_clicked=self.on_notification_icon_clicked,
)
# Clickable DateTime for todo list
self.datetime_button = Button(
name="datetime-button",
child=DateTime(name="date-time", formatters=["%a %-d %b %I:%M %P"]),
on_clicked=self.on_datetime_clicked,
)
self.recording_indicator = RecordingIndicator()
# Workspace indicator
self.workspace_indicator = WorkspaceIndicator()
self.children = CenterBox(
name="panel",
start_children=Box(
name="modules-left",
children=[
self.imac,
self.menubar,
],
),
center_children=Box(
name="modules-center",
children=self.recording_indicator,
),
end_children=Box(
name="modules-right",
spacing=4,
orientation="h",
children=[
self.workspace_indicator,
self.tray_revealer,
self.chevron_button,
self.indicators,
self.search,
self.control_center_button,
self.datetime_button,
self.notification_center_icon_button,
],
),
)
# Connect to DND state changes for notification icon
modus_service.connect("dont-disturb-changed", self.on_dnd_changed)
# Connect to notification service for icon state updates
notification_service.connect(
"notify::count", self.on_notification_count_changed
)
# Set initial notification icon state
self.update_notification_icon()
return self.show_all()
def search_apps(self):
self.launcher.show_launcher()
def toggle_tray(self, *_):
current_state = self.tray_revealer.child_revealed
self.tray_revealer.child_revealed = not current_state
if self.tray_revealer.child_revealed:
self.chevron_button.get_child().set_from_file(
get_relative_path("../../config/assets/icons/misc/chevron-left.svg")
)
else:
self.chevron_button.get_child().set_from_file(
get_relative_path("../../config/assets/icons/misc/chevron-right.svg")
)
def on_dnd_changed(self, _, dnd_state):
"""Handle DND state changes from the service."""
self.update_notification_icon() # Update notification icon when DND changes
def on_notification_count_changed(self, service, *args):
"""Handle notification count changes from the service."""
self.update_notification_icon()
def on_notification_icon_clicked(self, *args):
"""Handle notification icon clicks - only open center if there are notifications."""
count = notification_service.count
if count > 0:
# Only open notification center if there are notifications
self.notification_center.toggle_mousecapture()
# Do nothing if no notifications
def on_datetime_clicked(self, *args):
"""Handle datetime button clicks - open todo list."""
self.todo_list.toggle_mousecapture()
def update_notification_icon(self):
"""Update the notification icon based on count and DND state."""
count = notification_service.count
dnd_enabled = modus_service.dont_disturb
if dnd_enabled:
# DND is enabled - show disabled icon
icon_file = "notification-disabled.svg"
elif count > 0:
# Has notifications - show active icon
icon_file = "notification-active.svg"
else:
# No notifications - show inactive icon
icon_file = "notification-inactive.svg"
icon_path = get_relative_path(
f"../../config/assets/icons/notifications/{icon_file}"
)
self.notification_icon.set_from_file(icon_path)