)e5iCGdZddlZddlZddlZddlmZddlmZddlm Z m Z m Z ddl m Z mZddlmZmZmZGdd e Zy) zSystem tray application for DaemonControl. This module provides the SystemTrayApp class that creates a system tray icon with a context menu for controlling the DaemonControl daemon. N)Path)Optional)QObjectQTimer pyqtSignal)QActionQIcon) QApplicationQMenuQSystemTrayIconceZdZdZeeZfdZddZddZ de fdZ ddZ dd Z d ed eddfd Zdd ZddZddZddZddZddZxZS) SystemTrayAppzSystem tray application for DaemonControl. Provides a system tray icon with menu to control the daemon, monitor status, and access logs. c\t|ddlm}||_|jj |jj j |jddlm }||_ |j|j|jy)a?Initialize system tray application. Creates: - QSystemTrayIcon with icons - Context menu with actions - Main GUI window (hidden by default) Note: Daemon is managed by systemd, not by this GUI. Use 'systemctl --user status daemoncontrol' to check daemon status. ) MainWindowr)DatabaseManagerN)super__init__ main_windowrhide jobs_modifiedconnect_on_jobs_modified core.databaserdb_init_tray_icon _init_menu_init_fleet_status_check)selfrr __class__s 9/mnt/ssd/data/python-lab/DaemonControl/gui/system_tray.pyrzSystemTrayApp.__init__s  ,&<  &&..t/E/EF 2!#   %%'returnNct||_ttjdz }t t |dz |_t t |dz |_t t |dz |_ |jj|j|jjd|jjj|jy)zCreate system tray icon. Loads icons from gui/resources/ directory and sets up the tray icon with initial state (inactive/stopped). resourceszicon_active.pngzicon_inactive.pngzicon_error.pngz+DaemonControl GUI - Click to open dashboardN)r tray_iconr__file__parentr str icon_active icon_inactive icon_errorsetIcon setToolTip activatedr_on_tray_activated)r resources_dirs r!rzSystemTrayApp._init_tray_icon>s ).X-- ;  ]5F%F!GH"3}7J'J#KLM4D$D EF t112 !!"OP   (()@)@Ar"cy)u2Create context menu with actions. Menu structure: - Open Dashboard - ───────────── (separator) - Open Logs Folder - ───────────── (separator) - Exit Note: Menu is created on-demand via _on_tray_activated() to work around Qt6 rendering issues on some Linux desktop environments. Daemon control (Start/Stop/Reload) has been removed since the daemon is now managed by systemd. Use systemctl commands to manage the daemon. Nrs r!rzSystemTrayApp._init_menuSsr"ct}td|}|jj|j|j ||j td|}|jj|j|j ||j td|}|jj|j|j ||S)a?Create and return context menu. Creates menu fresh each time to work around Qt6 rendering bugs on some Linux desktop environments (especially Wayland). Simplified menu without daemon controls (daemon managed by systemd). Returns: QMenu with all actions configured u📊 Open Dashboardu📂 Open Logs FolderExit) r r triggeredrshow_main_window addAction addSeparatoropen_logs_folderexit_app)rmenuopen_gui_action logs_action exit_actions r!_create_context_menuz"SystemTrayApp._create_context_menuesw""7>!!))$*?*?@ ' 5t< %%d&;&;< {# fd+ %%dmm4 {# r"c~ ddlm}|}|jdd}t|j j }|j s|jdd|ytjdt|gy#t$r(}|jd d t|Yd}~yd}~wwxYw) zmOpen logs folder in system file manager. Uses xdg-open on Linux to open the logs directory. r) ConfigManagerloggingdaemon_log_filezLogs Not FoundzLog directory does not exist: Nzxdg-openErrorzFailed to open logs folder: ) corerCgetr expanduserr(exists_show_notification subprocessPopenr) Exception)rrCconfiglog_filelog_dires r!r;zSystemTrayApp.open_logs_folder s   *"_Fzz)->?H8n//188G>>#''$4WI>   j#g,7 8   # #.s1vh7   sA'B * B B<B77B<cd|jr|jtjy)z_Exit the application. Stops daemon if running, then exits the Qt application. N)daemon_running stop_daemonr quitr4s r!r<zSystemTrayApp.exit_app's%       r"titlemessagecp|jj||tjjdy)zShow system notification. Args: title: Notification title message: Notification message Displays a system tray notification for 3 seconds. i N)r& showMessager MessageIcon Information)rrWrXs r!rKz SystemTrayApp._show_notificationzs. ""    ' ' 3 3   r"c8|jjy)zUShow the tray icon. Makes the tray icon visible in the system tray. N)r&showr4s r!r^zSystemTrayApp.shows r"c|jj|jj|jjy)zUShow main GUI window. Opens the main window and brings it to front. N)rr^raise_activateWindowr4s r!r8zSystemTrayApp.show_main_windows:  ! '')r"cddlm}ddlm}||jj k(r|j y||jjk(r|j y||jjk(rz|j}|jj}|jr |j|jy|j|jyy)zHandle tray icon activation (click). Args: reason: Activation reason from Qt Opens main window on double-click. Shows context menu on right-click (manually created to fix Qt6/Wayland issues). r)r )QCursorN)PyQt6.QtWidgetsr PyQt6.QtGuircActivationReason DoubleClickr8TriggerContextrAr&geometryisValidexec bottomLeftpos)rreasonr rcr=rjs r!r0z SystemTrayApp._on_tray_activateds 4' _55AA A  ! ! # 77?? ?  ! ! # 77?? ?,,.D~~..0H! (--/0 '++-(@r"cb|jr#|jdd|jyy)zdHandle jobs modified from GUI. If daemon is running, reload it to pick up changes. z Jobs Modifiedz$Reloading daemon to apply changes...N)rTrK reload_jobsr4s r!rzSystemTrayApp._on_jobs_modifieds4     # #6      r"c|jt|_|jjj |j|jj dy)aSetup lightweight fleet status monitoring from database. Reads overall fleet status from database every 30 seconds and updates tray icon color accordingly. This is very lightweight (single DB query, no network/docker calls). i0uN)_update_icon_from_dbrfleet_status_timertimeoutrstartr4s r!rz&SystemTrayApp._init_fleet_status_checksP !!##)( ''//0I0IJ %%e,r"c |jj}|jdi}|jdd}|jd}||dkDrA|jj |j |jj dy|dk(rA|jj |j|jj d y|d k(rA|jj |j|jj d y|jj |j |jj d |jy#t$rX}td ||jj |j |jj dYd}~yd}~wwxYw)aUpdate tray icon based on latest overall fleet status from database. Icon colors: - Green (active): All systems healthy - Red (error): Critical issues detected - Grey (inactive): Warning, unknown status, or stale data overallstatusunknown age_secondsNiXz0DaemonControl - No recent data (daemon stopped?)healthyu'DaemonControl - All Systems Healthy ✓criticalz)DaemonControl - Critical Issues Detected!zDaemonControl - Status: z,Error updating tray icon from fleet status: z"DaemonControl - Status check error) rget_latest_fleet_statusrHr&r-r+r.r*r,rWrNprint)r status_datarxryr{rRs r!rsz"SystemTrayApp._update_icon_from_dbst L''99;K!ooi4G[[95F!++m4K"kC&7&&t'9'9:))*\]"&&t'7'78))*ST:%&&t7))*UV&&t'9'9:)),DV\\^DT*UV L @D E NN " "4#5#5 6 NN % %&J K K  Ls.BE7AE7AE7%AE77 GAGG)r#N)__name__ __module__ __qualname____doc__rr)status_changedrrrr rAr;r<rKr^r8r0rrrs __classcell__)r s@r!rrsu _N (DB* $ e J:f  c d *)> - $Lr"r)rosrLsyspathlibrtypingr PyQt6.QtCorerrrrerr rdr r r rr3r"r!rs:   44&@@gLGgLr"