# Copyright (c) 2025 Jeffrey Hsu - JITToolBox # # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import os from dataclasses import dataclass from typing import Callable from PySide6.QtGui import QIcon, QShowEvent from qfluentwidgets import FluentIcon, MSFluentWindow, NavigationItemPosition, MessageBox, setThemeColor from ui import MAIN_THEME_COLOR, BLUE_BACKGROUND_COLOR from ui.pyui.about_ui import AboutWidget from ui.pyui.achievement_ui import AchievementWidget from ui.pyui.defense_ui import DefenseWidget from ui.pyui.picker_ui import PickerWidget from ui.pyui.test_ui import TestWidget from utils.function import RELEASE_ENV @dataclass(frozen=True) class InterfaceSpec: key: str factory: Callable[[], object] icon: FluentIcon nav_text: str position: NavigationItemPosition = NavigationItemPosition.TOP enabled: bool = True class MainWindow(MSFluentWindow): def __init__(self): super().__init__() setThemeColor(MAIN_THEME_COLOR) self.setCustomBackgroundColor(BLUE_BACKGROUND_COLOR, BLUE_BACKGROUND_COLOR) self.interface_specs = self.build_interface_specs() self.interfaces = self.create_interfaces(self.interface_specs) self.bind_error_handlers() self.initNavigation() self.initWindow() def build_interface_specs(self) -> list[InterfaceSpec]: return [ InterfaceSpec( key="achievement", factory=lambda: AchievementWidget('Achievement Interface', self), icon=FluentIcon.SPEED_HIGH, nav_text='达成度', enabled=True, ), InterfaceSpec( key="defense", factory=lambda: DefenseWidget('Defense Interface', self), icon=FluentIcon.FEEDBACK, nav_text='答辩', enabled=True, ), InterfaceSpec( key="picker", factory=lambda: PickerWidget('Picker Interface', self), icon=FluentIcon.PEOPLE, nav_text='提问', enabled=not RELEASE_ENV, ), InterfaceSpec( key="test", factory=lambda: TestWidget('Test Interface', self), icon=FluentIcon.VIEW, nav_text='测试', enabled=not RELEASE_ENV, ), InterfaceSpec( key="about", factory=lambda: AboutWidget('About Interface', self), icon=FluentIcon.INFO, nav_text='关于', position=NavigationItemPosition.BOTTOM, enabled=True ), ] def create_interfaces(self, specs: list[InterfaceSpec]) -> dict[str, object]: interfaces: dict[str, object] = {} for spec in specs: if not spec.enabled: continue widget = spec.factory() interfaces[spec.key] = widget setattr(self, f"{spec.key}Interface", widget) return interfaces def bind_error_handlers(self): achievement = self.interfaces.get("achievement") defense = self.interfaces.get("defense") if achievement and hasattr(achievement, "error"): achievement.error.connect(self.showError) if defense and hasattr(defense, "errorSignal"): defense.errorSignal.connect(self.showError) def initNavigation(self): for spec in self.interface_specs: widget = self.interfaces.get(spec.key) if not widget: continue self.addSubInterface(widget, spec.icon, spec.nav_text, position=spec.position) def initWindow(self): self.resize(900, 700) self.setWindowTitle('教学工具箱') self.setWindowIcon(QIcon(':/images/logo.png')) def showError(self, title: str, message: str): box = MessageBox(title, message, self) box.yesButton.setText("关闭") box.cancelButton.hide() box.exec() def showEvent(self, event: QShowEvent): super().showEvent(event) if RELEASE_ENV: import pyi_splash pyi_splash.update_text('正在加载...') pyi_splash.close()