# 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 . from PySide6.QtCore import Qt, Signal, QTimer from PySide6.QtWidgets import QVBoxLayout, QHBoxLayout, QWidget, QFileDialog from qfluentwidgets import PushButton, FluentIcon, PrimaryPushButton, IconWidget, BodyLabel, \ SpinBox, HyperlinkButton from module.picker.schema import PickerExcel, PickerStudent from ui import MAIN_THEME_COLOR from ui.components.widget import Widget, MyGroupHeaderCardWidget from ui.pyui.sub.picker import PickStudentLabelUi from utils.function import open_template class PickStudentMode(QWidget): errorSignal = Signal(str) def __init__(self, parent=None): super().__init__(parent) self.card = MyGroupHeaderCardWidget(self) self.vbox = QVBoxLayout(self) self.vbox.setContentsMargins(0, 0, 0, 0) self.btnHBox = QHBoxLayout(self) self.openTemplateBtn = HyperlinkButton("", "下载模板") self.chooseBtn = PushButton("打开") self.startButton = PrimaryPushButton(FluentIcon.PLAY_SOLID, "开始") self.bottomLayout = QHBoxLayout() self.hintIcon = IconWidget(FluentIcon.INFO.icon(color=MAIN_THEME_COLOR)) self.hintLabel = BodyLabel("点击开始按钮以开始抽签 👉") self.spinbox = SpinBox() self.psui = PickStudentLabelUi(self) self.card.setTitle("输入选项") self.chooseBtn.setFixedWidth(120) self.startButton.setFixedWidth(120) self.startButton.setEnabled(False) self.spinbox.setRange(0, 6) self.spinbox.setFixedWidth(120) self.spinbox.setEnabled(False) self.psui.hide() self.hintIcon.setFixedSize(16, 16) self.hintIcon.autoFillBackground() self.bottomLayout.setSpacing(10) self.bottomLayout.setContentsMargins(24, 15, 24, 20) self.bottomLayout.addWidget(self.hintIcon, 0, Qt.AlignLeft) self.bottomLayout.addWidget(self.hintLabel, 0, Qt.AlignLeft) self.bottomLayout.addStretch(1) self.bottomLayout.addWidget(self.startButton, 0, Qt.AlignRight) self.bottomLayout.setAlignment(Qt.AlignVCenter) self.btnHBox.addWidget(self.openTemplateBtn) self.btnHBox.addWidget(self.chooseBtn) self.group = self.card.addGroup(FluentIcon.DOCUMENT, "学生名单", "选择学生名单", self.btnHBox) self.spinGroup = self.card.addGroup(FluentIcon.SETTING, "提问次数", "设置提问的最大次数", self.spinbox) self.spinGroup.setSeparatorVisible(True) self.card.vBoxLayout.addLayout(self.bottomLayout) self.vbox.addWidget(self.card) self.vbox.addWidget(self.psui) self.vbox.addStretch(1) # ============================== self.chooseBtn.clicked.connect(self.choose_file) self.spinbox.valueChanged.connect(lambda: PickerExcel.save_total_time(value=self.spinbox.value())) self.startButton.clicked.connect(self.start_rolling) self.psui.rollingText.finishSignal.connect(self.finish_rolling) self.openTemplateBtn.clicked.connect(lambda: open_template("template-pick-student.xlsm", self)) # ============================== self.filepath = "" self.students = [] def choose_file(self): file_path, _ = QFileDialog.getOpenFileName(self, "选择文件", "", "Excel 文件 (*.xlsm);") if file_path: self.group.setContent("已选择文件:" + file_path) self.filepath = file_path self.startButton.setEnabled(True) self.init_spinbox_value() def init_spinbox_value(self): if not self.filepath: return try: PickerExcel.open(self.filepath) self.spinbox.setValue(PickerExcel.read_total_time()) self.spinbox.setEnabled(True) except Exception as e: self.errorSignal.emit(str(e)) self.spinbox.setEnabled(False) self.startButton.setEnabled(False) def start_rolling(self): self.students = PickerExcel.read_student() self.psui.show() self.psui.rollingText.set_items(self.students) self.psui.rollingText.start_rolling() self.startButton.setEnabled(False) def finish_rolling(self): stu = PickerStudent.pick(self.students) if not (stu.so and stu.name): self.errorSignal.emit("学生信息读取失败") self.psui.rollingText.show_result(stu) timer = QTimer(self) timer.setSingleShot(True) timer.timeout.connect(lambda: self.show_screen(stu)) timer.start(1000) def show_screen(self, stu: PickerStudent): self.psui.show_scoring() self.psui.scoring.submitSignal.connect(lambda score: self.scoring_finished(score, stu)) def scoring_finished(self, score: int, student: PickerStudent): student.append_score(score) PickerExcel.write_back(student) self.psui.hide() self.startButton.setEnabled(True) class PickerWidget(Widget): errorSignal = Signal(str, str) def __init__(self, key: str, parent=None): super().__init__(key, parent) self.vbox = QVBoxLayout(self) self.psm = PickStudentMode(self) self.vbox.addWidget(self.psm) self.vbox.addStretch(1) # =========================== self.psm.errorSignal.connect(lambda n: self.errorSignal.emit("😢 不好出错了", n))