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
+
+
+
-
+
+
+ toolBar
+
+
+ TopToolBarArea
+
+
+ false
+
+
+
- Config
+ 工具箱
+
+
+ QAction::MenuRole::NoRole
+
+
+ FrameLog
+ QFrame
+
+ 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