初始提交
This commit is contained in:
+176
@@ -0,0 +1,176 @@
|
||||
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()
|
||||
Reference in New Issue
Block a user