diff --git a/.gitignore b/.gitignore index cd5504d..4c4247c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,34 @@ __pycache__/ *.pyc +*.pyo +*.pyd +.Python +*.so +*.egg +*.egg-info/ +dist/ +build/ *.spec /output - - +.venv/ +venv/ +env/ +.env +.env.local +.idea/ +.vscode/ +*.log +*.swp +*.swo +*~ +.DS_Store +.pytest_cache/ +.coverage +htmlcov/ +.ipynb_checkpoints/ +*.manifest +*.spec +config.json +*.qm +*.ts +*.trae/ \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 294db7d..0000000 --- a/LICENSE +++ /dev/null @@ -1,18 +0,0 @@ -MIT License - -Copyright (c) 2026 feifei.xu - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -associated documentation files (the "Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the -following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial -portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT -LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO -EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 407a214..c7d5374 100644 --- a/README.md +++ b/README.md @@ -1,2 +1 @@ # Model_Team_Tools - diff --git a/build.py b/build.py new file mode 100644 index 0000000..bdea196 --- /dev/null +++ b/build.py @@ -0,0 +1,72 @@ +import os +import sys +import glob +import platform +import subprocess +from pathlib import Path +from zipfile import ZIP_DEFLATED, ZipFile + +from main import APP_NAME, APP_VERSION + +COMPILER = "mingw64" +OUTPUT_PATH = Path('output') +RESOURCES_PATH = Path("resources") +RELEASE_PATH = OUTPUT_PATH / APP_NAME + +BUILD_PATH = OUTPUT_PATH / f'{platform.system().lower()}-{platform.machine().lower()}' + + +def build_main(): + nuitka_cmd = [ + 'python', + '-m', + 'nuitka', + '--standalone', + '--show-memory', + '--show-progress', + '--plugin-enable=pyside6', + '--include-module=qt_material', + f"--include-data-dir={RESOURCES_PATH}=resources", + ] + + icon_path = str(RESOURCES_PATH / "main.ico") + if os.path.exists(icon_path): + nuitka_cmd.extend([ + f'--windows-icon-from-ico={icon_path}', + ]) + nuitka_cmd.append(f'--output-dir={BUILD_PATH}') + if platform.system() == 'Windows': + nuitka_cmd.append('--windows-console-mode=disable') + nuitka_cmd.append(f'--{COMPILER}') + + nuitka_cmd.append('./main.py') + + result = subprocess.run(nuitka_cmd,shell=True) + if result.returncode != 0: + raise RuntimeError('Nuitka building failed.') + + print('Building done.') + + +def create_zip(): + file_list = glob.glob(f'{BUILD_PATH / APP_NAME / "dist"}', recursive=True) + file_list.sort() + + if not os.path.exists(RELEASE_PATH): + os.mkdir(RELEASE_PATH) + + portable_file = RELEASE_PATH / f'{APP_NAME}-{platform.system()}-{platform.machine()}-{APP_VERSION}.zip' + print('Creating portable package...') + + with ZipFile(portable_file, 'w', compression=ZIP_DEFLATED) as zf: + for file in file_list: + file = Path(file) + name_in_zip = f'{APP_NAME}/{"/".join(file.parts[3:])}' + print(name_in_zip) + zf.write(file, name_in_zip) + + print('Creating portable package done.') + + +if __name__ == '__main__': + build_main() \ No newline at end of file diff --git a/core/__init__.py b/core/__init__.py new file mode 100644 index 0000000..8ce62a7 --- /dev/null +++ b/core/__init__.py @@ -0,0 +1,18 @@ +""" +Core 模块 - 核心功能模块包 + +本包包含应用程序的核心功能组件: +- 日志系统(logging 包) +- 工具箱系统(tools 包) + +提供统一的接口导出,方便其他模块调用。 + +Author: Model Team +Version: 0.0.1 +""" + +from .logging.log import FrameLog +from .tools.tools import ToolsWindow # FromTools → ToolsWindow + +__all__ = ["FrameLog", "ToolsWindow"] + diff --git a/core/logging/log.py b/core/logging/log.py new file mode 100644 index 0000000..881bca1 --- /dev/null +++ b/core/logging/log.py @@ -0,0 +1,209 @@ +""" +日志模块 - 提供统一的日志记录功能 + +功能说明: +- 日志写入文件 (logs/log_file.log) +- 日志输出到控制台 +- 日志显示到 UI 的 TextEdit 组件 + +架构设计: +- 使用组合模式避免 PySide6 QObject.emit() 方法冲突 +- LogHandler: 独立的日志处理器,继承自 logging.Handler +- FrameLog: UI 组件,负责日志配置和显示 + +日志格式:%(asctime)s [%(levelname)s] %(message)s +时间格式:%Y-%m-%d %H:%M:%S +""" + +import logging +from pathlib import Path +from typing import Callable, Optional + +from PySide6.QtCore import QObject, Signal +from PySide6.QtWidgets import QFrame, QTextEdit + +from .log_ui import Ui_FrameLog + +# 日志配置常量 +LOG_FILE = "logs/log_file.log" # 日志文件路径 +CONSOLE_OUTPUT = True # 是否输出到控制台 + + +class LogHandler(logging.Handler): + """ + 独立的日志处理器 + + 继承自 logging.Handler,用于处理日志记录的格式化输出 + 使用回调函数机制避免与 PySide6 QObject.emit() 方法名冲突 + + 设计原因: + - logging.Handler.emit() 和 QObject.emit() 方法签名冲突 + - 使用组合模式,将回调函数作为日志传递的桥梁 + """ + + def __init__(self, callback: Callable[[str], None]) -> None: + """ + 初始化日志处理器 + + Args: + callback: 回调函数,接收格式化后的日志消息字符串 + """ + super().__init__() + self.callback = callback + + def emit(self, record: logging.LogRecord) -> None: + """ + 处理日志记录 + + 当日志系统调用此方法时,将格式化后的日志消息传递给回调函数 + + Args: + record: 日志记录对象,包含级别、消息等信息 + + 异常处理: + - RecursionError: 防止递归调用导致无限循环 + - 其他异常: 使用 handleError 记录错误 + """ + try: + msg = self.format(record) + self.callback(msg) + except RecursionError: + self.handleError(record) + except Exception: + self.handleError(record) + + +class FrameLog(QFrame, Ui_FrameLog): + """ + 日志显示框架组件 + + 继承自 QFrame(Qt 框架组件)和 Ui_FrameLog(自动生成的 UI 界面) + 负责日志系统的配置和 UI 显示功能 + + 功能: + - 初始化日志系统(文件、控制台、UI) + - 将日志消息显示到 TextEdit 组件 + - 通过信号机制实现线程安全的 UI 更新 + """ + + # PySide6 信号定义,用于跨线程传递日志消息 + log_signal = Signal(str) + + def __init__(self, parent: Optional[QObject] = None) -> None: + """ + 初始化日志框架 + + Args: + parent: 父组件对象,默认为 None + """ + QFrame.__init__(self, parent) + self.setupUi(self) + self._init_logging() + self._connect_signal() + + def _init_logging(self) -> None: + """ + 初始化日志系统 + + 配置日志系统的各个组件: + - 设置日志级别为 DEBUG + - 配置日志格式化器 + - 设置文件日志处理器(可选) + - 设置控制台日志处理器(可选) + - 配置 UI 日志处理器 + """ + logger = logging.getLogger() + logger.setLevel(logging.DEBUG) + + # 创建日志格式化器:时间 [级别] 消息 + formatter = logging.Formatter( + "%(asctime)s [%(levelname)s] %(message)s", + datefmt="%Y-%m-%d %H:%M:%S" + ) + + # 配置文件日志处理器(如果启用) + if LOG_FILE: + self._setup_file_handler(logger, formatter) + + # 配置控制台日志处理器(如果启用) + if CONSOLE_OUTPUT: + self._setup_console_handler(logger, formatter) + + # 配置 UI 日志处理器 + self._log_handler = LogHandler(self._update_log_display) + self._log_handler.setFormatter(formatter) + self._log_handler.setLevel(logging.DEBUG) + logger.addHandler(self._log_handler) + + def _setup_file_handler(self, logger: logging.Logger, formatter: logging.Formatter) -> None: + """ + 配置日志文件处理器 + + 将日志写入指定文件,支持 UTF-8 编码 + + Args: + logger: 日志记录器实例 + formatter: 日志格式化器 + + 异常处理: + - OSError: 操作系统错误(如磁盘满) + - PermissionError: 权限不足 + - 失败时降级到控制台输出 + """ + try: + log_path = Path(LOG_FILE) + log_path.parent.mkdir(parents=True, exist_ok=True) + file_handler = logging.FileHandler(log_path, encoding='utf-8') + file_handler.setFormatter(formatter) + file_handler.setLevel(logging.DEBUG) + logger.addHandler(file_handler) + except (OSError, PermissionError) as e: + logging.warning(f"无法创建日志文件 {LOG_FILE}: {e}") + logging.warning("日志将仅输出到控制台") + + def _setup_console_handler(self, logger: logging.Logger, formatter: logging.Formatter) -> None: + """ + 配置日志控制台处理器 + + 将日志输出到标准控制台(stdout) + + Args: + logger: 日志记录器实例 + formatter: 日志格式化器 + + 注意: + - 控制台输出级别设置为 INFO,只显示重要信息 + - DEBUG 级别的日志不会输出到控制台 + """ + console_handler = logging.StreamHandler() + console_handler.setFormatter(formatter) + console_handler.setLevel(logging.INFO) + logger.addHandler(console_handler) + + def _connect_signal(self) -> None: + """ + 连接日志信号到 UI 更新方法 + + 将 log_signal 信号连接到 _update_log_display 方法 + 实现日志消息的线程安全传递 + """ + self.log_signal.connect(self._update_log_display) + + def _update_log_display(self, message: str) -> None: + """ + 更新 UI 的日志显示组件 + + 将日志消息追加到 TextEdit 组件中显示 + + Args: + message: 格式化后的日志消息字符串 + + 实现细节: + - 使用 findChild 查找 TextEdit 组件 + - 使用 append 方法追加日志消息,自动换行 + """ + self.textEdit.append(message) + + # text_edit = self.findChild(QTextEdit, "textEdit") + # if text_edit: + # text_edit.append(message) \ No newline at end of file diff --git a/core/logging/log.ui b/core/logging/log.ui new file mode 100644 index 0000000..fa9722b --- /dev/null +++ b/core/logging/log.ui @@ -0,0 +1,24 @@ + + + FrameLog + + + + 0 + 0 + 982 + 300 + + + + Frame + + + + + + + + + + diff --git a/core/logging/log_ui.py b/core/logging/log_ui.py new file mode 100644 index 0000000..20d1805 --- /dev/null +++ b/core/logging/log_ui.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- + +################################################################################ +## Form generated from reading UI file 'log.ui' +## +## Created by: Qt User Interface Compiler version 6.8.2 +## +## WARNING! All changes made in this file will be lost when recompiling UI file! +################################################################################ + +from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, + QMetaObject, QObject, QPoint, QRect, + QSize, QTime, QUrl, Qt) +from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, + QFont, QFontDatabase, QGradient, QIcon, + QImage, QKeySequence, QLinearGradient, QPainter, + QPalette, QPixmap, QRadialGradient, QTransform) +from PySide6.QtWidgets import (QApplication, QFrame, QGridLayout, QSizePolicy, + QTextEdit, QWidget) + +class Ui_FrameLog(object): + def setupUi(self, FrameLog): + if not FrameLog.objectName(): + FrameLog.setObjectName(u"FrameLog") + FrameLog.resize(982, 300) + self.gridLayout = QGridLayout(FrameLog) + self.gridLayout.setObjectName(u"gridLayout") + self.textEdit = QTextEdit(FrameLog) + self.textEdit.setObjectName(u"textEdit") + + self.gridLayout.addWidget(self.textEdit, 0, 0, 1, 1) + + + self.retranslateUi(FrameLog) + + QMetaObject.connectSlotsByName(FrameLog) + # setupUi + + def retranslateUi(self, FrameLog): + FrameLog.setWindowTitle(QCoreApplication.translate("FrameLog", u"Frame", None)) + # retranslateUi + diff --git a/core/tools/tool_card.py b/core/tools/tool_card.py new file mode 100644 index 0000000..80ae81d --- /dev/null +++ b/core/tools/tool_card.py @@ -0,0 +1,15 @@ + +from PySide6.QtWidgets import QFrame +from .tool_card_ui import Ui_FrameToolCard + + +class ToolCard(QFrame, Ui_FrameToolCard): + """工具卡片类 + + 继承自 QFrame(Qt 帧基类)和 Ui_FrameToolCard(Qt Designer 生成的 UI 界面) + 负责显示工具的卡片界面,包含工具的图标、名称和描述。 + """ + def __init__(self, parent = None) -> None: + super().__init__(parent) + self.setupUi(self) + diff --git a/core/tools/tool_card.ui b/core/tools/tool_card.ui new file mode 100644 index 0000000..a58118b --- /dev/null +++ b/core/tools/tool_card.ui @@ -0,0 +1,90 @@ + + + FrameToolCard + + + + 0 + 0 + 491 + 64 + + + + Frame + + + + + + + + + 0 + 0 + + + + Name + + + + + + + + 0 + 0 + + + + 安装 + + + + + + + + 0 + 0 + + + + 卸载 + + + + + + + + 0 + 0 + + + + 更新 + + + + + + + + + + 0 + 0 + + + + TextLabel + + + + + + + + diff --git a/core/tools/tool_card_ui.py b/core/tools/tool_card_ui.py new file mode 100644 index 0000000..95a85e3 --- /dev/null +++ b/core/tools/tool_card_ui.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- + +################################################################################ +## Form generated from reading UI file 'tool_card.ui' +## +## Created by: Qt User Interface Compiler version 6.11.1 +## +## WARNING! All changes made in this file will be lost when recompiling UI file! +################################################################################ + +from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, + QMetaObject, QObject, QPoint, QRect, + QSize, QTime, QUrl, Qt) +from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, + QFont, QFontDatabase, QGradient, QIcon, + QImage, QKeySequence, QLinearGradient, QPainter, + QPalette, QPixmap, QRadialGradient, QTransform) +from PySide6.QtWidgets import (QApplication, QFrame, QGridLayout, QLabel, + QPushButton, QSizePolicy, QWidget) + +class Ui_FrameToolCard(object): + def setupUi(self, FrameToolCard): + if not FrameToolCard.objectName(): + FrameToolCard.setObjectName(u"FrameToolCard") + FrameToolCard.resize(491, 64) + self.gridLayout_2 = QGridLayout(FrameToolCard) + self.gridLayout_2.setObjectName(u"gridLayout_2") + self.gridLayout = QGridLayout() + self.gridLayout.setObjectName(u"gridLayout") + self.labelName = QLabel(FrameToolCard) + self.labelName.setObjectName(u"labelName") + sizePolicy = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.labelName.sizePolicy().hasHeightForWidth()) + self.labelName.setSizePolicy(sizePolicy) + + self.gridLayout.addWidget(self.labelName, 0, 0, 1, 1) + + self.pushButtonInstall = QPushButton(FrameToolCard) + self.pushButtonInstall.setObjectName(u"pushButtonInstall") + sizePolicy1 = QSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) + sizePolicy1.setHorizontalStretch(0) + sizePolicy1.setVerticalStretch(0) + sizePolicy1.setHeightForWidth(self.pushButtonInstall.sizePolicy().hasHeightForWidth()) + self.pushButtonInstall.setSizePolicy(sizePolicy1) + + self.gridLayout.addWidget(self.pushButtonInstall, 0, 1, 1, 1) + + self.pushButtonUninstall = QPushButton(FrameToolCard) + self.pushButtonUninstall.setObjectName(u"pushButtonUninstall") + sizePolicy1.setHeightForWidth(self.pushButtonUninstall.sizePolicy().hasHeightForWidth()) + self.pushButtonUninstall.setSizePolicy(sizePolicy1) + + self.gridLayout.addWidget(self.pushButtonUninstall, 0, 2, 1, 1) + + self.pushButtonUpdate = QPushButton(FrameToolCard) + self.pushButtonUpdate.setObjectName(u"pushButtonUpdate") + sizePolicy1.setHeightForWidth(self.pushButtonUpdate.sizePolicy().hasHeightForWidth()) + self.pushButtonUpdate.setSizePolicy(sizePolicy1) + + self.gridLayout.addWidget(self.pushButtonUpdate, 0, 3, 1, 1) + + + self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1) + + self.labelInfo = QLabel(FrameToolCard) + self.labelInfo.setObjectName(u"labelInfo") + sizePolicy2 = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Expanding) + sizePolicy2.setHorizontalStretch(0) + sizePolicy2.setVerticalStretch(0) + sizePolicy2.setHeightForWidth(self.labelInfo.sizePolicy().hasHeightForWidth()) + self.labelInfo.setSizePolicy(sizePolicy2) + + self.gridLayout_2.addWidget(self.labelInfo, 1, 0, 1, 1) + + + self.retranslateUi(FrameToolCard) + + QMetaObject.connectSlotsByName(FrameToolCard) + # setupUi + + def retranslateUi(self, FrameToolCard): + FrameToolCard.setWindowTitle(QCoreApplication.translate("FrameToolCard", u"Frame", None)) + self.labelName.setText(QCoreApplication.translate("FrameToolCard", u"Name", None)) + self.pushButtonInstall.setText(QCoreApplication.translate("FrameToolCard", u"\u5b89\u88c5", None)) + self.pushButtonUninstall.setText(QCoreApplication.translate("FrameToolCard", u"\u5378\u8f7d", None)) + self.pushButtonUpdate.setText(QCoreApplication.translate("FrameToolCard", u"\u66f4\u65b0", None)) + self.labelInfo.setText(QCoreApplication.translate("FrameToolCard", u"TextLabel", None)) + # retranslateUi + diff --git a/core/tools/tools.py b/core/tools/tools.py new file mode 100644 index 0000000..dee4842 --- /dev/null +++ b/core/tools/tools.py @@ -0,0 +1,86 @@ +""" +工具箱模块 + +提供工具箱主窗口,包含各种实用工具的入口。 +使用 PySide6 构建的窗口框架。 + +主要功能: +- 工具箱主窗口界面 +- 窗口居中显示功能 +- 工具分类和导航 + +Author: Model Team +Version: 0.0.1 +""" +import logging + +from qt_material import apply_stylesheet + +from pathlib import Path +from .tools_ui import Ui_FormTools +from PySide6.QtGui import QIcon +from PySide6.QtWidgets import QWidget, QApplication + +logger = logging.getLogger(__name__) + +PLUGINS_PATH = Path('Y:/SE/xufeifei/plugins') + +class ToolsWindow(QWidget, Ui_FormTools): + """工具箱主窗口类 + + 继承自 QWidget(Qt 窗口基类)和 Ui_FormTools(Qt Designer 生成的 UI 界面) + 负责显示工具箱的主界面,提供工具的分类和导航功能。 + + 窗口特性: + - 默认尺寸: 400x293 像素 + - 支持窗口居中显示 + - 可作为独立窗口或嵌入其他窗口使用 + + Attributes: + parent: 父窗口对象,默认为 None(顶级窗口) + """ + def __init__(self, parent: QWidget = None) -> None: + """初始化工具箱窗口 + + 创建工具箱窗口实例,初始化 UI 界面。 + + Args: + parent: 父窗口对象,用于建立父子关系。 + 默认为 None,表示这是顶级窗口。 + """ + super().__init__(parent) + self.setupUi(self) + + self.initUI() + self.load_stylesheet() + + def initUI(self) -> None: + """ + 初始化用户界面 + + 配置窗口标题、图标、大小和居中显示。 + """ + self.setWindowTitle("工具箱") + self.setWindowIcon(QIcon('resources/tools.ico')) + + + def load_stylesheet(self) -> None: + """ + 加载 Qt 样式表和自定义样式文件 + + 使用 qt_material 库加载暗色主题,并应用自定义 QSS 样式表 + 失败时记录错误日志,但不影响应用继续运行(降级策略) + + 异常处理: + - FileNotFoundError: 样式文件不存在 + - RuntimeError: 主题加载失败 + - 其他异常: 记录警告但不中断应用 + """ + try: + apply_stylesheet(self, style=None,theme='dark_teal.xml', css_file='resources/my.qss') + except FileNotFoundError as e: + logger.warning(f"样式文件未找到,使用默认主题: {e}") + except RuntimeError as e: + logger.warning(f"主题加载失败,使用默认主题: {e}") + except Exception as e: + logger.warning(f"样式加载失败,使用默认主题: {e}") diff --git a/core/tools/tools.ui b/core/tools/tools.ui new file mode 100644 index 0000000..a7d278c --- /dev/null +++ b/core/tools/tools.ui @@ -0,0 +1,30 @@ + + + FormTools + + + + 0 + 0 + 810 + 423 + + + + + 0 + 0 + + + + Form + + + + + + + + + + diff --git a/core/tools/tools_ui.py b/core/tools/tools_ui.py new file mode 100644 index 0000000..385a34d --- /dev/null +++ b/core/tools/tools_ui.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- + +################################################################################ +## Form generated from reading UI file 'tools.ui' +## +## Created by: Qt User Interface Compiler version 6.11.1 +## +## WARNING! All changes made in this file will be lost when recompiling UI file! +################################################################################ + +from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, + QMetaObject, QObject, QPoint, QRect, + QSize, QTime, QUrl, Qt) +from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, + QFont, QFontDatabase, QGradient, QIcon, + QImage, QKeySequence, QLinearGradient, QPainter, + QPalette, QPixmap, QRadialGradient, QTransform) +from PySide6.QtWidgets import (QApplication, QGridLayout, QListWidget, QListWidgetItem, + QSizePolicy, QWidget) + +class Ui_FormTools(object): + def setupUi(self, FormTools): + if not FormTools.objectName(): + FormTools.setObjectName(u"FormTools") + FormTools.resize(810, 423) + sizePolicy = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(FormTools.sizePolicy().hasHeightForWidth()) + FormTools.setSizePolicy(sizePolicy) + self.gridLayout = QGridLayout(FormTools) + self.gridLayout.setObjectName(u"gridLayout") + self.listWidget = QListWidget(FormTools) + self.listWidget.setObjectName(u"listWidget") + + self.gridLayout.addWidget(self.listWidget, 0, 0, 1, 1) + + + self.retranslateUi(FormTools) + + QMetaObject.connectSlotsByName(FormTools) + # setupUi + + def retranslateUi(self, FormTools): + FormTools.setWindowTitle(QCoreApplication.translate("FormTools", u"Form", None)) + # retranslateUi + diff --git a/main.ico b/main.ico deleted file mode 100644 index bad03ad..0000000 Binary files a/main.ico and /dev/null differ diff --git a/main.py b/main.py index 793250a..20925da 100644 --- a/main.py +++ b/main.py @@ -1,27 +1,122 @@ +""" +Model Team Tools - 主程序入口 + +应用程序主窗口的初始化和配置模块 +使用 PySide6 构建的桌面应用程序框架 + +主要功能: +- 初始化 Qt 主窗口 +- 加载 Qt Material 样式表 +- 配置菜单栏和状态栏 +- 提供统一的日志记录接口 +""" import sys +import importlib +import logging +import core +import traceback -from PySide6.QtGui import * -from PySide6.QtCore import * -from PySide6.QtWidgets import * +from pathlib import Path + +from typing import Optional +from PySide6.QtGui import QIcon +from PySide6.QtWidgets import QApplication, QMainWindow, QMenuBar, QStatusBar,QFileDialog from qt_material import apply_stylesheet - from main_ui import Ui_MainWindow +# 获取模块日志记录器 +logger = logging.getLogger(__name__) + +# 版本号常量 +MAJOR_VER: int = 0 # 主版本号 +MINOR_VER: int = 0 # 次版本号 +MICRO_VER: int = 1 # 修订版本号 + +APP_NAME: str = "Model Team Tools" +APP_VERSION: str = f"{MAJOR_VER}.{MINOR_VER}.{MICRO_VER}" -class MainWindow(QMainWindow,Ui_MainWindow): - def __init__(self): +class MainWindow(QMainWindow, Ui_MainWindow): + """ + 主窗口类 + + 继承自 QMainWindow(Qt 主窗口基类)和 Ui_MainWindow(Qt Designer 生成的 UI 界面) + 负责应用程序主窗口的初始化、样式配置和界面布局 + """ + + def __init__(self) -> None: super().__init__() self.setupUi(self) - self.initUI() - def initUI(self): - self.setWindowIcon(QIcon("main.ico")) - self.setWindowTitle("Model Team Tools") + def initUI(self) -> None: + """ + 初始化用户界面组件 + + 执行以下初始化操作: + - 加载 Qt 样式表和自定义样式 + - 设置窗口标题 + - 配置菜单栏 + - 配置状态栏 + - 记录初始化日志 + + 注意:此方法在主窗口创建后调用 + """ + self.load_stylesheet() + self.setWindowTitle(APP_NAME) + self.setWindowIcon(QIcon('resources/main.ico')) + self.menubar: Optional[QMenuBar] = self.menuBar() + self.statusbar: QStatusBar = self.statusBar() + self.statusbar.showMessage(f"Version: {APP_VERSION}") + + self.action_tools.triggered.connect(self.on_tools) + + def load_stylesheet(self) -> None: + """ + 加载 Qt 样式表和自定义样式文件 + + 使用 qt_material 库加载暗色主题,并应用自定义 QSS 样式表 + 失败时记录错误日志,但不影响应用继续运行(降级策略) + + 异常处理: + - FileNotFoundError: 样式文件不存在 + - RuntimeError: 主题加载失败 + - 其他异常: 记录警告但不中断应用 + """ + try: + apply_stylesheet(self, style=None,theme='dark_teal.xml', css_file='resources/my.qss') + except FileNotFoundError as e: + logger.warning(f"样式文件未找到,使用默认主题: {e}") + except RuntimeError as e: + logger.warning(f"主题加载失败,使用默认主题: {e}") + except Exception as e: + logger.warning(f"样式加载失败,使用默认主题: {e}") + + def on_tools(self) -> None: + """打开工具箱窗口 + + 创建并显示工具箱窗口实例。包含完整的错误处理机制, + 确保任何异常都不会导致主程序崩溃。 + + 异常处理: + - 捕获所有异常并记录到日志 + - 显示详细的错误堆栈信息 + - 不影响主窗口的正常使用 + + 日志记录: + - 成功打开工具箱时记录 INFO 级别日志 + - 打开失败时记录 ERROR 级别日志 + """ + try: + self.tools = core.ToolsWindow() + self.tools.show() + logger.info("工具箱窗口已打开") + except Exception as e: + logger.error(f"无法打开工具箱窗口: {e}") + logger.error(traceback.format_exc()) if __name__ == '__main__': - app = QApplication([]) - main = MainWindow() + app = QApplication(sys.argv) + main: MainWindow = MainWindow() main.show() - sys.exit(app.exec()) + sys.exit(app.exec()) \ No newline at end of file diff --git a/main.ui b/main.ui index 31ffdca..1158c13 100644 --- a/main.ui +++ b/main.ui @@ -6,8 +6,8 @@ 0 0 - 800 - 600 + 1200 + 900 @@ -18,6 +18,28 @@ + + + + + 0 + 0 + + + + + 16777215 + 250 + + + + QFrame::Shape::StyledPanel + + + QFrame::Shadow::Raised + + + @@ -25,25 +47,47 @@ 0 0 - 800 + 1200 21 - File + 文件 - + - + + + toolBar + + + TopToolBarArea + + + false + + + - Config + 工具箱 + + + QAction::MenuRole::NoRole + + + FrameLog + QFrame +
core.h
+ 1 +
+
diff --git a/main_ui.py b/main_ui.py index b6ce4cb..f5ed970 100644 --- a/main_ui.py +++ b/main_ui.py @@ -3,7 +3,7 @@ ################################################################################ ## Form generated from reading UI file 'main.ui' ## -## Created by: Qt User Interface Compiler version 6.8.2 +## Created by: Qt User Interface Compiler version 6.11.1 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ @@ -16,17 +16,20 @@ from PySide6.QtGui import (QAction, QBrush, QColor, QConicalGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) -from PySide6.QtWidgets import (QApplication, QGridLayout, QMainWindow, QMenu, - QMenuBar, QSizePolicy, QStackedWidget, QStatusBar, - QWidget) +from PySide6.QtWidgets import (QApplication, QFrame, QGridLayout, QMainWindow, + QMenu, QMenuBar, QSizePolicy, QStackedWidget, + QStatusBar, QToolBar, QWidget) + +from core import FrameLog class Ui_MainWindow(object): def setupUi(self, MainWindow): if not MainWindow.objectName(): MainWindow.setObjectName(u"MainWindow") - MainWindow.resize(800, 600) - self.actionconfigs = QAction(MainWindow) - self.actionconfigs.setObjectName(u"actionconfigs") + MainWindow.resize(1200, 900) + self.action_tools = QAction(MainWindow) + self.action_tools.setObjectName(u"action_tools") + self.action_tools.setMenuRole(QAction.MenuRole.NoRole) self.centralwidget = QWidget(MainWindow) self.centralwidget.setObjectName(u"centralwidget") self.gridLayout = QGridLayout(self.centralwidget) @@ -36,19 +39,35 @@ class Ui_MainWindow(object): self.gridLayout.addWidget(self.stackedWidget, 0, 0, 1, 1) + self.frame = FrameLog(self.centralwidget) + self.frame.setObjectName(u"frame") + sizePolicy = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.frame.sizePolicy().hasHeightForWidth()) + self.frame.setSizePolicy(sizePolicy) + self.frame.setMaximumSize(QSize(16777215, 250)) + self.frame.setFrameShape(QFrame.Shape.StyledPanel) + self.frame.setFrameShadow(QFrame.Shadow.Raised) + + self.gridLayout.addWidget(self.frame, 1, 0, 1, 1) + MainWindow.setCentralWidget(self.centralwidget) self.menubar = QMenuBar(MainWindow) self.menubar.setObjectName(u"menubar") - self.menubar.setGeometry(QRect(0, 0, 800, 21)) + self.menubar.setGeometry(QRect(0, 0, 1200, 21)) self.menu = QMenu(self.menubar) self.menu.setObjectName(u"menu") MainWindow.setMenuBar(self.menubar) self.statusbar = QStatusBar(MainWindow) self.statusbar.setObjectName(u"statusbar") MainWindow.setStatusBar(self.statusbar) + self.toolBar = QToolBar(MainWindow) + self.toolBar.setObjectName(u"toolBar") + MainWindow.addToolBar(Qt.ToolBarArea.TopToolBarArea, self.toolBar) self.menubar.addAction(self.menu.menuAction()) - self.menu.addAction(self.actionconfigs) + self.menu.addAction(self.action_tools) self.retranslateUi(MainWindow) @@ -57,7 +76,8 @@ class Ui_MainWindow(object): def retranslateUi(self, MainWindow): MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None)) - self.actionconfigs.setText(QCoreApplication.translate("MainWindow", u"Config", None)) - self.menu.setTitle(QCoreApplication.translate("MainWindow", u"File", None)) + self.action_tools.setText(QCoreApplication.translate("MainWindow", u"\u5de5\u5177\u7bb1", None)) + self.menu.setTitle(QCoreApplication.translate("MainWindow", u"\u6587\u4ef6", None)) + self.toolBar.setWindowTitle(QCoreApplication.translate("MainWindow", u"toolBar", None)) # retranslateUi diff --git a/nuitka-crash-report.xml b/nuitka-crash-report.xml new file mode 100644 index 0000000..6d273c3 --- /dev/null +++ b/nuitka-crash-report.xml @@ -0,0 +1,7481 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..8842134 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +PySide6>=6.0.0 +Nuitka==2.6.6 +qt_material>=0.1.1 +logging>=0.1.0 \ No newline at end of file diff --git a/resources/main.ico b/resources/main.ico new file mode 100644 index 0000000..29d3482 Binary files /dev/null and b/resources/main.ico differ diff --git a/resources/my.qss b/resources/my.qss new file mode 100644 index 0000000..4e3bd87 --- /dev/null +++ b/resources/my.qss @@ -0,0 +1,19 @@ +* {{ + color: #ffffffff !important; + font: 16px "SimSun" !important; + text-transform: none; +}} + +QPushButton {{ + text-transform: none; +}} + +QTabBar::tab {{ + text-transform: none; +}} + +QTextEdit {{ + color: #ffffffff !important; + font: 16px "SimSun" !important; + text-transform: none; +}} \ No newline at end of file diff --git a/resources/tools.ico b/resources/tools.ico new file mode 100644 index 0000000..0512c3e Binary files /dev/null and b/resources/tools.ico differ