Files
JITToolBox/ui/main.py

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()