You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
82 lines
2.6 KiB
Python
82 lines
2.6 KiB
Python
"""
|
|
System Tray Icon Handler
|
|
Manages the application in the system tray
|
|
"""
|
|
import pystray
|
|
import logging
|
|
from typing import Callable, Optional
|
|
from PIL import Image, ImageDraw
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
class SystemTrayIcon:
|
|
def __init__(self, app_name: str):
|
|
self.app_name = app_name
|
|
self.icon: Optional[pystray.Icon] = None
|
|
self.status_text = "Initializing..."
|
|
self.on_quit: Optional[Callable] = None
|
|
self.on_show: Optional[Callable] = None
|
|
|
|
def _create_image(self, status: str = "ready") -> Image.Image:
|
|
"""Create a simple tray icon image"""
|
|
size = 64
|
|
color_map = {
|
|
'ready': (0, 200, 0),
|
|
'running': (0, 150, 200),
|
|
'error': (200, 0, 0),
|
|
'waiting': (200, 150, 0),
|
|
}
|
|
|
|
color = color_map.get(status, (128, 128, 128))
|
|
image = Image.new('RGB', (size, size), color)
|
|
draw = ImageDraw.Draw(image)
|
|
draw.rectangle([0, 0, size-1, size-1], outline=(0, 0, 0), width=2)
|
|
|
|
return image
|
|
|
|
def set_status(self, status: str, text: str):
|
|
"""Update the tray icon status"""
|
|
self.status_text = text
|
|
if self.icon:
|
|
self.icon.update_menu()
|
|
|
|
def create_menu(self) -> pystray.Menu:
|
|
"""Create the context menu for the tray icon"""
|
|
menu_items = [
|
|
pystray.MenuItem(f"📊 {self.app_name}", action=None),
|
|
pystray.MenuItem("─" * 30, action=None),
|
|
pystray.MenuItem("Status: " + self.status_text, action=None),
|
|
pystray.MenuItem("─" * 30, action=None),
|
|
pystray.MenuItem("Quit", self._on_quit_click),
|
|
]
|
|
return pystray.Menu(*menu_items)
|
|
|
|
def _on_quit_click(self, icon, item):
|
|
"""Handle quit click"""
|
|
if self.on_quit:
|
|
self.on_quit()
|
|
if self.icon:
|
|
self.icon.stop()
|
|
|
|
def run(self):
|
|
"""Run the tray icon"""
|
|
try:
|
|
self.icon = pystray.Icon(
|
|
name=self.app_name,
|
|
icon=self._create_image('running'),
|
|
menu=self.create_menu(),
|
|
title=self.app_name
|
|
)
|
|
self.icon.run()
|
|
except Exception as e:
|
|
logger.error(f"Error running tray icon: {e}")
|
|
|
|
def stop(self):
|
|
"""Stop the tray icon"""
|
|
if self.icon:
|
|
self.icon.stop()
|
|
|
|
def set_callbacks(self, on_quit: Optional[Callable] = None, on_show: Optional[Callable] = None):
|
|
"""Set callback functions"""
|
|
self.on_quit = on_quit
|
|
self.on_show = on_show |