init version
This commit is contained in:
442
gui_client.py
442
gui_client.py
@@ -1,26 +1,74 @@
|
||||
import sys
|
||||
import requests
|
||||
from datetime import datetime, timezone
|
||||
from zoneinfo import ZoneInfo
|
||||
from PySide6.QtWidgets import (
|
||||
QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
|
||||
QTableWidget, QTableWidgetItem, QPushButton, QMessageBox, QDialog,
|
||||
QFormLayout, QLineEdit, QComboBox, QTextEdit, QDialogButtonBox,
|
||||
QAbstractItemView
|
||||
QApplication, QWidget, QVBoxLayout, QHBoxLayout, QFormLayout, QAbstractItemView
|
||||
)
|
||||
from PySide6.QtCore import Qt, QThread, Signal, QObject
|
||||
from typing import Dict, Any, Optional
|
||||
from PySide6.QtCore import (
|
||||
Qt, QThread, Signal, QObject, QAbstractTableModel, QModelIndex, QLocale, QAbstractListModel
|
||||
)
|
||||
from PySide6.QtGui import QIcon
|
||||
from qfluentwidgets import (
|
||||
MSFluentWindow, setTheme, Theme, TableView, PushButton, MessageBox, MessageBoxBase,
|
||||
LineEdit, InfoBar, TextEdit, InfoBarIcon, FluentTranslator, TeachingTip, TeachingTipTailPosition,
|
||||
ModelComboBox,
|
||||
|
||||
)
|
||||
from qfluentwidgets import FluentIcon as Fi
|
||||
import resources
|
||||
|
||||
# dict[str, str | int] 就是
|
||||
# {
|
||||
# "ID": "xxx",
|
||||
# "NAME": "zzz",
|
||||
# "SAFE": -2,
|
||||
# "UPDATE_DATA": "aaa",
|
||||
# "NOTES": ""
|
||||
# }
|
||||
|
||||
|
||||
# --- API 客户端配置 ---
|
||||
BASE_URL = "http://127.0.0.1:17701/api/v1/ext"
|
||||
BASE_URL = "https://safe-marks.oranj.work/api/v1/ext"
|
||||
|
||||
# 安全状态与中文的映射 (根据新要求)
|
||||
SAFE = [1, 0, -1, -2]
|
||||
SAFE_MAP = {
|
||||
1: "安全 (safe)",
|
||||
0: "未知 (unsure)",
|
||||
-1: "不安全 (unsafe)",
|
||||
-2: "不详 (unknown)"
|
||||
1: "安全",
|
||||
0: "未知",
|
||||
-1: "不安全",
|
||||
-2: "未记录"
|
||||
}
|
||||
# 反向映射,用于 QComboBox
|
||||
SAFE_MAP_INV = {v: k for k, v in SAFE_MAP.items()}
|
||||
SAFE_MAP_ICON = {
|
||||
1: InfoBarIcon.SUCCESS.icon(),
|
||||
0: InfoBarIcon.WARNING.icon(),
|
||||
-1: InfoBarIcon.ERROR.icon(),
|
||||
-2: InfoBarIcon.INFORMATION.icon(),
|
||||
}
|
||||
|
||||
|
||||
class APIException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def show_quick_tip(widget: QWidget, caption: str, text: str):
|
||||
mb = MessageBox(caption, text, widget)
|
||||
mb.cancelButton.setHidden(True)
|
||||
mb.buttonLayout.insertStretch(0, 1)
|
||||
mb.buttonLayout.setStretch(1, 0)
|
||||
mb.yesButton.setMinimumWidth(100)
|
||||
mb.setClosableOnMaskClicked(True)
|
||||
mb.exec()
|
||||
|
||||
|
||||
def accept_warning(widget: QWidget, condition: bool,
|
||||
caption: str = "警告", text: str = "你确定要继续吗?") -> bool:
|
||||
if condition:
|
||||
mb = MessageBox(caption, text, widget)
|
||||
if not mb.exec():
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
# --- API 工作线程 ---
|
||||
@@ -43,9 +91,9 @@ class ApiWorker(QObject):
|
||||
if not response.ok:
|
||||
try:
|
||||
detail = response.json().get("detail", response.text)
|
||||
raise Exception(f"API 错误 (状态 {response.status_code}): {detail}")
|
||||
raise APIException(f"API 错误 (状态 {response.status_code}): {detail}")
|
||||
except requests.JSONDecodeError:
|
||||
raise Exception(f"API 错误 (状态 {response.status_code}): {response.text}")
|
||||
raise APIException(f"API 错误 (状态 {response.status_code}): {response.text}")
|
||||
return response.json()
|
||||
|
||||
def do_query_all(self):
|
||||
@@ -57,7 +105,7 @@ class ApiWorker(QObject):
|
||||
except Exception as e:
|
||||
self.error.emit(str(e))
|
||||
|
||||
def do_add_one(self, extension: Dict[str, Any]):
|
||||
def do_add_one(self, extension: dict[str, str | int]):
|
||||
"""执行 add_one 操作 (dict)"""
|
||||
try:
|
||||
response = self.session.post(f"{BASE_URL}/add_one", json=extension)
|
||||
@@ -66,7 +114,7 @@ class ApiWorker(QObject):
|
||||
except Exception as e:
|
||||
self.error.emit(str(e))
|
||||
|
||||
def do_update_one(self, item_id: str, payload: Dict[str, Any]):
|
||||
def do_update_one(self, item_id: str, payload: dict[str, str | int]):
|
||||
"""执行 update_one 操作 (dict)"""
|
||||
try:
|
||||
response = self.session.put(f"{BASE_URL}/update_one/{item_id}", json=payload)
|
||||
@@ -85,127 +133,241 @@ class ApiWorker(QObject):
|
||||
self.error.emit(str(e))
|
||||
|
||||
|
||||
class SafeStatusListModel(QAbstractListModel):
|
||||
|
||||
def __init__(self, parent: QWidget = None):
|
||||
super().__init__(parent)
|
||||
self.safe_status = SAFE
|
||||
|
||||
def rowCount(self, /, parent = ...):
|
||||
return len(self.safe_status)
|
||||
|
||||
def columnCount(self, parent, /):
|
||||
return 1
|
||||
|
||||
def data(self, index: QModelIndex, /, role: int = ...):
|
||||
row = index.row()
|
||||
if role == Qt.ItemDataRole.EditRole:
|
||||
return SAFE_MAP[self.safe_status[row]]
|
||||
elif role == Qt.ItemDataRole.DecorationRole:
|
||||
return SAFE_MAP_ICON[self.safe_status[row]]
|
||||
elif role == Qt.ItemDataRole.UserRole:
|
||||
return self.safe_status[row]
|
||||
return None
|
||||
|
||||
# --- 添加/编辑 对话框 ---
|
||||
class ExtensionDialog(QDialog):
|
||||
class ExtensionDialog(MessageBoxBase):
|
||||
"""用于添加或编辑插件条目的对话框。"""
|
||||
|
||||
def __init__(self, parent=None, extension_data: Optional[Dict] = None):
|
||||
def __init__(self, extension_data: dict[str, str | int] = None, parent=None):
|
||||
super().__init__(parent)
|
||||
self.is_edit_mode = extension_data is not None
|
||||
|
||||
self.setWindowTitle("编辑插件" if self.is_edit_mode else "添加插件")
|
||||
self.setMinimumWidth(400)
|
||||
|
||||
# 创建控件
|
||||
self.id_edit = QLineEdit()
|
||||
self.name_edit = QLineEdit()
|
||||
self.safe_combo = QComboBox()
|
||||
self.notes_edit = QTextEdit()
|
||||
self.lne_id = LineEdit(self)
|
||||
self.lne_name = LineEdit(self)
|
||||
self.safe_combo = ModelComboBox(self)
|
||||
self.notes_edit = TextEdit(self)
|
||||
|
||||
# 填充 SAFE 下拉框 (使用新的 MAP)
|
||||
for text in SAFE_MAP_INV.keys():
|
||||
self.safe_combo.addItem(text)
|
||||
safe_list_model = SafeStatusListModel(self)
|
||||
self.safe_combo.setModel(safe_list_model)
|
||||
|
||||
# 布局
|
||||
form_layout = QFormLayout()
|
||||
form_layout.addRow("ID:", self.id_edit)
|
||||
form_layout.addRow("名称 (NAME):", self.name_edit)
|
||||
form_layout.addRow("安全状态 (SAFE):", self.safe_combo)
|
||||
form_layout.addRow("备注 (NOTES):", self.notes_edit)
|
||||
|
||||
self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
||||
self.button_box.accepted.connect(self.accept)
|
||||
self.button_box.rejected.connect(self.reject)
|
||||
form_layout.addRow("ID:", self.lne_id)
|
||||
form_layout.addRow("名称:", self.lne_name)
|
||||
form_layout.addRow("安全状态:", self.safe_combo)
|
||||
form_layout.addRow("备注:", self.notes_edit)
|
||||
|
||||
self.cw = QWidget(self)
|
||||
main_layout = QVBoxLayout()
|
||||
main_layout.addLayout(form_layout)
|
||||
main_layout.addWidget(self.button_box)
|
||||
self.setLayout(main_layout)
|
||||
self.cw.setLayout(main_layout)
|
||||
|
||||
self.viewLayout.addWidget(self.cw)
|
||||
|
||||
if self.is_edit_mode:
|
||||
self.id_edit.setText(extension_data.get("ID", ""))
|
||||
self.id_edit.setReadOnly(True) # ID 不允许修改
|
||||
self.name_edit.setText(extension_data.get("NAME", ""))
|
||||
safe_status = extension_data.get("SAFE", 0)
|
||||
self.safe_combo.setCurrentText(SAFE_MAP.get(safe_status, "未知 (unsure)"))
|
||||
self.lne_id.setText(extension_data.get("ID", ""))
|
||||
self.lne_id.setReadOnly(True) # ID 不允许修改
|
||||
self.lne_name.setText(extension_data.get("NAME", ""))
|
||||
safe_status: int = extension_data.get("SAFE", -2)
|
||||
self.safe_combo.setCurrentIndex(SAFE.index(safe_status))
|
||||
self.notes_edit.setText(extension_data.get("NOTES", ""))
|
||||
else:
|
||||
self.safe_combo.setCurrentIndex(SAFE.index(-2))
|
||||
|
||||
def get_data(self) -> Dict[str, Any]:
|
||||
def validate(self) -> bool:
|
||||
if len(self.lne_id.text()) == 0:
|
||||
TeachingTip.create(
|
||||
target=self.lne_id,
|
||||
title="错误",
|
||||
content="ID 不能为空!",
|
||||
icon=InfoBarIcon.ERROR,
|
||||
isClosable=True,
|
||||
duration=2000,
|
||||
tailPosition=TeachingTipTailPosition.BOTTOM,
|
||||
parent=self
|
||||
)
|
||||
return False
|
||||
if len(self.lne_name.text()) == 0:
|
||||
TeachingTip.create(
|
||||
target=self.lne_name,
|
||||
title="错误",
|
||||
content="名称不能为空!",
|
||||
icon=InfoBarIcon.ERROR,
|
||||
isClosable=True,
|
||||
duration=2000,
|
||||
tailPosition=TeachingTipTailPosition.BOTTOM,
|
||||
parent=self,
|
||||
)
|
||||
return False
|
||||
return True
|
||||
|
||||
def get_data(self) -> dict[str, str | int]:
|
||||
"""获取对话框中用于 'add_one' 的数据"""
|
||||
return {
|
||||
"ID": self.id_edit.text(),
|
||||
"NAME": self.name_edit.text(),
|
||||
"SAFE": SAFE_MAP_INV.get(self.safe_combo.currentText(), 0),
|
||||
"ID": self.lne_id.text(),
|
||||
"NAME": self.lne_name.text(),
|
||||
"SAFE": self.safe_combo.currentData(),
|
||||
"NOTES": self.notes_edit.toPlainText()
|
||||
}
|
||||
|
||||
def get_update_payload(self) -> Dict[str, Any]:
|
||||
def get_update_payload(self) -> dict[str, str | int]:
|
||||
"""获取对话框中用于 'update_one' 的数据 (不含ID)"""
|
||||
return {
|
||||
"NAME": self.name_edit.text(),
|
||||
"SAFE": SAFE_MAP_INV.get(self.safe_combo.currentText(), 0),
|
||||
"NAME": self.lne_name.text(),
|
||||
"SAFE": self.safe_combo.currentData(),
|
||||
"NOTES": self.notes_edit.toPlainText()
|
||||
}
|
||||
|
||||
|
||||
class ExtensionsDataTable(QAbstractTableModel):
|
||||
|
||||
def __init__(self, ext_data: list[dict[str, str | int]], parent=None):
|
||||
super().__init__(parent)
|
||||
self.ext_data = ext_data or []
|
||||
self.headers = ["ID", "名称", "安全性", "更新日期", "备注"]
|
||||
self.col_map = {
|
||||
0: "ID",
|
||||
1: "NAME",
|
||||
2: "SAFE",
|
||||
3: "UPDATE_DATE",
|
||||
4: "NOTES",
|
||||
}
|
||||
|
||||
def rowCount(self, /, parent = ...):
|
||||
return len(self.ext_data)
|
||||
|
||||
def columnCount(self, /, parent = ...):
|
||||
return len(self.headers)
|
||||
|
||||
def headerData(self, section: int, orientation: Qt.Orientation, /, role: int = ...):
|
||||
if orientation == Qt.Orientation.Horizontal:
|
||||
if role == Qt.ItemDataRole.DisplayRole:
|
||||
return self.headers[section]
|
||||
return None
|
||||
|
||||
def data(self, index: QModelIndex, /, role: int = ...):
|
||||
row = index.row()
|
||||
col = index.column()
|
||||
ext = self.ext_data[row]
|
||||
col_val = ext[self.col_map[col]]
|
||||
if role == Qt.ItemDataRole.DisplayRole:
|
||||
if col == 2:
|
||||
return SAFE_MAP[col_val]
|
||||
elif col == 3:
|
||||
return self.iso2custom(col_val)
|
||||
else:
|
||||
return col_val
|
||||
if role == Qt.ItemDataRole.DecorationRole:
|
||||
if col == 2:
|
||||
return SAFE_MAP_ICON[col_val]
|
||||
# 一行的每一个列都返回所有数据,这样不管双击一行的哪一个位置,都可以获取到所有数据
|
||||
if role == Qt.ItemDataRole.UserRole:
|
||||
return ext
|
||||
return None
|
||||
|
||||
def update_data(self, ext_data: list[dict[str, str | int]]):
|
||||
self.beginResetModel()
|
||||
self.ext_data.clear()
|
||||
self.ext_data.extend(ext_data)
|
||||
self.endResetModel()
|
||||
|
||||
@staticmethod
|
||||
def iso2custom(iso_time: str) -> str:
|
||||
dt = datetime.fromisoformat(iso_time)
|
||||
dt = dt.replace(tzinfo=timezone.utc)
|
||||
dt = dt.astimezone(ZoneInfo("America/New_York"))
|
||||
custom_format = "%Y-%m-%d %H:%M:%S"
|
||||
|
||||
return dt.strftime(custom_format)
|
||||
|
||||
|
||||
class MainInterface(QWidget):
|
||||
|
||||
def __init__(self, ext_data: list[dict[str, str | int]] = None, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setObjectName("main")
|
||||
self.vly_m = QVBoxLayout()
|
||||
self.setLayout(self.vly_m)
|
||||
|
||||
self.hly_top = QHBoxLayout()
|
||||
self.pbn_refresh = PushButton(Fi.SYNC, "刷新", self)
|
||||
self.pbn_add = PushButton(Fi.ADD, "添加", self)
|
||||
self.pbn_delete = PushButton(Fi.DELETE, "删除", self)
|
||||
|
||||
self.hly_top.addWidget(self.pbn_refresh)
|
||||
self.hly_top.addWidget(self.pbn_add)
|
||||
self.hly_top.addWidget(self.pbn_delete)
|
||||
self.hly_top.addStretch(1)
|
||||
self.vly_m.addLayout(self.hly_top)
|
||||
|
||||
self.tbv_m = TableView(self)
|
||||
self.ext_model = ExtensionsDataTable(ext_data, self)
|
||||
self.tbv_m.setModel(self.ext_model)
|
||||
self.tbv_m.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers)
|
||||
self.tbv_m.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows) # 整行选中
|
||||
self.tbv_m.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection) # 只允许单选
|
||||
self.tbv_m.verticalHeader().hide()
|
||||
self.tbv_m.setBorderVisible(True)
|
||||
self.tbv_m.setBorderRadius(4)
|
||||
|
||||
self.tbv_m.horizontalHeader().setStretchLastSection(True)
|
||||
self.tbv_m.setColumnWidth(0, 250)
|
||||
self.tbv_m.setColumnWidth(1, 200)
|
||||
self.tbv_m.setColumnWidth(3, 180)
|
||||
|
||||
self.vly_m.addWidget(self.tbv_m)
|
||||
|
||||
|
||||
# --- 主窗口 ---
|
||||
class MainWindow(QMainWindow):
|
||||
class MainWindow(MSFluentWindow):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setWindowTitle("插件管理器")
|
||||
self.setGeometry(100, 100, 800, 600)
|
||||
self.setWindowTitle("插件安全标记")
|
||||
self.setWindowIcon(QIcon(":/logo.png"))
|
||||
# self.navigationInterface.hide()
|
||||
self.resize(1000, 760)
|
||||
desktop = QApplication.screens()[0].availableGeometry()
|
||||
w, h = desktop.width(), desktop.height()
|
||||
self.move(w // 2 - self.width() // 2, h // 2 - self.height() // 2)
|
||||
setTheme(Theme.LIGHT)
|
||||
|
||||
self.table_widget = QTableWidget()
|
||||
self.setup_table()
|
||||
# --- UI ---
|
||||
self.main_interface = MainInterface(parent=self)
|
||||
self.addSubInterface(self.main_interface, Fi.HOME, "主页", Fi.HOME_FILL)
|
||||
|
||||
self.refresh_button = QPushButton("刷新 (Query All)")
|
||||
self.add_button = QPushButton("添加 (Add One)")
|
||||
self.delete_button = QPushButton("删除选定 (Delete One)")
|
||||
|
||||
button_layout = QHBoxLayout()
|
||||
button_layout.addWidget(self.refresh_button)
|
||||
button_layout.addWidget(self.add_button)
|
||||
button_layout.addWidget(self.delete_button)
|
||||
button_layout.addStretch()
|
||||
|
||||
main_layout = QVBoxLayout()
|
||||
main_layout.addLayout(button_layout)
|
||||
main_layout.addWidget(self.table_widget)
|
||||
|
||||
central_widget = QWidget()
|
||||
central_widget.setLayout(main_layout)
|
||||
self.setCentralWidget(central_widget)
|
||||
|
||||
self.setup_worker_thread()
|
||||
|
||||
# 连接信号和槽
|
||||
self.refresh_button.clicked.connect(self.worker.do_query_all)
|
||||
self.add_button.clicked.connect(self.on_add)
|
||||
self.delete_button.clicked.connect(self.on_delete)
|
||||
self.table_widget.doubleClicked.connect(self.on_edit)
|
||||
|
||||
# 初始加载数据
|
||||
self.worker.do_query_all()
|
||||
|
||||
def setup_table(self):
|
||||
"""初始化表格"""
|
||||
self.table_widget.setColumnCount(5)
|
||||
self.table_widget.setHorizontalHeaderLabels(
|
||||
["ID", "名称 (NAME)", "安全 (SAFE)", "更新日期 (UPDATE_DATE)", "备注 (NOTES)"])
|
||||
self.table_widget.setEditTriggers(QAbstractItemView.NoEditTriggers)
|
||||
self.table_widget.setSelectionBehavior(QAbstractItemView.SelectRows) # 整行选中
|
||||
self.table_widget.setSelectionMode(QAbstractItemView.SingleSelection) # 只允许单选
|
||||
self.table_widget.horizontalHeader().setStretchLastSection(True)
|
||||
self.table_widget.resizeColumnsToContents()
|
||||
|
||||
def setup_worker_thread(self):
|
||||
"""初始化后台工作线程和 QObject"""
|
||||
# --- 初始化后台工作线程和 QObject ---
|
||||
self.thread = QThread()
|
||||
self.worker = ApiWorker()
|
||||
self.worker.moveToThread(self.thread)
|
||||
|
||||
# 连接 Worker 的新信号
|
||||
self.worker.queryAllFinished.connect(self.populate_table)
|
||||
self.worker.queryAllFinished.connect(self.main_interface.ext_model.update_data)
|
||||
self.worker.addOneFinished.connect(self.handle_operation_finished)
|
||||
self.worker.updateOneFinished.connect(self.handle_operation_finished)
|
||||
self.worker.deleteOneFinished.connect(self.handle_operation_finished)
|
||||
@@ -213,6 +375,15 @@ class MainWindow(QMainWindow):
|
||||
|
||||
self.thread.start()
|
||||
|
||||
# 连接信号和槽
|
||||
self.main_interface.pbn_refresh.clicked.connect(self.worker.do_query_all)
|
||||
self.main_interface.pbn_add.clicked.connect(self.on_add)
|
||||
self.main_interface.pbn_delete.clicked.connect(self.on_delete)
|
||||
self.main_interface.tbv_m.doubleClicked.connect(self.on_edit)
|
||||
|
||||
# 初始加载数据
|
||||
self.worker.do_query_all()
|
||||
|
||||
def closeEvent(self, event):
|
||||
"""关闭窗口时,确保线程也退出"""
|
||||
self.thread.quit()
|
||||
@@ -221,88 +392,61 @@ class MainWindow(QMainWindow):
|
||||
|
||||
# --- GUI 槽函数 (在主线程中运行) ---
|
||||
|
||||
def populate_table(self, data: list):
|
||||
"""使用从 API 获取的数据填充表格"""
|
||||
self.table_widget.setRowCount(0)
|
||||
|
||||
for row, item in enumerate(data):
|
||||
self.table_widget.insertRow(row)
|
||||
|
||||
id_item = QTableWidgetItem(item.get("ID"))
|
||||
name_item = QTableWidgetItem(item.get("NAME"))
|
||||
safe_val = item.get("SAFE", 0)
|
||||
safe_item = QTableWidgetItem(SAFE_MAP.get(safe_val, "未知 (unsure)")) # 使用新 MAP
|
||||
date_item = QTableWidgetItem(item.get("UPDATE_DATE"))
|
||||
notes_item = QTableWidgetItem(item.get("NOTES"))
|
||||
|
||||
# 存储原始数据到 ID 项中,以便编辑时检索
|
||||
id_item.setData(Qt.UserRole, item)
|
||||
|
||||
self.table_widget.setItem(row, 0, id_item)
|
||||
self.table_widget.setItem(row, 1, name_item)
|
||||
self.table_widget.setItem(row, 2, safe_item)
|
||||
self.table_widget.setItem(row, 3, date_item)
|
||||
self.table_widget.setItem(row, 4, notes_item)
|
||||
|
||||
self.table_widget.resizeColumnsToContents()
|
||||
|
||||
def handle_operation_finished(self, result: dict):
|
||||
"""添加/更新/删除成功后的通用处理器"""
|
||||
QMessageBox.information(self, "操作成功", f"操作已成功完成。\n{result}")
|
||||
InfoBar.success("", "操作已成功完成。", duration=2000, parent=self.window())
|
||||
self.worker.do_query_all() # 重新加载数据
|
||||
|
||||
def handle_error(self, error_message: str):
|
||||
"""显示来自工作线程的错误消息"""
|
||||
QMessageBox.critical(self, "API 错误", f"与服务器通信时发生错误:\n{error_message}")
|
||||
show_quick_tip(self, "API 错误", f"与服务器通信时发生错误:\n{error_message}")
|
||||
|
||||
# --- 按钮点击处理 ---
|
||||
|
||||
def on_add(self):
|
||||
"""打开“添加”对话框 (add_one)"""
|
||||
dialog = ExtensionDialog(self)
|
||||
dialog = ExtensionDialog(parent=self)
|
||||
if dialog.exec():
|
||||
data = dialog.get_data()
|
||||
if not data.get("ID") or not data.get("NAME"):
|
||||
self.handle_error("ID 和 名称 (NAME) 不能为空。")
|
||||
return
|
||||
self.worker.do_add_one(data)
|
||||
|
||||
def on_edit(self, index):
|
||||
def on_edit(self, index: QModelIndex):
|
||||
"""打开“编辑”对话框(通过双击)(update_one)"""
|
||||
row = index.row()
|
||||
item_data = self.table_widget.item(row, 0).data(Qt.UserRole)
|
||||
item_data = index.data(Qt.ItemDataRole.UserRole)
|
||||
item_id = item_data.get("ID")
|
||||
|
||||
dialog = ExtensionDialog(self, extension_data=item_data)
|
||||
dialog = ExtensionDialog(extension_data=item_data, parent=self)
|
||||
if dialog.exec():
|
||||
update_payload = dialog.get_update_payload()
|
||||
self.worker.do_update_one(item_id, update_payload)
|
||||
|
||||
def on_delete(self):
|
||||
"""删除当前选定的行 (delete_one)"""
|
||||
current_row = self.table_widget.currentRow()
|
||||
if current_row < 0:
|
||||
QMessageBox.warning(self, "未选择", "请选择一行进行删除。")
|
||||
# 前面设定了只能选中一行
|
||||
ext_data: list[dict] = [index.data(Qt.ItemDataRole.UserRole)
|
||||
for index in self.main_interface.tbv_m.selectedIndexes()
|
||||
if index.column() == 0]
|
||||
if len(ext_data) == 0:
|
||||
show_quick_tip(self, "警告", "你没有选中任何插件。")
|
||||
return
|
||||
|
||||
id_item = self.table_widget.item(current_row, 0)
|
||||
item_id = id_item.text()
|
||||
ext_d: dict = ext_data[0]
|
||||
if accept_warning(self, True, "警告",
|
||||
f"你确定要删除插件【{ext_d.get('NAME')}】吗?"):
|
||||
return
|
||||
|
||||
reply = QMessageBox.question(
|
||||
self,
|
||||
"确认删除",
|
||||
f"你确定要删除插件 (ID: {item_id}) 吗?",
|
||||
QMessageBox.Yes | QMessageBox.No,
|
||||
QMessageBox.No
|
||||
)
|
||||
|
||||
if reply == QMessageBox.Yes:
|
||||
self.worker.do_delete_one(item_id)
|
||||
self.worker.do_delete_one(ext_d.get("ID"))
|
||||
|
||||
|
||||
# --- 运行 GUI ---
|
||||
if __name__ == "__main__":
|
||||
def main():
|
||||
app = QApplication(sys.argv)
|
||||
window = MainWindow()
|
||||
window.show()
|
||||
sys.exit(app.exec())
|
||||
translator = FluentTranslator(QLocale(QLocale.Language.Chinese, QLocale.Country.China))
|
||||
app.installTranslator(translator)
|
||||
win = MainWindow()
|
||||
win.show()
|
||||
return app.exec()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
PySide6-Essentials
|
||||
PySide6-Fluent-Widgets
|
||||
requests
|
||||
tzdata
|
||||
|
||||
297
resources.py
Normal file
297
resources.py
Normal file
@@ -0,0 +1,297 @@
|
||||
# Resource object code (Python 3)
|
||||
# Created by: object code
|
||||
# Created by: The Resource Compiler for Qt version 6.10.0
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PySide6 import QtCore
|
||||
|
||||
qt_resource_data = b"\
|
||||
\x00\x00\x10v\
|
||||
\x89\
|
||||
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
|
||||
\x00\x00\x80\x00\x00\x00\x80\x08\x03\x00\x00\x00\xf4\xe0\x91\xf9\
|
||||
\x00\x00\x03\x00PLTEGpL\x04\x06\x03\x00\x00\
|
||||
\x00\x00\x00\x00\x00\x00\x00z\xabh\x00\x00\x00\x1b=E\
|
||||
\x01\x02\x01\x10!%\x00\x03\x04\x00\x00\x00\x01\x02\x01\x00\
|
||||
\x00\x00\x03\x08\x07a\xaf\xc1\x04\x06\x03!\xaf\xe6\x02\x03\
|
||||
\x01\x00\x00\x00(O\x1a\x03\x04\x02\x00g\x8f\x00\x00\x00\
|
||||
\x05\x09\x04\x00\x00\x00\x00\x00\x00\x04\x08\x03\x02\x05\x02*\
|
||||
U\x1b-\x5c\x1c\x05\x09\x03\x00Gb}\xda\xfa\x07@\
|
||||
W\x08\x12\x05\x11$\x0b'j\x82\x92\xd4n\x9f\xe5\xfb\
|
||||
\xa1\xe6\xfb%j\x82\x1b7\x11\x84\xdb\xf6.t\x8b\x00\
|
||||
D^&n\x86E\xa6\x94T\xae\x96}\xd9\xf6k\xd0\
|
||||
\xf2#;\x1b\x0a\x9d\xcf\x15J;\x00D]#G\x16\
|
||||
#6\x1c2S&Jz8\x01FaV\xb2\x9c/\
|
||||
z\x93'q\x8b,v\x90\x00Ie0{\x955\x82\
|
||||
\x9dY\x91D\x00E`H\xaa\x9bCk4d\xa3M\
|
||||
\x0aCK#\x86\x92z\xaeb7\x87\xa2.\xbf\xf5\x00\
|
||||
\xa3\xe1\x00Fb\x02\xa7\xe6\x1cIE\x00\xa1\xdf\x13[\
|
||||
u\x00Gb\x00\xa1\xdf\x00\xa2\xe0\x00\xa3\xe2\xab\xdb\x91\
|
||||
\xd0\xea\xc2\xcc\xe3\xc29S0\x9d\xd6}\xa0\xde}\x99\
|
||||
\xd8s[\x89J\x0b\x15\x08=\x8e\xa9j\xcd\xed+S\
|
||||
\x1c-X\x1d.[\x1e\x00=V\x00Fb\x00C]\
|
||||
\x00;S\x00E_\x00AZ*P\x1cw\xbb]\x80\
|
||||
\xc2h\x00?X,W\x1dz\xbea\x83\xc4l\x00\x93\
|
||||
\xccx\xbc_-Z\x1d~\xc0e,V\x1d+U\x1d\
|
||||
\x00\x9e\xdb\x00\x8e\xc5\x00\x91\xca*R\x1c\x00Ie\x85\
|
||||
\xc5m\x00\x8c\xc2\x00\x9a\xd6)M\x1b\x00B\x5c\x00:\
|
||||
P\x00\x9c\xd8\x00\x94\xce\x82\xc3j\x89\xc8r\x00\x97\xd2\
|
||||
.]\x1e(K\x1b&F\x1a\x00\x8a\xbf\x00\xa3\xe1\x00\
|
||||
\xa0\xdeg\xb0L\x7f\xc1gm\xb5S}\xbfd\x00\x99\
|
||||
\xd3/^\x1e\x11\x22\x0c0`\x1e\x00\x8f\xc7t\xba[\
|
||||
o\xb6U\x00\xa5\xe4\x00\x88\xbc\x008N{\xbfc)\
|
||||
N\x1c/_\x1e\x86\xc6o\x9e\xd7\x890b\x1f%B\
|
||||
\x1a\x00\x83\xb5\x00\x85\xb9k\xb3Qq\xb7W'H\x1b\
|
||||
i\xb2O\x8e\xccx\x88\xc7p\x00\xa7\xe7\x006L\x9a\
|
||||
\xd4\x85s\xb8Yr\xb8X\x92\xce{\x8c\xcau\x94\xd0\
|
||||
~\x8a\xc9s\x00\x16\x1e\x97\xd2\x81\x15(\x0e\x00\xa9\xe9\
|
||||
\x00\x96\xd0\x00~\xb0\x00\xaa\xec\x18.\x11\x8b\xc9u\x0b\
|
||||
\x15\x07%D\x19\x00&3\x00\x1e*\x00\xac\xee\x03\xb0\
|
||||
\xf2\x0e\x1c\x0a\x00->\x1c4\x14\x00\xae\xf0>]2\
|
||||
P|@\xa4\xedx/`\x1eQ\xc4\xed\x013FO\
|
||||
x@\x86\xc6n\x1f9\x16#>\x19PtC \xa9\
|
||||
\xdb;U1d\x94O>\xbb\xe9\x01Qo\x00Wy\
|
||||
7Z)/G&\x01`\x831c\x1f\x0bCG0\
|
||||
T\x22\x10\xa6\xdf\x0aJ]\x10Ne\x92\xca{\x89\xc7\
|
||||
d\xa8\xde\x93D\xa0\x89\x1d\xa0\xd1Gn3n\xa1R\
|
||||
\x9e\xe2w%\xb8\xf0\x17\x97\xc7\x18Xn$q~?\
|
||||
k>3O's\xadU\x0d)\x1d\x0b51c\xc2\
|
||||
\xa1\x82\xbea[\x87C\x02p\x96`\x9fs;zY\
|
||||
\x09u\x9d\x18J8\x12=7\x1dPF.bJp\
|
||||
\xc2y\x00\xff\x00z\x00\x04,;\xc9\x0b\x00\x00\x01\x00\
|
||||
tRNS\x00\x17\x11%\x09\x19\x0d\x01\x06\x03K,\
|
||||
\x1c3!\x09U\x0e{9\xf9C\xfefq^>\x97\
|
||||
\x88\xf9\xf9\xa5\xecq\xfd\xb9\xcc\xef\xfeiW\xdf\xe0D\
|
||||
\xf9\xec\xd1\xfb\xf61\x1f\xadd\xf6h\xee\x96\xc1\xdd\xaa\
|
||||
\xf7\xc4\xad\xb9\xf7\xf7\xfa\xec\x88\xfb\xcd\xf6\xf5\xfe\xfd\xfd\
|
||||
n\xb9\xcft;\xef\xa4\x0f\xdf\xd0\xa2\x8f\x83u2\xab\
|
||||
\xbb\xcb\xce\xdc\xfd\x14\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\
|
||||
\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\
|
||||
\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\
|
||||
\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\
|
||||
\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\
|
||||
\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\
|
||||
\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\
|
||||
\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\
|
||||
\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\
|
||||
\xff\xff\xff\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\
|
||||
\xff\xff\x09\x193o\xbfu\x00\x00\x0c%IDAT\
|
||||
x\xda\xec\x9aiT\x14W\x1a\x86U\x10hDQ\x14\
|
||||
\x04\xb7$\xe8`\xc6IF'\x1a5\x893C\xc6h\
|
||||
\xd4$\x93\xcc\xbeo(6\xb2)\xa2\x12\x05\x89\xf4\xa8\
|
||||
\x11P\xd1\x91\x88#.\x19\x04Y\x04\xc1\xd6F\x81\x06\
|
||||
\x8c\xa0\x10C\x0b\xad\x88\xa22\xda\x86(q\xc1}M\
|
||||
r\xce|\xf7\xdeZnU\xdd\xc2\xaa\xfe1\xbfx\xe9\
|
||||
\xe6\x1c\xff\xf8<\xdf[\xf7\xd6\xad\xd6\xee\xd1\xa3;\xdd\
|
||||
\xe9Nw\xba\xd3\x1d.\xee\x8a\xfc\x1f\xe1\xde\xef\xbf\xfb\
|
||||
\xee\x0bBF\xbf0\x9a\xcf\x8b\xa3_\xe4\xf3\x03>?\
|
||||
\xe2\xf2\x0a\xce? \x03p\xbcUc\x90E9\xde\x80\
|
||||
#G\x8e\x1c\x83\x1f\x94\xaf\x8f|Mr\x1a\xe7\x0b\xb5\
|
||||
\x9c\xfe\xe24\x97w^B\xf9\x9e\x98\xef\xf3\xf9!\x9f\
|
||||
\x1f\xe3\xfc\x14\xe7'8\xbf|\xe3\x8d\xb7$\x02\x98\x0e\
|
||||
\x12\x9f\xa1\x94\x97\x97\x1f<\x08\xaf\x83\x07\xf7\xec\xd9\xf3\
|
||||
o\x94\xb5k\xd7\xfe\x97\xcfI\xf4#\xe6\xf4\xdfo\x5c\
|
||||
\xc7\xb9t\xfd\x12\x97\x8b\x97.\xa2\x18/\x1a\x8dI\xc6\
|
||||
\xa4@cRxRRx8\xfc\x12~\xc3\xaf\xa4\x97\
|
||||
\x15\x0d\x1c;\xc6\xd1\xcb\x09Z\x84\xaf]\xb7v\xdd\xba\
|
||||
u\x1fB\xfe\x09\xf9\x08\xf2/\x94\x8f?>t\xe8\xd0\
|
||||
\xc9w\x02\x0b33\x0b\x0b\x0b\xe1m\xca\xc41\x99L\
|
||||
a\xa6\xb00\xfc\x0e\x0b%\x89\xe6\x13N$\xe4\x02<\
|
||||
\xbf\x9c\xe2\x0bxD\xc7\xf8\x0f9\xfcG\x98\x0e\xf8\x95\
|
||||
+W\x22\x01.\x99<?\xcc\x84\xd9\x08O\x04\xa2C\
|
||||
\xe5|\xa3Q&\x80\xf9\xe5\xf2\xf1\x05\xbc||\x1eO\
|
||||
\x0b\x08\xe3\x9b$\xfc0j\xfep\x91/\x118&\x8e\
|
||||
\xafl\xbf\xab\xf1W.\x5cv\xf2g\x81\xea|\xe9\xf4\
|
||||
b\xfdF\x85\xc0gZ\xc6W\xe2\x17.[\xc8\x09d\
|
||||
R\xfc0\x81\x1fF.\x7f\xa8\xbc~\xb9\x00k\xf1i\
|
||||
h\x1f\xf8\xcb\x96}\x85\x05\x18\xe3s\xcbO( \x5c\
|
||||
\xca\x9f'\x15\xe0\xf0:\x16\x1f\xc1s\x02]\xf0\x99\xf5\
|
||||
\x1b\xe7\xcd\x93\x088\xd5>\xe6o\xde\x0c\x02\xec\xfa\x95\
|
||||
\xf3S\xe3+\x05\x9e\xbd\xf8\x84\x9d/\x8e\xbfy\xb3(\
|
||||
\xc0\x1a?T\xad~\x94\xe7%\x02N\xb5\x8f\xf8K\xbf\
|
||||
z3Z\x13_R?d.-\xa0o\xf1-\x14\xc7\
|
||||
_\xba\x94\x13\xe8\x0a\xcf\xa8\x1f\xf8R\x01][\x9f\xc6\
|
||||
/MD\x02\xba\xeb\x07\xbeD@\xdf\xd6\xa7\xf8\x89\x89\
|
||||
H@\x7f\xfds\x95\x02z\xb6\xbe8>\xe4\xda\x9b\xa1\
|
||||
\xfa\xebW\x08\xe8Z|\x9b\xc5\xf1\x13\x13S\xaf\xe1\x06\
|
||||
t\xd6/\x17\xd0\xb9\xf5)|*i@S\xfdF\x1a\
|
||||
\xaf\x10\xd0\xb3\xf5\xf9\xf6SQ\xae\xbd\x14\xaa\xbf~H\
|
||||
\x82D@\xdf\xd6\x17\xc6OM\xdd\xbaU\x14\xd0^\x7f\
|
||||
\xf0\xf3?\x97<\x92y\xff\xf6\xbd\xf7~\xf3\xeb_h\
|
||||
\xde\xfa\xe2\xf8[)\x81g\xd5\xff2\x82\xbe5\xd1\xf3\
|
||||
\x03\x97_\xa1\xa7p\xd6\x93\xf9\x80W\xde\xd7\xb4\xf5\xc5\
|
||||
\xf1\x91\xc0\x8dPm\xf5O\xecax\xf6\x87\x83\x09\xaa\
|
||||
\xf8\xec\xb2\xb2\xecDI\xfb\x98\x9f\x9dM\x044\xd4?\
|
||||
Q\xcb'\x84\x09\xaa[\xdf\xaf\xa1\xb6\xfa\xf0\x81\xc3\xd5\
|
||||
\xb5\x85a\xc6\x84\x963\xe7\xfc\x1e<\x06\xa5l$\x10\
|
||||
\x0d\x8f\x9f\x85\x0d\x0d\xb5\xb5\xb5\xd5\xd5\xd5&\xd5\xd5\xaf\
|
||||
M@\xb5}\xbf\xe8Ld \x0b\x08\x99\x1a\xaa\x0f\xe3\
|
||||
T\xe3\xccP\xbd\xf9i\x16`/>\xbf\xe8PS\x83\
|
||||
LA\xc4\xd6ri\xa8\x0dT]\xfd\x1a\x05\xd4\xb6>\
|
||||
\x08@\xd1`pX\xc4cp\x03\x09y.4\x99\x02\
|
||||
Uo>\xda\x04T\xb7\xbe_xh\xa8)\xb3P(\
|
||||
\x81\xe0\x1b2\xf1]\x10/>\xe0\x02/P\xed\xec\x99\
|
||||
[]\xf3\xb7\x91#\x9f\x1b\xea\xe3\xef\xdf\xdf\xf7\x83?\
|
||||
\xf6\xf6\xf6f}J\x9d\xa0\xba\xf5\xfd\xc2\xa1\x82L\xb4\
|
||||
\xd6p\x09\xc0\xaf\xad-4E\x1b\xc9\xdf\x9f\x80\xd3\x92\
|
||||
\xd0\xd2\x12\xacz\xf3\xab\xae\xacI/\xadhlj\xed\
|
||||
<U\x87rJ\xbc\x15x\xff\xe1\xf7\xbf\xfb\xd3\x9f\xff\
|
||||
\x12\xd4\xf1\xf9]\xd5\xad\xef\x97\xc4\x0b\xc0Z?|\x00\
|
||||
\xc6o\xc8\x8c\x9e\x0bD\x923-gH\x82\xd5\xee\xfd\
|
||||
\x09O\x11\x1a\xd8g\xcf\x9emk\x8b\x88\x88\x18$\x0e\
|
||||
\xde\xfbK>wUo\xbc\x94\x002\x80\xf1C\xe7%\
|
||||
p\xd4s\xe7\xe0\xc5%\x98Y?\x12\xf8\x06q\xb7o\
|
||||
_\xb1\x1dG*\xf0)\x9f\xbbj\xa7~\xaa\x9f\x11\xaf\
|
||||
\xc2\x0b\xdf|\xfb\xed\xcd\x9b7\xaf\xc0\xfb\xd1\xa3G7\
|
||||
\xe7\xfc\xe8<\x08V;{\x12\x9e$''\xafX\
|
||||
!\xf0\xb7K\x05\xbe\xe4\x04\xd4N\xfd\xd4\x99\x0f\x1f>\
|
||||
\x8c\x09\xfa\x1c\xd2\xd1\x11\x14t\x19%\x08\xae\x19\xfas\
|
||||
\xd0\xfe\xef\xbe{\xd8\xde\xde>s\xe6\xcc\xc7\x8f\x83\x99\
|
||||
|\xb4B^\x95\xf0\xd9\x0d\x14\xddU9\xf5SS\xa7\
|
||||
\x99\xcd\x16\x8b\xc3a\xb1\x98?-*\xea\xe8\xc0hI\
|
||||
\x82\xf6\xcf\xba\xda\x5c\x7fs\x86\x12\x9f@\xd6\xe8\xab\xc9\
|
||||
4\x9e)P\x04\x0d\xa8\x1d{\xd3\xf2\xf3\xf3\xf7\xe5[\
|
||||
\xf7\xe1\xe4;\x1c\x0e\xab\xb5\xc4\x5cb)\xb2t8f\
|
||||
]\xbdo\xaf\xeb\xeclm\xcdM\xa9\xca\x9a\xc1\xac\x1f\
|
||||
\x0bH\xf9\xf1\x0a\x81\x22\x18m\x8a\xda\xa9O\x04 \xd6\
|
||||
\xfd\xfb\xf7\xaf^]PP\xb0\x13r\xe2\xc4\x89\x82}\
|
||||
\xf6\xdc,\x9c*\xf4\xae\x9a\xc1\xac\x9f\x08P\xf8\x88x\
|
||||
\x85\x00\xe2\x17MQ;\xf5\x91\x00\xc2[\x11\x9e\xf0O\
|
||||
,_\xbe<&&\xa6\xc0\xde\x94\xc5\xa7\x0a\x090\xc7\
|
||||
G\x02\xf4\xf8\xf1\xf1!2\x01\xccG\x02\xecS?{\
|
||||
\x9a\xc8'\xe3s\xfcU;\xed\x14>%\xe5\x02\xeb\xf2\
|
||||
\x8b\x02\x22_*PD\xf8 o\x9f;\xf5\xb3\xc7\
|
||||
*\xf9\x08\xbfJ\x14\xc0|N@1>\x11\x10\xf0\xc0\
|
||||
\x975\x80\xf1E\x96)\xac\xf6\x11\x1f\x04\x18\xf5\x03?\
|
||||
j\xb9\x9d\xc2\x13\x01\xc6\xf8p\x9f~B\x8f/\x13(\
|
||||
*\x12\x05\x94\xed\xa3\xec\x1a\xcb\xaa\x1f\xf8\x9c\x00\xcfG\
|
||||
\x02\xca\xcb\x0f\xa7D\xc2\xbc'R~\x9cR\xc0b\xb1\
|
||||
\x8cc\xb5\x0f\xf8] \xc0\xa8\x1f\xf8Q1v\x9a\x0f\
|
||||
\x02r\xfc\xdc\xe8\xc2;wn\x97V\x9c\x0a\xa1\xf0!\
|
||||
qJ\x01\xd8\xd3H@\xd9\xfe.\x94\xb1\x22\x9f\x1a?\
|
||||
**\x0d\x04D|J\xee\x05\x8ao45\xdc\xb9}\
|
||||
;\x1d\xa5\xb4\xf4(\x12\x10\xc6\x8fS\x0aXP\xc6\xb1\
|
||||
\xda'\x02\xac\xfa\x81\x0f\x024\x9f\x13\x88\x86G\x97\xdb\
|
||||
55\xe9\xf0\x22\xf8\x8a\x8a\xc6\xba\x10\x9a\xbfd\x89T\
|
||||
\xc0b\x11\x04\x14\xed\xa3\x94\x8de\xd5\x9f\x96\x96\xb6x\
|
||||
\x95\x9d\xc2\xe7\xe6>\x85G\xc4\x03\x95\x95\x955\x955\
|
||||
(\xe95\x04\x7f\xf4hS]\x88X?\xf0\xa5\x02\x04\
|
||||
o6\x8fc\x8f\xbf\xab\xacl,\xab\xfe\xb4\xc5\x8bA\
|
||||
\x80\xe6\xe7\x96\x226\x0e\xe6\xf3\xf8\xc6\xa6,\x10\x10\xea\
|
||||
\x07\xfe\xfc\xe1\x94\x00\xcf7\x8fc\x8f\x0fi\x97\xed>\
|
||||
\x9e\xbf\x91\x17\xc8\xcd\xe5\x05\x98\xfc\xa6\xdc\xba8j\xfc\
|
||||
\xf9\xf3\x95\x02fN@\xba\xf8v\x95\x01\x1f^\xed\xac\
|
||||
\xfa\x81\xcf\x0bp\xfc\xe4\xf4J\xd1\x80\xf0\x01\xdf(\x08\
|
||||
\xc4\x09\xfc\xd92\x01\xb3\x99\x08P\xedgs\xe3\x93\x06\
|
||||
X\xf5\x03\x7f[\x94\x9d\xe6\xf3\x02\xfc\xf8\xa8\x00r\x05\
|
||||
Z\xeb\x96H\xf82\x01\xc277?\xbdp\xf1\xfa\xb9\
|
||||
\x07e\xd4\xf8\x18\x0f\x02\xac\xfa\x81\xbf-\xcdN\xe1\x93\
|
||||
\x93K\x85\xea\x11\x1a\xd8\x00om\xc5\xcf\x82q!\x14\
|
||||
^&@\xf0%%\xcdM\x8dG+J\xe1\xe7\xce\x85\
|
||||
\x8b- \x22\xa6\x1d\xe3c\xa4\xf5o\xdb\xb6`\x01\x08\
|
||||
P\xfc\xe4\x0a\x09;\x8b<\x02\xc3c\xa8l|\x99\x00\
|
||||
\xcf/i\xce\xca\xe2\x14P\xd2\xd3o\x0b\x22\xed\xac\xfa\
|
||||
\x81\x0f\x024?\xf9h\x85\xd09a\xb7\xb5\x85\x84H\
|
||||
W\x1f\xc6\xcf^\xa4\x10(A\x02pS!\x0a\x98O\
|
||||
\xee\x22\xe9H\xe4\x11\xab~\xe0/Xl\xa7\xf0\xc9\xc9\
|
||||
\x8d\xb8\xf2N\xfc\xf8\xdd\x16\x12\x1fO\xdf\xfb$|\xb9\
|
||||
@I\x09/P\xd5\x84\x0c*\x04\x01\x22a\x93\xf3\x09\
|
||||
>6\x96\x08\xf0\xfc\xed\xe4r\x9fm\x8b\x90\x1d=\x0a\
|
||||
\xbeL\x00\xe3\xf3\xf3I\x03M\x8d\xd8 \x9d\x8e\x8dU\
|
||||
?\xf0c7\xdaE<<vB\xe3\x11\xd2\x07\x0fV\
|
||||
\xfd\x8b\x16\xcd\x99#\x11\xc0xN\x00\x1a\x80\x0aP\xe8\
|
||||
\x1al\xac\xfac\x89\x00\xc5\x97>w\xaa\x8f?G*\
|
||||
P\xc2\x15\x90\xdf\x9c\x92RU\xd5v\xf6\x0a\x0e4\xd9\
|
||||
\xd9\x0a+\x02{\xd8X\xf5\xc7\xc6FFn\xb4+\xf8\
|
||||
\xca\xfa\x97P|\x82\x97\x0b\xa0\xf1!\xb3\x9a\xaf\xde\xbb\
|
||||
|\xef\xde\xde[W\xaf67\xdf\xbf__\x8f=:\
|
||||
;s\xb3\xeae\xbb\x8f\xe7Gn\xb3;3\xbe\xb2\x81\
|
||||
|\x12G\x09<\xf2\x9b\x1d%\xfb\x82.\xdf\x8b\xbc\xc5\
|
||||
{\xd8\xae\x5cif\xd5\x0f\xfc\xc8\x05\xf6g\x8d\xcf\xe6\
|
||||
\xaf\x915\x80\xc3=xZ\xad\xf9\x0e\xab\xc3Q\x02\x1a\
|
||||
\x05\xbc\xc7-V\xfd\x90\x0cN\x80=~\x88*~\x8d\
|
||||
D@\xc0K>w\x14\xac\xb6ZW;\x1c\xf9\xa8\x8e\
|
||||
\xcb\xf7\x98\xfc\x8c\x8c\x8cX\x9b\x13\xf5\x03\x7f\x93B\x80\
|
||||
\xfd\xb9#&f\xf9\xce\x82\x9dVk\x01\xab\xfe\x0cN\
|
||||
@[\xfd\x8bx>\xc2o\xda4B&\xa0\xf2\xb9\x83\
|
||||
\xbb\xf7G\xa5\xb1\xea\x87\xec\x8d\xb5\xad\xd0_?\xf0w\
|
||||
H\x05\xf6\xc9\xf8\xb2\xa3O\xa5~\xe0c\x01\xdd\xf5\x03\
|
||||
_*\xc0\xae\x7f\x95\xda\xcdG\x18\x7f\xef\xde\xe2H\xdb\
|
||||
\x0a)>^\xcb\xf8;v\x1c\xa7\x05\xba\xaa_\xca\x8f\
|
||||
\x95\xf2\x8b\x8bwG\xda\x9c\x19\x7f\xc7\xf1O\xa4\x02V\
|
||||
\xb5\xcf\x1d]\xd6\x0f|\x22\xa0y\xf3#<\xe1K\x04\
|
||||
\xac\xf4\xee\xd3Q?\xf0\xb7d\xd8\xf4\xae>\x8c\xff\xe4\
|
||||
?\x12\x01'\xeb\x07>\x12\xd0_?\xf0%\x02\xce\xd6\
|
||||
\x0f\xfc-{m*G\x8f*\xfe8\xc2\xcb\x04\xd4\xeb\
|
||||
_\xdcU\xfd\x90\x0dD@\xef\xf82\x01\x84/p\xa2\
|
||||
~\xe0\x13\x01'\xf8\xe7i\x01g\xeb\x07\xfe\x86b\x9b\
|
||||
\xde\xd5\x87\xf1\xe7\xcf\x8fp\xa7\x05\xb4\xd7O\xf17\xa0\
|
||||
\x14\xd7;3>\x12\xf00\x88\x02zn~\xf4\xf8\x1b\
|
||||
rrv\xd7k:z\xa8\xd5\x87\xf1 \xe0\xe6\xc1u\
|
||||
\xe0\xde\x9b\xaf?Fg\xfd\xc0\x07\x01'\xea\xc7\x02=\
|
||||
]\x0d\x82\x80\x93\xf5\x03?gK\xbd\x13\xf5#\xfex\
|
||||
/7\x22\xe0n\xe8\xa9\xa3\xfeb\xc9\xf899yX\
|
||||
@/~\xc4\xa8a\x9e}\xf8\x06\xdc\x0d\xfd\xa8\xfa\xa3\
|
||||
\xf4\xd4\x9f\x93\x97\x87\x04t\x8e?i\xd4P\x9f\x00\xcf\
|
||||
\xbe\xfdzy\x08\x02\xce\xd6\x9f\x87\x05\x9ey\xf4P\xab\
|
||||
\xef\xf8\xa4Q\xcf\x0d\xf3\x0f\xf0\x1c\xd8\xc7\xab\x97\xab\x81\
|
||||
[\x84\x06\xafU\xba\xeb\x17\xf8y\x1b\xea\xb5\xdf\xfb\xc6\
|
||||
\x8c\x1c:\xccgp\x7f_\xc0\xf7t\xf3\xe0\xf9=\x0c\
|
||||
\xae.\xfd'\xffu\x96Z\xfd\x91\xea\xf5\xe7\xe5\xad_\
|
||||
\x0f\x02\x9a\xf8\xc39\xba\xe7\x90\xbe.\x80w\x15\xf9=\
|
||||
\xdc=\xdcz\xba\x0c\xf4\xf4\x9f<}j\xac\xbe\xfa\x81\
|
||||
\x0f\x02]\x1f=\x08\x7f\x9c\xa3\x07x\xc2\xf0\x1c\xde@\
|
||||
\xfd\xff\xb9\x01\x0c\xbc\x5c\xfa\x0e\xf1\xec?x\xf2\xf8\xe9\
|
||||
o/\xd0\x5c\xffz\x22\xd0\xf5\xf8;&\x8dBt\xff\
|
||||
\x004<\xc2\xf7r\x95\xf1\xc1\xc0\xe0\xe1\xea\xd6\xabg\
|
||||
?\x97\xbe\x03}\xfb\x07\xf8O~\xed\xf5[]\xd7\x9f\
|
||||
\xc3\xe3\x91@W\xfc5\xb0\xe88\xba\xef@\x82wS\
|
||||
\xe0\xc9V0x`\x09/\x97>\xb8\x8aa\xe3\xa7O\
|
||||
\xdd\x9d\xd1\xf5\xe5\xe7\x05\xd4\xf0\xc3\xc7\x10:\x5cx\xdf\
|
||||
!\x22\xde\xc3\xa0\xf6\x95aw\xae\x09\xaf~X\x02W\
|
||||
\xf1vW\xf5\x13\x016\x7f\xd0\x98\x91\x84\xce\x0d\x8f\xf0\
|
||||
j\xe3+$\xc8\xf5\xe83\xd0\xd73`\xb0\xcfx\xb0\
|
||||
P\xa9_\x14\x90\x1e=k&\xd1\xf4!\x18\xdf\xcfK\
|
||||
\x0b^&\xc1_\x0f\x7ftA\xf2\x18\xe3\xf3\x02\xf4\xf8\
|
||||
s`\xd1\x09t\x19^\x1b\x9f|\xd3[X\x14p=\
|
||||
\xd0\xd2\x1c\xec3\xf4\xb5\xd7\xa7\xe6\xc9\xf9X@\xe4\xcf\
|
||||
\x1e#\xd2\xd1\xf04\xdeU;^)\x81\xaf\x07\xae\x02\
|
||||
.\xc8z\xa9\x80\xf8O\x0e\x02\x9d\x1f\x9e\xc7\xf3\x8bO\
|
||||
\xf7\x17\xd6\x91\x03'\x81\x16\x05Y\x9a>C\xe1\x82H\
|
||||
\x04\x10}\x10Z\xf2<\x1d\x86W\xe2\x0dN~_\xfe\
|
||||
\x7f\xed\x9b1\x0e\x830\x0cEE\x14\xa5\x80P\x07\xa4\
|
||||
\x0e\x9dz9\x8e\xc0!{,\xfe\xb7\xdd\x8a\xb4\x88\x81\
|
||||
\xa4e\xf1\xbb\xc0{\xb1a\xf4:\xc2>\x8a;F\xf1\
|
||||
\xc0B,`\x9am\xed\x9c<\xed:\xfb\x95>\x1e\xd7\
|
||||
oG\xe8>0\x0a,\xe4\xa9\x7f\xbb\xad\xbd\xb7\xb7\xd3\
|
||||
\x9e\xe9\x8b\xcf\x05^\x0dY\x04F1\x8eo\xf7\x8d\x0f\
|
||||
\x87\x1br\xb1\x8b\xbeh\xfa\xfb\x11W\xad\xe8\xeds\x13\
|
||||
/\xcdpCN{e\xfdV\x04*\xd4(\x0cBC\
|
||||
\x82\xd8U_\xfdX\xc3\x1a\x18\x91R\xf8$\x091\xd2\
|
||||
\xdev\x95\x9f\xff\x1d!\x1d9\xad\xa1\xe7\x1c\xbf=\x8c\
|
||||
\xe9v\xf9\xdf\xa5\xcc\xe5\xd4\x1b\x1d\xc7q\x1c\xc7)c\
|
||||
\x01\xf8\x0eHZ\xe9\xd3K\x9a\x00\x00\x00\x00IEN\
|
||||
D\xaeB`\x82\
|
||||
"
|
||||
|
||||
qt_resource_name = b"\
|
||||
\x00\x08\
|
||||
\x05\xe2Y'\
|
||||
\x00l\
|
||||
\x00o\x00g\x00o\x00.\x00p\x00n\x00g\
|
||||
"
|
||||
|
||||
qt_resource_struct = b"\
|
||||
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
|
||||
\x00\x00\x00\x00\x00\x00\x00\x00\
|
||||
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
|
||||
\x00\x00\x01\x99\xf9l\xfe\x95\
|
||||
"
|
||||
|
||||
def qInitResources():
|
||||
QtCore.qRegisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)
|
||||
|
||||
def qCleanupResources():
|
||||
QtCore.qUnregisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)
|
||||
|
||||
qInitResources()
|
||||
5
resources.qrc
Normal file
5
resources.qrc
Normal file
@@ -0,0 +1,5 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>logo.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
Reference in New Issue
Block a user