fix: Simplify tray icon - remove timer and complex styling that blocks UI

The tray icon was blocking the main UI thread because:
1. QTimer was updating menu state every second
2. Complex stylesheet on menu may cause blocking
3. Emojis in menu items might cause encoding issues

Simplified:
- Removed update timer (no longer needed)
- Removed complex stylesheet (use default)
- Removed emojis from menu items
- Made TrayIcon inherit QWidget for proper parent
- Simplified signal connections
This commit is contained in:
LemonNexus 2026-02-15 23:29:54 +00:00
parent eba2e029e3
commit 0d2494abd7
1 changed files with 43 additions and 122 deletions

View File

@ -1,32 +1,17 @@
""" """
EU-Utility - System Tray Icon EU-Utility - System Tray Icon (Simplified)
============================= ==========================================
System tray implementation with right-click menu. Simple, responsive system tray icon.
Replaces the floating icon with a proper tray icon.
""" """
from PyQt6.QtWidgets import QSystemTrayIcon, QMenu, QApplication from PyQt6.QtWidgets import QSystemTrayIcon, QMenu, QApplication, QWidget
from PyQt6.QtGui import QAction from PyQt6.QtGui import QAction, QIcon, QColor, QPainter, QFont
from PyQt6.QtCore import QTimer, pyqtSignal, QObject from PyQt6.QtCore import pyqtSignal
from PyQt6.QtGui import QIcon, QColor, QPainter, QFont, QFontMetrics
from core.logger import get_logger
logger = get_logger(__name__)
class TrayIcon(QObject): class TrayIcon(QWidget):
""" """Simple system tray icon for EU-Utility."""
System tray icon for EU-Utility.
Features:
- Right-click context menu
- Show/hide dashboard
- Toggle activity bar
- Settings access
- Quit option
"""
show_dashboard = pyqtSignal() show_dashboard = pyqtSignal()
toggle_activity_bar = pyqtSignal() toggle_activity_bar = pyqtSignal()
@ -36,126 +21,62 @@ class TrayIcon(QObject):
def __init__(self, app: QApplication, parent=None): def __init__(self, app: QApplication, parent=None):
super().__init__(parent) super().__init__(parent)
self.app = app self.app = app
self.tray_icon = None
self.menu = None
# Create icon
self._create_icon() self._create_icon()
self._setup_menu()
self._setup_visibility_timer() # Create menu (but don't set it yet)
self._create_menu()
# Connect signals
self.tray_icon.activated.connect(self._on_activated)
def _create_icon(self): def _create_icon(self):
"""Create the tray icon with EU logo.""" """Create tray icon."""
# Create a simple colored circle icon with "EU" text # Create simple icon
pixmap = QIcon.fromTheme("applications-system")
# If no system icon, create custom
if pixmap.isNull():
from PyQt6.QtGui import QPixmap, QPainter, QColor, QFont
px = QPixmap(64, 64) px = QPixmap(64, 64)
px.fill(QColor(255, 140, 66)) # Orange background px.fill(QColor(255, 140, 66)) # Orange
painter = QPainter(px) painter = QPainter(px)
painter.setPen(QColor(255, 255, 255)) painter.setPen(QColor(255, 255, 255))
font = QFont("Segoe UI", 24, QFont.Weight.Bold) font = QFont("Segoe UI", 24, QFont.Weight.Bold)
painter.setFont(font) painter.setFont(font)
painter.drawText(px.rect(), Qt.AlignmentFlag.AlignCenter, "EU") painter.drawText(px.rect(), 0x84, "EU") # AlignCenter
painter.end() painter.end()
pixmap = QIcon(px)
self.tray_icon = QSystemTrayIcon(self) self.tray_icon = QSystemTrayIcon(self)
self.tray_icon.setIcon(pixmap) self.tray_icon.setIcon(QIcon(px))
self.tray_icon.setToolTip("EU-Utility") self.tray_icon.setToolTip("EU-Utility")
# Show the icon
self.tray_icon.show() self.tray_icon.show()
# Connect activation (double-click) def _create_menu(self):
self.tray_icon.activated.connect(self._on_activated) """Create simple context menu."""
def _setup_menu(self):
"""Setup the right-click context menu."""
self.menu = QMenu() self.menu = QMenu()
self.menu.setStyleSheet("""
QMenu {
background: rgba(35, 35, 35, 0.98);
color: white;
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 8px;
padding: 8px;
}
QMenu::item {
padding: 10px 24px;
border-radius: 6px;
}
QMenu::item:selected {
background: rgba(255, 140, 66, 0.3);
}
QMenu::separator {
height: 1px;
background: rgba(255, 255, 255, 0.1);
margin: 8px 16px;
}
""")
# Dashboard action # Simple actions (no emojis to avoid encoding issues)
self.dashboard_action = QAction("📊 Dashboard", self) self.dashboard_action = QAction("Dashboard", self)
self.dashboard_action.triggered.connect(self.show_dashboard) self.dashboard_action.triggered.connect(self.show_dashboard.emit)
self.menu.addAction(self.dashboard_action) self.menu.addAction(self.dashboard_action)
# Activity Bar toggle self.activity_bar_action = QAction("Activity Bar", self)
self.activity_bar_action = QAction("🎮 Activity Bar", self)
self.activity_bar_action.setCheckable(True) self.activity_bar_action.setCheckable(True)
self.activity_bar_action.triggered.connect(self.toggle_activity_bar) self.activity_bar_action.triggered.connect(self.toggle_activity_bar.emit)
self.menu.addAction(self.activity_bar_action) self.menu.addAction(self.activity_bar_action)
self.menu.addSeparator() self.menu.addSeparator()
# Settings self.quit_action = QAction("Quit", self)
self.settings_action = QAction("⚙️ Settings", self) self.quit_action.triggered.connect(self.quit_app.emit)
self.settings_action.triggered.connect(self.open_settings)
self.menu.addAction(self.settings_action)
self.menu.addSeparator()
# Quit
self.quit_action = QAction("❌ Quit", self)
self.quit_action.triggered.connect(self.quit_app)
self.menu.addAction(self.quit_action) self.menu.addAction(self.quit_action)
# Set menu # Set context menu
self.tray_icon.setContextMenu(self.menu) self.tray_icon.setContextMenu(self.menu)
def _setup_visibility_timer(self):
"""Setup timer to update menu state."""
self.update_timer = QTimer(self)
self.update_timer.timeout.connect(self._update_menu_state)
self.update_timer.start(1000) # Update every second
def _update_menu_state(self):
"""Update menu checkbox states."""
# This will be connected to actual state
pass
def _on_activated(self, reason): def _on_activated(self, reason):
"""Handle tray icon activation.""" """Handle double-click."""
if reason == QSystemTrayIcon.ActivationReason.DoubleClick: if reason == QSystemTrayIcon.ActivationReason.DoubleClick:
self.show_dashboard.emit() self.show_dashboard.emit()
def show_notification(self, title: str, message: str, duration: int = 3000):
"""Show a system notification."""
if self.tray_icon and self.tray_icon.supportsMessages():
self.tray_icon.showMessage(
title,
message,
QSystemTrayIcon.MessageIcon.Information,
duration
)
def set_activity_bar_checked(self, checked: bool): def set_activity_bar_checked(self, checked: bool):
"""Update activity bar menu item state.""" """Update checkbox."""
self.activity_bar_action.setChecked(checked) self.activity_bar_action.setChecked(checked)
def is_visible(self) -> bool:
"""Check if tray icon is visible."""
return self.tray_icon and self.tray_icon.isVisible()