177 lines
6.0 KiB
Python
177 lines
6.0 KiB
Python
import os
|
|
import threading
|
|
import logging
|
|
|
|
from PIL import Image
|
|
import pystray
|
|
|
|
import config
|
|
import fetcher
|
|
import wallpaper
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
STYLES = ["fill", "fit", "stretch", "tile", "center"]
|
|
STYLE_LABELS = {"fill": "填充", "fit": "适应", "stretch": "拉伸", "tile": "平铺", "center": "居中"}
|
|
|
|
|
|
def _get_icon_path():
|
|
return os.path.join(config._get_app_dir(), "assets", "icon.ico")
|
|
|
|
|
|
class TrayApp:
|
|
def __init__(self):
|
|
self._icon = None
|
|
self._auto_timer = None
|
|
self._running = False
|
|
|
|
def run(self):
|
|
self._running = True
|
|
image = Image.open(_get_icon_path())
|
|
self._icon = pystray.Icon(
|
|
"WallpaperChanger",
|
|
image,
|
|
"壁纸更换器",
|
|
menu=self._build_menu(),
|
|
)
|
|
self._icon.title = "壁纸更换器"
|
|
if config.get("auto_refresh.enabled"):
|
|
self._start_auto_refresh()
|
|
self._icon.run()
|
|
|
|
def stop(self):
|
|
self._running = False
|
|
self._stop_auto_refresh()
|
|
if self._icon:
|
|
self._icon.stop()
|
|
|
|
def _build_menu(self):
|
|
show_notify = config.get("wallpaper.show_notification", True)
|
|
notify_label = "弹出通知: 开" if show_notify else "弹出通知: 关"
|
|
return pystray.Menu(
|
|
pystray.MenuItem("刷新壁纸", self._on_refresh, default=True),
|
|
pystray.MenuItem("自动刷新", self._auto_refresh_submenu()),
|
|
pystray.MenuItem("填充方式", self._fill_style_submenu()),
|
|
pystray.Menu.SEPARATOR,
|
|
pystray.MenuItem(notify_label, self._on_toggle_notification),
|
|
pystray.Menu.SEPARATOR,
|
|
pystray.MenuItem("安装右键菜单", self._on_install_menu),
|
|
pystray.MenuItem("卸载右键菜单", self._on_uninstall_menu),
|
|
pystray.Menu.SEPARATOR,
|
|
pystray.MenuItem("退出", self._on_exit),
|
|
)
|
|
|
|
def _auto_refresh_submenu(self):
|
|
enabled = config.get("auto_refresh.enabled", False)
|
|
label = "状态: 开启" if enabled else "状态: 关闭"
|
|
return pystray.Menu(
|
|
pystray.MenuItem(label, None),
|
|
pystray.Menu.SEPARATOR,
|
|
pystray.MenuItem("开启", self._on_auto_on),
|
|
pystray.MenuItem("关闭", self._on_auto_off),
|
|
)
|
|
|
|
def _fill_style_submenu(self):
|
|
items = []
|
|
for s in STYLES:
|
|
items.append(
|
|
pystray.MenuItem(
|
|
STYLE_LABELS[s],
|
|
self._on_set_fill_style,
|
|
checked=lambda item, _s=s: _s == config.get("wallpaper.fill_style", "fill"),
|
|
)
|
|
)
|
|
return pystray.Menu(*items)
|
|
|
|
def _on_refresh(self, icon, item=None):
|
|
threading.Thread(target=self._do_refresh, daemon=True).start()
|
|
|
|
def _do_refresh(self):
|
|
try:
|
|
image_path = fetcher.fetch_wallpaper()
|
|
fill_style = config.get("wallpaper.fill_style", "fill")
|
|
ok = wallpaper.set_wallpaper(image_path, fill_style)
|
|
if ok and self._icon:
|
|
if config.get("wallpaper.show_notification", True):
|
|
self._icon.notify("壁纸已更新")
|
|
except Exception as e:
|
|
logger.exception("Refresh failed")
|
|
if self._icon and config.get("wallpaper.show_notification", True):
|
|
self._icon.notify(f"刷新失败: {e}")
|
|
|
|
def _on_auto_on(self, icon, item):
|
|
config.set_("auto_refresh.enabled", True)
|
|
self._start_auto_refresh()
|
|
icon.update_menu()
|
|
|
|
def _on_auto_off(self, icon, item):
|
|
config.set_("auto_refresh.enabled", False)
|
|
self._stop_auto_refresh()
|
|
icon.update_menu()
|
|
|
|
def _on_set_fill_style(self, icon, item):
|
|
for s in STYLES:
|
|
if STYLE_LABELS[s] == str(item):
|
|
config.set_("wallpaper.fill_style", s)
|
|
break
|
|
icon.update_menu()
|
|
|
|
def _on_toggle_notification(self, icon, item):
|
|
current = config.get("wallpaper.show_notification", True)
|
|
config.set_("wallpaper.show_notification", not current)
|
|
icon.update_menu()
|
|
|
|
def _on_install_menu(self, icon, item):
|
|
threading.Thread(target=self._do_install_menu, daemon=True).start()
|
|
|
|
def _do_install_menu(self):
|
|
try:
|
|
from install_menu import install
|
|
install()
|
|
if self._icon:
|
|
self._icon.notify("右键菜单已安装")
|
|
except Exception as e:
|
|
logger.exception("Install menu failed")
|
|
if self._icon:
|
|
self._icon.notify(f"安装失败: {e}")
|
|
|
|
def _on_uninstall_menu(self, icon, item):
|
|
threading.Thread(target=self._do_uninstall_menu, daemon=True).start()
|
|
|
|
def _do_uninstall_menu(self):
|
|
try:
|
|
from install_menu import uninstall
|
|
uninstall()
|
|
if self._icon:
|
|
self._icon.notify("右键菜单已卸载")
|
|
except Exception as e:
|
|
logger.exception("Uninstall menu failed")
|
|
if self._icon:
|
|
self._icon.notify(f"卸载失败: {e}")
|
|
|
|
def _on_exit(self, icon, item):
|
|
self.stop()
|
|
|
|
def _start_auto_refresh(self):
|
|
self._stop_auto_refresh()
|
|
interval = config.get("auto_refresh.interval_minutes", 10) * 60
|
|
self._auto_timer = threading.Timer(interval, self._auto_refresh_tick)
|
|
self._auto_timer.daemon = True
|
|
self._auto_timer.start()
|
|
logger.info("Auto refresh started, interval=%ds", interval)
|
|
|
|
def _stop_auto_refresh(self):
|
|
if self._auto_timer:
|
|
self._auto_timer.cancel()
|
|
self._auto_timer = None
|
|
|
|
def _auto_refresh_tick(self):
|
|
if not self._running:
|
|
return
|
|
self._do_refresh()
|
|
if config.get("auto_refresh.enabled"):
|
|
interval = config.get("auto_refresh.interval_minutes", 10) * 60
|
|
self._auto_timer = threading.Timer(interval, self._auto_refresh_tick)
|
|
self._auto_timer.daemon = True
|
|
self._auto_timer.start()
|