138 lines
4.8 KiB
Python
138 lines
4.8 KiB
Python
# 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 <https://www.gnu.org/licenses/>.
|
|
|
|
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()
|