""" 工具箱模块 提供工具箱主窗口,包含各种实用工具的入口。 使用 PySide6 构建的窗口框架。 主要功能: - 工具箱主窗口界面 - 窗口居中显示功能 - 工具分类和导航 Author: Model Team Version: 0.0.1 """ import os import sys import logging import threading import importlib from qt_material import apply_stylesheet from pathlib import Path from .plugins_ui import Ui_FormPlugins from PySide6.QtGui import QIcon from PySide6.QtWidgets import QWidget, QListWidgetItem from PySide6.QtCore import QSize, Signal from .plugins_card import PluginsCard from .plugin_registry import PluginRegistry logger = logging.getLogger(__name__) LOCAL_PLUGINS_PATH = Path("./plugins") REMOTE_PLUGINS_PATH = Path('Y:/SE/xufeifei/plugins') class Plugins(QWidget, Ui_FormPlugins): """工具箱主窗口类 继承自 QWidget(Qt 窗口基类)和 Ui_FormTools(Qt Designer 生成的 UI 界面) 负责显示工具箱的主界面,提供工具的分类和导航功能。 窗口特性: - 默认尺寸: 400x293 像素 - 支持窗口居中显示 - 可作为独立窗口或嵌入其他窗口使用 Attributes: parent: 父窗口对象,默认为 None(顶级窗口) """ update_tool_card = Signal(dict) def __init__(self, plugin_registry:PluginRegistry, parent: QWidget = None) -> None: """初始化工具箱窗口 创建工具箱窗口实例,初始化 UI 界面。 Args: parent: 父窗口对象,用于建立父子关系。 默认为 None,表示这是顶级窗口。 """ super().__init__(parent) self.setupUi(self) self.plugin_registry = plugin_registry self.cards: dict = {} self.initUI() self.load_stylesheet() self.plugin_registry.update_plugins_card_signal.connect(self.on_update_plugins_card) self.plugin_registry.uninstall_completed_signal.connect(self.on_plugin_uninstalled) def initUI(self) -> None: """ 初始化用户界面 配置窗口标题、图标、大小和居中显示。 """ self.setWindowTitle("工具箱") self.setWindowIcon(QIcon('resources/tools.ico')) # self.update_tool_card.connect(self.on_update_tool_card) 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 start_load_tools(self): # self.sub_thread = threading.Thread(target= self.load_tool_list,args=(self.tools,)) # self.sub_thread.start() # def load_tool_list(self, tools:dict): # if not os.path.exists(REMOTE_PLUGINS_PATH): # logger.error("服务器链接错误!") # return # #读取服务器工具信息 # sys.path.append(str(REMOTE_PLUGINS_PATH)) # for tool in Path(REMOTE_PLUGINS_PATH).glob("*.pyd"): # tool_name = tool.stem # try: # module = importlib.import_module(tool_name) # name = module.read_tool_name() # version = module.read_tool_version() # description = module.read_tool_description() # if name in tools.keys(): # pass # else: # tools[name] = {} # tools[name]["name"] = tool_name # tools[name]["local version"] = None # tools[name]["local description"] = None # tools[name]["remote version"] = version # tools[name]["remote description"] = description # tools[name]['remote path'] = REMOTE_PLUGINS_PATH # except Exception as e: # logger.error(f"服务器{tool_name}无法加载:{str(e)}") # sys.path.remove(str(REMOTE_PLUGINS_PATH)) # self.update_tool_card.emit(tools) def on_update_plugins_card(self, plugins:dict): for name in plugins.keys(): if name in self.cards: # 卡片已存在,只刷新状态(避免重复创建叠加) self.cards[name].info = plugins[name] self.cards[name].refresh() else: item = QListWidgetItem(self.listWidget) plugin_card = PluginsCard(name, plugins[name]) plugin_card.send_event_signal.connect(self.plugin_registry.start_plugins_event) self.cards[name] = plugin_card item.setSizeHint(QSize(plugin_card.sizeHint().width(), 200)) self.listWidget.addItem(item) self.listWidget.setCurrentItem(item) self.listWidget.setItemWidget(item, plugin_card) def on_plugin_uninstalled(self, name: str) -> None: """卸载完成后刷新对应卡片状态。""" card = self.cards.get(name) if card is not None: card.refresh()