194 lines
7.0 KiB
Python
194 lines
7.0 KiB
Python
"""
|
|
EU-Utility - System Tray Icon (Debug Version)
|
|
=============================================
|
|
|
|
Simple, responsive system tray icon with debug logging.
|
|
"""
|
|
|
|
from PyQt6.QtWidgets import QSystemTrayIcon, QMenu, QApplication, QWidget
|
|
from PyQt6.QtGui import QAction, QIcon, QColor, QPainter, QFont, QPixmap
|
|
from PyQt6.QtCore import pyqtSignal, Qt, QTimer
|
|
|
|
# Import debug logger
|
|
try:
|
|
from core.debug_logger import debug_logger
|
|
DEBUG_AVAILABLE = True
|
|
except ImportError:
|
|
DEBUG_AVAILABLE = False
|
|
# Dummy logger
|
|
class DummyLogger:
|
|
def debug(self, *args): pass
|
|
def info(self, *args): pass
|
|
def warn(self, *args): pass
|
|
def error(self, *args): pass
|
|
def start_timer(self, *args): pass
|
|
def end_timer(self, *args): return 0.0
|
|
debug_logger = DummyLogger()
|
|
|
|
|
|
class TrayIcon(QWidget):
|
|
"""Simple system tray icon for EU-Utility."""
|
|
|
|
show_dashboard = pyqtSignal()
|
|
toggle_activity_bar = pyqtSignal()
|
|
open_settings = pyqtSignal()
|
|
quit_app = pyqtSignal()
|
|
|
|
def __init__(self, app: QApplication, parent=None):
|
|
debug_logger.start_timer("TrayIcon.__init__")
|
|
super().__init__(parent)
|
|
self.app = app
|
|
|
|
debug_logger.debug("TRAY", "Creating tray icon...")
|
|
|
|
# Create icon
|
|
self._create_icon()
|
|
|
|
# Create menu (but don't set it yet)
|
|
debug_logger.debug("TRAY", "Creating menu...")
|
|
self._create_menu()
|
|
|
|
# Connect signals
|
|
debug_logger.debug("TRAY", "Connecting signals...")
|
|
self.tray_icon.activated.connect(self._on_activated)
|
|
|
|
debug_logger.end_timer("TrayIcon.__init__")
|
|
debug_logger.info("TRAY", "Tray icon initialized")
|
|
|
|
def _create_icon(self):
|
|
"""Create tray icon."""
|
|
debug_logger.start_timer("TrayIcon._create_icon")
|
|
|
|
# Create simple icon
|
|
px = QPixmap(64, 64)
|
|
px.fill(QColor(255, 140, 66)) # Orange
|
|
|
|
painter = QPainter(px)
|
|
painter.setPen(QColor(255, 255, 255))
|
|
font = QFont("Segoe UI", 24, QFont.Weight.Bold)
|
|
painter.setFont(font)
|
|
painter.drawText(px.rect(), 0x84, "EU") # AlignCenter
|
|
painter.end()
|
|
|
|
self.tray_icon = QSystemTrayIcon(self)
|
|
self.tray_icon.setIcon(QIcon(px))
|
|
self.tray_icon.setToolTip("EU-Utility")
|
|
self.tray_icon.show()
|
|
|
|
debug_logger.end_timer("TrayIcon._create_icon")
|
|
|
|
def _create_menu(self):
|
|
"""Create simple context menu."""
|
|
debug_logger.start_timer("TrayIcon._create_menu")
|
|
|
|
self.menu = QMenu()
|
|
|
|
# Track menu timing
|
|
self.menu.aboutToShow.connect(self._on_menu_about_to_show)
|
|
self.menu.aboutToHide.connect(self._on_menu_about_to_hide)
|
|
|
|
# Simple actions (no emojis to avoid encoding issues)
|
|
debug_logger.debug("TRAY", "Creating Dashboard action...")
|
|
self.dashboard_action = QAction("Dashboard (Click to Open)", self)
|
|
self.dashboard_action.triggered.connect(self._on_dashboard_clicked)
|
|
self.menu.addAction(self.dashboard_action)
|
|
|
|
debug_logger.debug("TRAY", "Creating Activity Bar action...")
|
|
self.activity_bar_action = QAction("Activity Bar (Ctrl+Shift+U)", self)
|
|
self.activity_bar_action.setCheckable(True)
|
|
self.activity_bar_action.triggered.connect(self._on_activity_bar_clicked)
|
|
self.menu.addAction(self.activity_bar_action)
|
|
|
|
self.menu.addSeparator()
|
|
|
|
debug_logger.debug("TRAY", "Creating Quit action...")
|
|
self.quit_action = QAction("Quit", self)
|
|
self.quit_action.triggered.connect(self._on_quit_clicked)
|
|
self.menu.addAction(self.quit_action)
|
|
|
|
# Set context menu
|
|
debug_logger.debug("TRAY", "Setting context menu...")
|
|
self.tray_icon.setContextMenu(self.menu)
|
|
|
|
debug_logger.end_timer("TrayIcon._create_menu")
|
|
|
|
def _on_menu_about_to_show(self):
|
|
"""Called when menu is about to show."""
|
|
debug_logger.start_timer("TRAY_MENU_SHOW")
|
|
debug_logger.debug("TRAY", "Menu about to show")
|
|
|
|
def _on_menu_about_to_hide(self):
|
|
"""Called when menu is about to hide."""
|
|
elapsed = debug_logger.end_timer("TRAY_MENU_SHOW")
|
|
debug_logger.debug("TRAY", f"Menu was visible for {elapsed:.2f}ms")
|
|
|
|
def _on_dashboard_clicked(self):
|
|
"""Handle dashboard click with timing."""
|
|
debug_logger.start_timer("TRAY_DASHBOARD_CLICK")
|
|
debug_logger.debug("TRAY", "Dashboard clicked - emitting signal...")
|
|
|
|
# Use single shot to not block menu
|
|
QTimer.singleShot(0, self._emit_dashboard)
|
|
|
|
def _emit_dashboard(self):
|
|
"""Emit dashboard signal."""
|
|
debug_logger.debug("TRAY", "Emitting show_dashboard signal...")
|
|
self.show_dashboard.emit()
|
|
debug_logger.end_timer("TRAY_DASHBOARD_CLICK")
|
|
|
|
def _on_activity_bar_clicked(self):
|
|
"""Handle activity bar click with timing."""
|
|
debug_logger.start_timer("TRAY_ACTIVITYBAR_CLICK")
|
|
debug_logger.debug("TRAY", "Activity Bar clicked - emitting signal...")
|
|
|
|
# Use single shot to not block menu
|
|
QTimer.singleShot(0, self._emit_activity_bar)
|
|
|
|
def _emit_activity_bar(self):
|
|
"""Emit activity bar signal."""
|
|
debug_logger.debug("TRAY", "Emitting toggle_activity_bar signal...")
|
|
self.toggle_activity_bar.emit()
|
|
debug_logger.end_timer("TRAY_ACTIVITYBAR_CLICK")
|
|
|
|
def _on_quit_clicked(self):
|
|
"""Handle quit click with timing."""
|
|
debug_logger.start_timer("TRAY_QUIT_CLICK")
|
|
debug_logger.debug("TRAY", "Quit clicked - emitting signal...")
|
|
|
|
# Use single shot to not block menu
|
|
QTimer.singleShot(0, self._emit_quit)
|
|
|
|
def _emit_quit(self):
|
|
"""Emit quit signal."""
|
|
debug_logger.debug("TRAY", "Emitting quit_app signal...")
|
|
self.quit_app.emit()
|
|
debug_logger.end_timer("TRAY_QUIT_CLICK")
|
|
|
|
def show(self):
|
|
"""Show the tray icon."""
|
|
debug_logger.debug("TRAY", "show() called")
|
|
if self.tray_icon:
|
|
self.tray_icon.show()
|
|
|
|
def hide(self):
|
|
"""Hide the tray icon."""
|
|
debug_logger.debug("TRAY", "hide() called")
|
|
if self.tray_icon:
|
|
self.tray_icon.hide()
|
|
|
|
def isVisible(self):
|
|
"""Check if tray icon is visible."""
|
|
return self.tray_icon.isVisible() if self.tray_icon else False
|
|
|
|
def _on_activated(self, reason):
|
|
"""Handle double-click."""
|
|
debug_logger.debug("TRAY", f"Activated with reason: {reason}")
|
|
if reason == QSystemTrayIcon.ActivationReason.DoubleClick:
|
|
debug_logger.debug("TRAY", "Double-click detected - showing dashboard")
|
|
self.show_dashboard.emit()
|
|
|
|
def set_activity_bar_checked(self, checked: bool):
|
|
"""Update checkbox."""
|
|
debug_logger.debug("TRAY", f"Setting Activity Bar checked: {checked}")
|
|
self.activity_bar_action.setChecked(checked)
|