import sys import os import time from PyQt6.QtCore import Qt from PyQt6.QtWidgets import QApplication from db.database import init_db from ui.dock import PanelWindow, _set_autostart from ui.ball import FloatBall, BALL_SIZE import ui.theme as theme from db import database __VERSION__ = "0.0.3" # ===================== 打包兼容核心函数 ===================== def get_resource_path(relative_path): """ 打包 EXE 后获取资源路径,开发环境也能用 """ if hasattr(sys, '_MEIPASS'): return os.path.join(sys._MEIPASS, relative_path) return os.path.join(os.path.abspath("."), relative_path) # ========================================================== def _wake_existing_or_exit() -> bool: """ Windows 单实例: - 若已有进程在运行:唤醒已有窗口并返回 False(当前进程退出) - 若无已有进程:返回 True(继续正常启动) """ if sys.platform != "win32": return True import ctypes import ctypes.wintypes mutex_name = r"Global\CleanDesktopOrganizerSingleton" title = "牛马软件柜 v" + __VERSION__ kernel32 = ctypes.windll.kernel32 user32 = ctypes.windll.user32 ERROR_ALREADY_EXISTS = 183 h_mutex = kernel32.CreateMutexW(None, False, mutex_name) if not h_mutex: return True last_err = kernel32.GetLastError() if last_err == ERROR_ALREADY_EXISTS: hwnd = None for _ in range(8): hwnd = user32.FindWindowW(None, title) if hwnd: break time.sleep(0.3) if hwnd: user32.ShowWindow(hwnd, 5) user32.SetForegroundWindow(hwnd) return False return True def main(): if not _wake_existing_or_exit(): return QApplication.setAttribute(Qt.ApplicationAttribute.AA_Use96Dpi, True) try: QApplication.setHighDpiScaleFactorRoundingPolicy( Qt.HighDpiScaleFactorRoundingPolicy.PassThrough ) except Exception: pass app = QApplication(sys.argv) app.setQuitOnLastWindowClosed(False) init_db() theme.load() _set_autostart(True) panel = PanelWindow() ball = FloatBall() panel._ball_ref = ball panel._apply_pin_window_layer() ball.clicked.connect(lambda: panel.show_near(ball.pos(), BALL_SIZE)) ball.right_clicked.connect(lambda pos: panel.tray.contextMenu().exec(pos)) has_saved = bool(database.get_setting("panel_x", "")) if has_saved: panel.setWindowOpacity(0) panel.show() panel.raise_() if hasattr(panel, "_ball_ref"): panel._ball_ref.hide() from PyQt6.QtCore import QPropertyAnimation anim = QPropertyAnimation(panel, b"windowOpacity") anim.setDuration(180) anim.setStartValue(0.0) anim.setEndValue(1.0) anim.start() panel._anim = anim else: ball._place_default() panel.show_near(ball.pos(), BALL_SIZE) sys.exit(app.exec()) if __name__ == "__main__": main()