91 lines
3.1 KiB
Python
91 lines
3.1 KiB
Python
import queue
|
|
import logging
|
|
import pystray
|
|
from PIL import Image, ImageDraw
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
_COLORS = {"dp": "#1565C0", "hdmi": "#B71C1C", "default": "#455A64"}
|
|
|
|
|
|
def _make_icon(label: str, color: str) -> Image.Image:
|
|
img = Image.new("RGBA", (64, 64), (0, 0, 0, 0))
|
|
draw = ImageDraw.Draw(img)
|
|
draw.ellipse([2, 2, 62, 62], fill=color)
|
|
text = label[:2].upper()
|
|
bbox = draw.textbbox((0, 0), text)
|
|
tw = bbox[2] - bbox[0]
|
|
th = bbox[3] - bbox[1]
|
|
draw.text(((64 - tw) // 2, (64 - th) // 2), text, fill="white")
|
|
return img
|
|
|
|
|
|
def _color_for(profile_id: str) -> str:
|
|
if "dp" in profile_id:
|
|
return _COLORS["dp"]
|
|
if "hdmi" in profile_id:
|
|
return _COLORS["hdmi"]
|
|
return _COLORS["default"]
|
|
|
|
|
|
class TrayApp:
|
|
def __init__(self, config_manager, switcher, settings_queue: queue.Queue):
|
|
self._config_manager = config_manager
|
|
self._switcher = switcher
|
|
self._settings_queue = settings_queue
|
|
self._icon: pystray.Icon | None = None
|
|
switcher.on_switch(self._on_profile_switched)
|
|
|
|
def _build_menu(self) -> pystray.Menu:
|
|
config = self._config_manager.get()
|
|
items = []
|
|
for profile in config.get("profiles", []):
|
|
pid = profile["id"]
|
|
name = profile["name"]
|
|
items.append(
|
|
pystray.MenuItem(
|
|
name,
|
|
lambda _, p=pid: self._switcher.apply_profile(p),
|
|
checked=lambda item, p=pid: (
|
|
self._config_manager.get_active_profile_id() == p
|
|
),
|
|
radio=True,
|
|
)
|
|
)
|
|
items.append(pystray.Menu.SEPARATOR)
|
|
items.append(pystray.MenuItem("Ustawienia", self._request_settings))
|
|
items.append(pystray.MenuItem("Wyjscie", self._exit))
|
|
return pystray.Menu(*items)
|
|
|
|
def _on_profile_switched(self, profile_id: str) -> None:
|
|
if self._icon is None:
|
|
return
|
|
profile = self._config_manager.get_profile(profile_id)
|
|
label = profile["name"][:2] if profile else "??"
|
|
title = profile["name"] if profile else profile_id
|
|
self._icon.icon = _make_icon(label, _color_for(profile_id))
|
|
self._icon.title = f"MonitorSwitcher \u2014 {title}"
|
|
self._icon.update_menu()
|
|
|
|
def _request_settings(self, icon=None, item=None) -> None:
|
|
self._settings_queue.put("open_settings")
|
|
|
|
def _exit(self, icon=None, item=None) -> None:
|
|
self._settings_queue.put("exit")
|
|
if self._icon:
|
|
self._icon.stop()
|
|
|
|
def run_tray(self) -> None:
|
|
active_id = self._config_manager.get_active_profile_id()
|
|
profile = self._config_manager.get_profile(active_id)
|
|
label = profile["name"][:2] if profile else "MS"
|
|
title = f"MonitorSwitcher \u2014 {profile['name']}" if profile else "MonitorSwitcher"
|
|
|
|
self._icon = pystray.Icon(
|
|
"MonitorSwitcher",
|
|
_make_icon(label, _color_for(active_id)),
|
|
title=title,
|
|
menu=self._build_menu(),
|
|
)
|
|
self._icon.run()
|