from pathlib import Path from random import choice from shutil import copy import requests import json import sys from PySide6.QtWidgets import QApplication, QWidget, QHBoxLayout, QMessageBox, QMainWindow, QStatusBar from PySide6.QtGui import QIcon, QResizeEvent, QShortcut, QKeySequence, QAction from PySide6.QtCore import Qt, QFileSystemWatcher from codes.common import clibs, db_operation from codes.ui.components.toolbar_ui import SToolBar from codes.ui.components.list_widget_ui import SListWidget from codes.ui.components.stacked_widget_ui import SStackedWidget from codes.ui.components.statusbar_ui import SStatusBar from codes.common.signal_bus import signal_bus from codes.common.worker import Worker from codes.common.exception_handler import handle_exception from codes.ui.overlay_page.overlay_ui import WidgetWithBg class MainWindow(QMainWindow): def __init__(self): super().__init__() self.pre_do() self.init_ui() self.post_do() def pre_do(self): self.m = Path(__file__).stem self.home_overlay = None db_operation.db_backup() db_operation.db_conn() def init_ui(self): self.setObjectName("MainWindow") self.setMinimumSize(clibs.win_width, clibs.win_height) self.resize(clibs.win_width, clibs.win_height) self.setWindowTitle("Toolbox") self.setWindowIcon(QIcon(f"{clibs.base_path}/assets/media/icon.ico")) # 任务栏/主窗口/状态栏 self.toolBar = SToolBar() self.addToolBar(self.toolBar) self.toolBar.setMovable(False) self.centralW = QWidget() self.setCentralWidget(self.centralW) self.statusBar = SStatusBar() self.setStatusBar(self.statusBar) layout_h = QHBoxLayout() # list widget self.listW = SListWidget() layout_h.addWidget(self.listW, stretch=1) self.stackedW =SStackedWidget() layout_h.addWidget(self.stackedW, stretch=5) self.centralW.setLayout(layout_h) def setup_slot(self): signal_bus.home_overlay_trigger.connect(self.ac_hp) signal_bus.home_overlay_close.connect(self.exit_overlay) self.install_sc() def post_do(self): self.setup_slot() self.setup_sc() def setup_sc(self, enable: bool = True): for sc_id, obj in self.sc_pool.items(): if isinstance(obj, QAction): obj.setEnabled(enable) elif isinstance(obj, QShortcut): obj.setEnabled(enable) if enable == False and (sc_id == "esc" or sc_id == "ctrl_alt_m") and self.home_overlay: obj.setEnabled(True) if (sc_id == "esc" or sc_id == "ctrl_alt_m") and self.home_overlay is None: obj.setEnabled(False) def install_sc(self): self.sc_pool = {} # QAction self.toolBar.ac_switch.setShortcut(QKeySequence("Ctrl+Alt+T")) self.sc_pool["ctrl_alt_t"] = self.toolBar.ac_switch self.toolBar.ac_homepage.setShortcut(QKeySequence("Ctrl+Alt+H")) self.sc_pool["ctrl_alt_h"] = self.toolBar.ac_homepage self.toolBar.ac_setting.setShortcut(QKeySequence("Ctrl+Alt+S")) self.sc_pool["ctrl_alt_s"] = self.toolBar.ac_setting self.toolBar.ac_log.setShortcut(QKeySequence("Ctrl+Alt+L")) self.sc_pool["ctrl_alt_l"] = self.toolBar.ac_log self.toolBar.ac_about.setShortcut(QKeySequence("Ctrl+Alt+A")) self.sc_pool["ctrl_alt_a"] = self.toolBar.ac_about # QShortcut self.sc_f11 = QShortcut(QKeySequence("F11"), self) self.sc_f11.activated.connect(self.shortcut_f11) self.sc_pool["f11"] = self.sc_f11 # Subpage self.sc_Esc = QShortcut(QKeySequence("Esc"), self) self.sc_Esc.activated.connect(signal_bus.home_overlay_auth.emit) self.sc_pool["esc"] = self.sc_Esc self.sc_caM = QShortcut(QKeySequence("Ctrl+Alt+M"), self) self.sc_caM.activated.connect(self.toggle_full_screen) self.sc_pool["ctrl_alt_m"] = self.sc_caM def ac_hp(self): def get_files(dir_path): folder = Path(dir_path) files = [p for p in folder.rglob("*") if p.is_file()] if files: rand_choice = choice(files) else: rand_choice = "" return rand_choice, files def del_repeat_proverb(proverbs: list): _proverbs = [] for proverb in proverbs: if proverb not in _proverbs: _proverbs.append(proverb) return _proverbs @handle_exception() def get_resources(): # background image bing = "https://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=8" req = requests.get(bing) res = req.json() _, files = get_files(f"{clibs.base_path}/assets/media/bg") image_names = [] for file in files: image_names.append(file.name.removesuffix(".jpg")) for image in res["images"]: image_name = "-".join([image["startdate"], image["hsh"]]) if image_name in image_names: continue else: image_url = f"""https://www.bing.com{image["url"]}""" file = Path(f"{clibs.base_path}/assets/media/bg/{image_name}.jpg") req = requests.get(image_url, stream=True, timeout=10) with open(file, "wb") as f: for chunk in req.iter_content(chunk_size=8192): f.write(chunk) # proverbs hitokoto = "https://v1.hitokoto.cn/" proverbs = [] proverb_file = Path(f"{clibs.base_path}/assets/media/hitokoto.json") req = requests.get(hitokoto) if not proverb_file.exists(): proverb_file.touch() proverb_file.write_text("[]") with open(proverb_file, "w") as f: f.write("[]") with open(proverb_file, mode="rt", encoding="utf-8") as f: proverbs = json.load(f) proverb = json.loads(req.text) if None in proverb.values(): for k, v in proverb.items(): if v is None: if v == "from_who": proverb.update({k: "佚名"}) elif v == "from": proverb.update({k: "不知道"}) else: proverb.update({k: "-"}) proverbs.append(proverb) proverbs = del_repeat_proverb(proverbs) with open(proverb_file, mode="wt", encoding="utf-8") as f: json.dump(proverbs, f, ensure_ascii=False) @handle_exception() def change_resources(): # avatar src, _ = get_files(f"{clibs.base_path}/assets/media/avatar") dst = f"{clibs.base_path}/assets/media/avatar.jpg" copy(src, dst) # proverbs with open(f"{clibs.base_path}/assets/media/hitokoto.json", mode="r", encoding="utf-8") as f: proverbs = json.load(f) res = choice(proverbs) sentence = res["hitokoto"] from_where = res["from"] from_who = res["from_who"] clibs.proverb = f"{sentence}\t\t※⌈{from_where}⌋ | {from_who}※" # bg src, _ = get_files(f"{clibs.base_path}/assets/media/bg") dst = f"{clibs.base_path}/assets/media/bg.jpg" copy(src, dst) def gen_page(): self.home_overlay = WidgetWithBg(parent=self) self.home_overlay.show() self.setup_sc(False) width, height = self.width(), self.height() if width > clibs.win_width: self.resize(self.width()-1, self.height()-1) else: self.resize(clibs.win_width+1, clibs.win_height+1) change_resources() self.launch_get_resources(get_resources) gen_page() def launch_get_resources(self, func, on_anything=None, *args, **kwargs): self.td_get_resources = Worker(func, *args, **kwargs) self.td_get_resources.started.connect(lambda: None) self.td_get_resources.result.connect(lambda: None) self.td_get_resources.error.connect(lambda: None) self.td_get_resources.finished.connect(lambda: None) self.td_get_resources.start() def toggle_full_screen(self): if self.isFullScreen(): self.setWindowFlags(self.windowFlags() ^ Qt.WindowType.WindowStaysOnTopHint) self.show() self.showMaximized() else: self.setWindowFlags(Qt.WindowType.WindowStaysOnTopHint) self.showFullScreen() def exit_overlay(self): self.home_overlay = None self.setup_sc() if self.isFullScreen(): self.setWindowFlags(self.windowFlags() ^ Qt.WindowType.WindowStaysOnTopHint) self.show() self.showMaximized() def shortcut_f11(self): if not self.home_overlay: self.ac_hp() self.toggle_full_screen() def resizeEvent(self, event: QResizeEvent): super().resizeEvent(event) if self.home_overlay: self.home_overlay.setGeometry(self.rect()) def closeEvent(self, event): if self.isFullScreen(): event.ignore() return reply = QMessageBox.question(self, "退出", "\n程序可能在运行,确定要退出吗?") if reply == QMessageBox.StandardButton.Yes: db_operation.db_close() event.accept() else: event.ignore() if __name__ == '__main__': app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec())