diff --git a/__pycache__/shortcut_target.cpython-313.pyc b/__pycache__/shortcut_target.cpython-313.pyc index fef1a15..7247c10 100644 Binary files a/__pycache__/shortcut_target.cpython-313.pyc and b/__pycache__/shortcut_target.cpython-313.pyc differ diff --git a/db/__pycache__/__init__.cpython-313.pyc b/db/__pycache__/__init__.cpython-313.pyc index 8433c2e..4472d17 100644 Binary files a/db/__pycache__/__init__.cpython-313.pyc and b/db/__pycache__/__init__.cpython-313.pyc differ diff --git a/db/__pycache__/database.cpython-313.pyc b/db/__pycache__/database.cpython-313.pyc index 3b1efd2..fac6f33 100644 Binary files a/db/__pycache__/database.cpython-313.pyc and b/db/__pycache__/database.cpython-313.pyc differ diff --git a/main.py b/main.py index 4082c38..e865a7a 100644 --- a/main.py +++ b/main.py @@ -111,6 +111,17 @@ def main(): ball.clicked.connect(lambda: panel.show_near(ball.pos(), BALL_SIZE)) ball.right_clicked.connect(lambda pos: panel.tray.contextMenu().exec(pos)) + # 全局快捷键 Alt+` 唤醒/隐藏主界面 + from PyQt6.QtGui import QShortcut, QKeySequence + _shortcut = QShortcut(QKeySequence("Alt+`"), panel) + _shortcut.setContext(Qt.ShortcutContext.ApplicationShortcut) + def _toggle_panel(): + if panel.isVisible(): + panel.minimize_to_ball() + else: + panel.show_near(ball.pos(), BALL_SIZE) + _shortcut.activated.connect(_toggle_panel) + has_saved = bool(database.get_setting("panel_x", "")) if has_saved: panel.setWindowOpacity(0) diff --git a/softwares/InnoSetup_92412/InnoSetup-6.7.1_zh_setup.exe b/softwares/InnoSetup_92412/InnoSetup-6.7.1_zh_setup.exe new file mode 100644 index 0000000..901ca00 Binary files /dev/null and b/softwares/InnoSetup_92412/InnoSetup-6.7.1_zh_setup.exe differ diff --git a/ui/__pycache__/__init__.cpython-313.pyc b/ui/__pycache__/__init__.cpython-313.pyc index b5fd8a8..5feefff 100644 Binary files a/ui/__pycache__/__init__.cpython-313.pyc and b/ui/__pycache__/__init__.cpython-313.pyc differ diff --git a/ui/__pycache__/ball.cpython-313.pyc b/ui/__pycache__/ball.cpython-313.pyc index da4eca8..2d4a476 100644 Binary files a/ui/__pycache__/ball.cpython-313.pyc and b/ui/__pycache__/ball.cpython-313.pyc differ diff --git a/ui/__pycache__/dialog_style.cpython-313.pyc b/ui/__pycache__/dialog_style.cpython-313.pyc index b8d10bd..0167c4a 100644 Binary files a/ui/__pycache__/dialog_style.cpython-313.pyc and b/ui/__pycache__/dialog_style.cpython-313.pyc differ diff --git a/ui/__pycache__/dock.cpython-313.pyc b/ui/__pycache__/dock.cpython-313.pyc index 372abeb..2a4ba7f 100644 Binary files a/ui/__pycache__/dock.cpython-313.pyc and b/ui/__pycache__/dock.cpython-313.pyc differ diff --git a/ui/__pycache__/flow_layout.cpython-313.pyc b/ui/__pycache__/flow_layout.cpython-313.pyc index 40bbfa3..ac9a412 100644 Binary files a/ui/__pycache__/flow_layout.cpython-313.pyc and b/ui/__pycache__/flow_layout.cpython-313.pyc differ diff --git a/ui/__pycache__/group.cpython-313.pyc b/ui/__pycache__/group.cpython-313.pyc index 1908be3..f25aa4f 100644 Binary files a/ui/__pycache__/group.cpython-313.pyc and b/ui/__pycache__/group.cpython-313.pyc differ diff --git a/ui/__pycache__/item.cpython-313.pyc b/ui/__pycache__/item.cpython-313.pyc index 3b2955f..1a6b05b 100644 Binary files a/ui/__pycache__/item.cpython-313.pyc and b/ui/__pycache__/item.cpython-313.pyc differ diff --git a/ui/__pycache__/settings_window.cpython-313.pyc b/ui/__pycache__/settings_window.cpython-313.pyc index 11558ac..38249a9 100644 Binary files a/ui/__pycache__/settings_window.cpython-313.pyc and b/ui/__pycache__/settings_window.cpython-313.pyc differ diff --git a/ui/__pycache__/theme.cpython-313.pyc b/ui/__pycache__/theme.cpython-313.pyc index ddf896c..f0854c6 100644 Binary files a/ui/__pycache__/theme.cpython-313.pyc and b/ui/__pycache__/theme.cpython-313.pyc differ diff --git a/ui/dock.py b/ui/dock.py index a26ebb0..52ae88e 100644 --- a/ui/dock.py +++ b/ui/dock.py @@ -22,6 +22,7 @@ from PyQt6.QtWidgets import ( QLabel, QMessageBox, QGridLayout, + QFrame, ) from PyQt6.QtCore import ( Qt, @@ -41,6 +42,61 @@ import ui.dialog_style as dialog_style from ui.updater import Updater from app_info import app_title + +class _ThemedTooltip(QFrame): + """跟随主题颜色的自定义 tooltip,替代系统黑色气泡。""" + def __init__(self, text: str): + super().__init__(None, Qt.WindowType.ToolTip | Qt.WindowType.FramelessWindowHint) + self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground) + self.setAttribute(Qt.WidgetAttribute.WA_ShowWithoutActivating) + self._lbl = QLabel(text, self) + self._lbl.setObjectName("tip_label") + lay = QVBoxLayout(self) + lay.setContentsMargins(0, 0, 0, 0) + lay.addWidget(self._lbl) + + def refresh_style(self): + t = theme.current() + is_dark = theme.name() == "dark" + bg = "#2d2d2d" if is_dark else "#ffffff" + fg = "#eeeeee" if is_dark else "#111111" + bd = t.get("search_border", "#888") + self._lbl.setStyleSheet( + f"QLabel#tip_label {{" + f"background:{bg}; color:{fg}; border:1px solid {bd};" + f"border-radius:6px; padding:5px 9px; font-size:12px;}}" + ) + + +def _install_themed_tooltip(btn: QPushButton, text: str): + """给按钮安装自定义 tooltip,完全替换系统气泡。""" + btn.setToolTip("") + tip = _ThemedTooltip(text) + timer = QTimer() + timer.setSingleShot(True) + + def _show(): + tip.refresh_style() + tip.adjustSize() + pos = QCursor.pos() + tip.move(pos.x() + 14, pos.y() + 22) + tip.show() + tip.raise_() + + def _enter(_e): + timer.start(400) + + def _leave(_e): + timer.stop() + tip.hide() + + timer.timeout.connect(_show) + btn.enterEvent = _enter + btn.leaveEvent = _leave + btn._tip = tip # 防 GC + btn._ttimer = timer # 防 GC + + PANEL_W = 260 PANEL_H = 40 MIN_W, MIN_H = 400, 5 @@ -548,10 +604,9 @@ class PanelWindow(QWidget): for tooltip, icon_name, callback in self._get_quick_actions(): btn = QPushButton() btn.setFixedSize(34, 34) - btn.setToolTip(tooltip) + _install_themed_tooltip(btn, tooltip) btn.setStyleSheet("border:none; background:transparent; border-radius:4px;") btn.setMouseTracking(True) - # 鼠标落在按钮上时,也要能触发边缘检测/resize btn.installEventFilter(self) try: btn.setIcon(qta.icon(icon_name, color="#888")) @@ -712,7 +767,7 @@ class PanelWindow(QWidget): self.menu_btn = QPushButton() self.menu_btn.setFixedSize(28, 28) - self.menu_btn.setToolTip("菜单") + _install_themed_tooltip(self.menu_btn, "菜单") self.menu_btn.setStyleSheet( "border:none; background:transparent; border-radius:4px;" ) @@ -720,7 +775,7 @@ class PanelWindow(QWidget): self.theme_btn = QPushButton() self.theme_btn.setFixedSize(28, 28) - self.theme_btn.setToolTip("切换亮/暗主题") + _install_themed_tooltip(self.theme_btn, "切换亮/暗主题") self.theme_btn.setStyleSheet( "border:none; background:transparent; border-radius:4px;" ) @@ -728,7 +783,7 @@ class PanelWindow(QWidget): self.settings_btn = QPushButton() self.settings_btn.setFixedSize(28, 28) - self.settings_btn.setToolTip("设置") + _install_themed_tooltip(self.settings_btn, "设置") self.settings_btn.setStyleSheet( "border:none; background:transparent; border-radius:4px;" ) @@ -736,7 +791,7 @@ class PanelWindow(QWidget): self.quit_btn = QPushButton() self.quit_btn.setFixedSize(28, 28) - self.quit_btn.setToolTip("退出程序") + _install_themed_tooltip(self.quit_btn, "退出程序") self.quit_btn.setStyleSheet( "border:none; background:transparent; border-radius:4px;" ) @@ -746,7 +801,7 @@ class PanelWindow(QWidget): bottom_layout.addStretch() self.update_btn = QPushButton() self.update_btn.setFixedSize(28, 28) - self.update_btn.setToolTip("检查更新") + _install_themed_tooltip(self.update_btn, "检查更新") self.update_btn.setStyleSheet("border:none; background:transparent; border-radius:4px;") self.update_btn.clicked.connect(lambda: self._updater.check(silent_if_latest=False)) bottom_layout.addWidget(self.update_btn) @@ -903,15 +958,26 @@ class PanelWindow(QWidget): def _apply_tooltip_theme(self, t: dict, is_dark: bool): """让所有控件 tooltip 跟随主题(含快捷栏按钮)。""" + from PyQt6.QtGui import QPalette, QColor + from PyQt6.QtWidgets import QToolTip + app = QApplication.instance() if app is None: return - bg = "rgba(45,45,45,245)" if is_dark else "rgba(255,255,255,250)" - fg = "#eeeeee" if is_dark else "#111111" - bd = t.get("menu_border") or t.get("search_border") or t.get("panel_border") or "#666" + bg = "#2d2d2d" if is_dark else "#ffffff" + fg = "#eeeeee" if is_dark else "#111111" + bd = t.get("menu_border") or t.get("search_border") or "#666" + + # 通过 palette 强制覆盖 tooltip 颜色(Windows 上 stylesheet 单独不够) + palette = app.palette() + palette.setColor(QPalette.ColorRole.ToolTipBase, QColor(bg)) + palette.setColor(QPalette.ColorRole.ToolTipText, QColor(fg)) + app.setPalette(palette) + + # stylesheet 同步设置(双保险) start = "/*TOOLTIP_THEME_START*/" - end = "/*TOOLTIP_THEME_END*/" + end = "/*TOOLTIP_THEME_END*/" tooltip_css = ( f"{start}\n" "QToolTip {\n" @@ -921,19 +987,17 @@ class PanelWindow(QWidget): " border-radius: 6px;\n" " padding: 6px 8px;\n" " font-size: 12px;\n" + " opacity: 240;\n" "}\n" f"{end}\n" ) - ss = app.styleSheet() or "" if start in ss and end in ss: - pre = ss.split(start, 1)[0] - post = ss.split(end, 1)[1] - ss = pre + tooltip_css + post + pre = ss.split(start, 1)[0] + post = ss.split(end, 1)[1] + ss = pre + tooltip_css + post else: - if ss and not ss.endswith("\n"): - ss += "\n" - ss += tooltip_css + ss = (ss + "\n" if ss and not ss.endswith("\n") else ss) + tooltip_css app.setStyleSheet(ss) def _quit_application(self): diff --git a/ui/settings_window.py b/ui/settings_window.py index ade3156..384e3f9 100644 --- a/ui/settings_window.py +++ b/ui/settings_window.py @@ -54,6 +54,7 @@ class SettingsWindow(QDialog): ("fa5s.rocket", "启动"), ("fa5s.folder-open", "缓存"), ("fa5s.heart", "捐赠"), + ("fa5s.info-circle", "关于"), ("fa5s.eraser", "初始化"), ] self._nav_ready = False @@ -79,6 +80,7 @@ class SettingsWindow(QDialog): self.stack.addWidget(self._page_startup()) self.stack.addWidget(self._page_cache()) self.stack.addWidget(self._page_donate()) + self.stack.addWidget(self._page_about()) self.stack.addWidget(self._page_initialization()) # 此时 stack 已就绪,允许导航回调正常工作 self._nav_ready = True @@ -241,11 +243,24 @@ class SettingsWindow(QDialog): self._autostart_check.toggled.connect(self._on_autostart) layout.addWidget(self._autostart_check) - layout.addWidget(self._divider()) + layout.addStretch() + return page + + def _page_about(self) -> QWidget: + page = QWidget() + layout = QVBoxLayout(page) + layout.setContentsMargins(24, 20, 24, 20) + layout.setSpacing(16) + layout.addWidget(self._section_title("关于")) - about = QLabel(f"{APP_NAME} v{__VERSION__}\n整理你的桌面快捷方式,保持桌面干净。") - about.setStyleSheet("color:#888; font-size:12px; line-height:1.6;") + about = QLabel( + f"{APP_NAME} v{__VERSION__}

" + "整理你的桌面快捷方式,保持桌面干净。

" + "快捷键:Alt + ` 唤醒 / 隐藏主界面" + ) + about.setStyleSheet("color:#888; font-size:12px; line-height:1.8;") + about.setTextFormat(Qt.TextFormat.RichText) layout.addWidget(about) layout.addStretch()