Files
JITToolBox/ui/pyui/achievement_ui.py
2025-06-28 18:45:20 +08:00

241 lines
8.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import os
from functools import wraps
from typing import Callable, Literal
from PySide6.QtCore import Qt, Signal, QThread
from PySide6.QtWidgets import QVBoxLayout, QFileDialog, QHBoxLayout
from qfluentwidgets import GroupHeaderCardWidget, FluentIcon, PushButton, LineEdit, IconWidget, BodyLabel, \
PrimaryPushButton, SwitchButton
from module import LOGLEVEL
from module.worker import ARGWorker
from ui import MAIN_THEME_COLOR
from ui.components.infobar import ProgressInfoBar
from ui.components.widget import Widget
class InputSettingCard(GroupHeaderCardWidget):
chooseSignal = Signal(str)
def __init__(self, parent=None):
super().__init__(parent)
self.setTitle("输入选项")
self.setBorderRadius(8)
self.chooseFileButton = PushButton("打开")
self.chooseFileButton.setFixedWidth(120)
self.inputGroup = self.addGroup(FluentIcon.DOCUMENT, "目标文件", "选择达成度计算表", self.chooseFileButton)
# ============================
self.chooseFileButton.clicked.connect(self.choose_file)
def choose_file(self):
file_path, _ = QFileDialog.getOpenFileName(self, "选择文件", "", "Excel 文件 (*.xlsm);")
if file_path:
self.inputGroup.setContent("已选择文件:" + file_path)
self.chooseSignal.emit(file_path)
class OutputSettingCard(GroupHeaderCardWidget):
updateSignal = Signal(str, str)
startSignal = Signal()
def __init__(self, parent=None):
super().__init__(parent)
self.setTitle("输出选项")
self.setBorderRadius(8)
self.chooseExportDirectoryButton = PushButton("选择")
self.exportFileNameLineEdit = LineEdit()
self.startButton = PrimaryPushButton(FluentIcon.PLAY_SOLID, "开始")
self.autoOpenSwitch = SwitchButton()
self.disableCompatibilityCheckSwitch = SwitchButton()
self.autoOpenSwitch.setChecked(True)
self.bottomLayout = QHBoxLayout()
self.hintIcon = IconWidget(FluentIcon.INFO.icon(color=MAIN_THEME_COLOR))
self.hintLabel = BodyLabel("点击开始按钮以开始生成 👉")
self.startButton.setEnabled(False)
# 设置底部工具栏布局
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.chooseExportDirectoryButton.setFixedWidth(120)
self.exportFileNameLineEdit.setPlaceholderText("请输入文件名")
self.startButton.setFixedWidth(120)
self.exportFileNameLineEdit.setFixedWidth(360)
self.exportFileNameLineEdit.setPlaceholderText("输入导出文件名例如21工程管理1达成度报告")
self.dirGroup = self.addGroup(FluentIcon.FOLDER, "导出目录", "选择导出文件的目录",
self.chooseExportDirectoryButton)
self.fnGroup = self.addGroup(FluentIcon.DOCUMENT, "导出文件名", "输入导出文件名", self.exportFileNameLineEdit)
self.aoGroup = self.addGroup(FluentIcon.VIEW, "自动打开", "生成完成后自动打开文件", self.autoOpenSwitch)
self.ccGroup = self.addGroup(FluentIcon.DEVELOPER_TOOLS, "关闭兼容性检查",
"⚠ 注意:该功能为实验性内容,仅当你明确了解其影响并知道自己在做什么时,才建议关闭兼容性检查!",
self.disableCompatibilityCheckSwitch)
self.ccGroup.setSeparatorVisible(True)
self.vBoxLayout.addLayout(self.bottomLayout)
# =============================
self.chooseExportDirectoryButton.clicked.connect(self.choose_dir)
self.startButton.clicked.connect(self.startSignal)
def choose_dir(self) -> None:
dir_path = QFileDialog.getExistingDirectory(self, "选择文件夹", "")
if dir_path:
self.dirGroup.setContent(f"当前保存的文件目录:{dir_path}")
self.updateSignal.emit('d', dir_path)
def update_path_and_filename_by_input_path(self, path: str):
dir_path = path[:path.rfind("/")]
self.dirGroup.setContent(f"已选择目录:{dir_path}")
self.updateSignal.emit('d', dir_path)
file_name = path[path.rfind("/") + 1:path.rfind(".")] + "-达成度报告"
self.exportFileNameLineEdit.setText(file_name)
self.updateSignal.emit('f', file_name)
class AchievementWidget(Widget):
error = Signal(str, str)
def __init__(self, key: str, parent=None):
super().__init__(key, parent)
self.inputGroup = InputSettingCard(self)
self.outputGroup = OutputSettingCard(self)
self.vbox = QVBoxLayout(self)
self.vbox.addWidget(self.inputGroup)
self.vbox.addWidget(self.outputGroup)
self.vbox.addStretch(1)
# =================================
self.pib = ProgressInfoBar(parent=self, isClosable=False, duration=-1)
self.pib.hide()
# =================================
self.thread = None
self.worker = None
self.successFlag = True
# ==================================
self.input_file_path = ""
self.output_file_path = ""
self.output_file_name = ""
# ==================================
self.inputGroup.chooseSignal.connect(self.input_signal_receive)
self.outputGroup.updateSignal.connect(self.export_signal_receive)
self.outputGroup.startSignal.connect(self.start_generate)
def enable_start_check(func: Callable):
@wraps(func)
def wrapper(self, *args, **kwargs):
result = func(self, *args, **kwargs)
fields = [
self.input_file_path,
self.output_file_path,
self.output_file_name,
]
if all(fields):
self.outputGroup.startButton.setEnabled(True)
else:
self.outputGroup.startButton.setEnabled(False)
return result
return wrapper
@enable_start_check
def set_value(
self,
key: Literal['input_file_path', 'output_file_path', 'output_file_name'],
value: str
) -> None:
setattr(self, key, value)
def input_signal_receive(self, file_path: str) -> None:
self.set_value('input_file_path', file_path)
self.outputGroup.update_path_and_filename_by_input_path(file_path)
def export_signal_receive(self, s_type: Literal['d', 'f'], value: str) -> None:
if s_type == 'd':
self.set_value('output_file_path', value)
elif s_type == 'f':
self.set_value('output_file_name', value)
def start_generate(self):
self.thread = QThread()
self.worker = ARGWorker(
self.input_file_path,
self.output_file_path,
self.output_file_name,
disable_cc=self.outputGroup.disableCompatibilityCheckSwitch.isChecked()
)
self.worker.moveToThread(self.thread)
self.outputGroup.startButton.setEnabled(False)
self.thread.started.connect(self.worker.run)
self.show_info_bar()
self.successFlag = True
self.worker.info.connect(self.show_info)
self.worker.error.connect(self.show_error)
self.worker.finished.connect(self.thread.quit)
self.worker.finished.connect(self.worker.deleteLater)
self.thread.finished.connect(self.thread.deleteLater)
self.thread.finished.connect(self.clear_thread_worker_refs)
self.thread.finished.connect(self.after_generate)
# 启动线程
self.thread.start()
def clear_thread_worker_refs(self):
self.thread = None
self.worker = None
def after_generate(self):
if self.outputGroup.autoOpenSwitch.isChecked() and self.successFlag:
try:
os.startfile(self.output_file_path + "/" + self.output_file_name + ".docx")
except Exception as e:
self.show_error("?? 不好出错了", str(e))
if self.successFlag:
self.pib.show_success(
content="正在打开文件" if self.outputGroup.autoOpenSwitch.isChecked() else "文件已保存")
else:
self.pib.show_error()
self.outputGroup.startButton.setEnabled(True)
def show_error(self, title: str, content: str):
self.successFlag = False
self.error.emit(title, content)
def show_info_bar(self):
self.pib.set_title('请稍后')
self.pib.show()
self.pib.set_progress(101)
def show_info(self, content: str, level: str):
if level == LOGLEVEL.INFO:
self.pib.set_title(content)