- PluginRegistry 新增 _update_requested 信号与 do_update slot - 待处理清单扩展支持 tool_name|remote_path 更新行格式 - 启动时 _process_pending_uninstalls 删旧 .pyd 后从服务器复制新文件 - PluginsCard 新增 parse_version 版本比较与 on_update_event - 更新链路复用卸载的自重启机制,一次重启完成更新
89 lines
3.0 KiB
Python
89 lines
3.0 KiB
Python
import os
|
||
import time
|
||
import logging
|
||
import threading
|
||
|
||
from .plugin_registry import Event
|
||
from PySide6.QtWidgets import QFrame
|
||
from PySide6.QtCore import Signal
|
||
from .plugins_card_ui import Ui_FramePluginsCard
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
|
||
def parse_version(version: str) -> tuple:
|
||
"""将版本字符串解析为可比较的元组,如 '1.10.0' -> (1, 10, 0)。
|
||
|
||
非数字段保持原样(字符串与整数混排时按元组规则比较,足够覆盖
|
||
常见的 '1.0.0' / '1.10.3' 场景)。None/空值/解析失败返回 (0,),
|
||
视为最低版本。
|
||
"""
|
||
if not version:
|
||
return (0,)
|
||
try:
|
||
parts = []
|
||
for seg in str(version).split('.'):
|
||
seg = seg.strip()
|
||
if seg.isdigit():
|
||
parts.append(int(seg))
|
||
else:
|
||
parts.append(seg)
|
||
return tuple(parts) if parts else (0,)
|
||
except Exception:
|
||
return (0,)
|
||
|
||
|
||
class PluginsCard(QFrame, Ui_FramePluginsCard):
|
||
"""工具卡片类
|
||
|
||
继承自 QFrame(Qt 帧基类)和 Ui_FrameToolCard(Qt Designer 生成的 UI 界面)
|
||
负责显示工具的卡片界面,包含工具的图标、名称和描述。
|
||
"""
|
||
send_event_signal = Signal(Event,str)
|
||
def __init__(self, name: str, info:dict, parent=None) -> None:
|
||
super().__init__(parent)
|
||
self.setupUi(self)
|
||
|
||
self.name = name
|
||
self.info = info
|
||
|
||
self.initUI()
|
||
|
||
def initUI(self):
|
||
self.refresh()
|
||
self.textBrowser.setReadOnly(True)
|
||
self.pushButtonUpdate.clicked.connect(self.on_update_event)
|
||
self.pushButtonInstall.clicked.connect(self.on_install_event)
|
||
self.pushButtonUninstall.clicked.connect(self.on_uninstall_event)
|
||
|
||
def refresh(self) -> None:
|
||
"""根据 info 刷新卡片显示与按钮状态。"""
|
||
self.textBrowser.setMarkdown(self.to_card())
|
||
installed = self.info["local version"] is not None
|
||
self.pushButtonInstall.setEnabled(not installed)
|
||
self.pushButtonUninstall.setEnabled(installed)
|
||
if installed:
|
||
remote = parse_version(self.info.get('remote version'))
|
||
local = parse_version(self.info.get('local version'))
|
||
self.pushButtonUpdate.setEnabled(remote > local)
|
||
else:
|
||
self.pushButtonUpdate.setEnabled(False)
|
||
|
||
def to_card(self):
|
||
card = f"# {self.name}\n\n"
|
||
card += f"**最新:** V{self.info['remote version']}\n\n"
|
||
if self.info['local version'] is None:
|
||
card += f"**当前:** 未安装!\n\n"
|
||
else:
|
||
card += f"**当前:** V{self.info['local version']}\n\n"
|
||
card += f"**描述:** {self.info['remote description']}"
|
||
return card
|
||
|
||
def on_install_event(self):
|
||
self.send_event_signal.emit(Event.Install, self.name)
|
||
|
||
def on_uninstall_event(self):
|
||
self.send_event_signal.emit(Event.Uninstall, self.name)
|
||
|
||
def on_update_event(self):
|
||
self.send_event_signal.emit(Event.Update, self.name) |