2026-03-02 14:29:58 +08:00
|
|
|
|
import sys
|
|
|
|
|
|
import os
|
|
|
|
|
|
import re
|
|
|
|
|
|
import json
|
|
|
|
|
|
import base64
|
|
|
|
|
|
import time
|
|
|
|
|
|
from PyQt6 import *
|
|
|
|
|
|
from PyQt6.QtCore import *
|
|
|
|
|
|
from PyQt6.QtGui import *
|
|
|
|
|
|
from PyQt6.QtWidgets import *
|
|
|
|
|
|
|
|
|
|
|
|
from PyQt6.QtQuick import *
|
|
|
|
|
|
from PyQt6.QtQml import *
|
|
|
|
|
|
|
|
|
|
|
|
from projectForm import ProjectForm
|
|
|
|
|
|
from devModelForm import DevModelForm
|
|
|
|
|
|
from deviceForm import DeviceForm
|
|
|
|
|
|
from taskForm import TaskForm
|
|
|
|
|
|
from dataSyncForm import DataSyncForm
|
|
|
|
|
|
from userForm import UserForm
|
|
|
|
|
|
from logForm import LogForm
|
|
|
|
|
|
from config import config
|
|
|
|
|
|
from logs import log
|
|
|
|
|
|
from influxDB import influxdb
|
|
|
|
|
|
from grafana import grafana
|
|
|
|
|
|
from taskListForm import TaskListForm
|
|
|
|
|
|
from loginForm import LoginForm
|
|
|
|
|
|
from interfaceSession.interfaceManager import interfaceManager
|
|
|
|
|
|
from influxdbModel.influxdbManager import influxdbManager
|
|
|
|
|
|
from deviceModel.deviceManager import deviceManager
|
|
|
|
|
|
from taskModel.taskActuatorManager import taskActuatorManager
|
|
|
|
|
|
from taskGroupModel.taskGroupManager import taskGroupManager
|
|
|
|
|
|
from taskModel.taskManager import taskManager
|
|
|
|
|
|
from instructionModel.instructionManager import instructionManager
|
|
|
|
|
|
from projectModel.projectManager import projectManager
|
|
|
|
|
|
from userModel.userManager import userManager
|
|
|
|
|
|
from common import common
|
|
|
|
|
|
from models import Session
|
|
|
|
|
|
from version import app_version
|
|
|
|
|
|
from ui.Ui_mainForm import Ui_MainWindow
|
|
|
|
|
|
from dog import dog
|
|
|
|
|
|
from dog import suDog
|
|
|
|
|
|
import ui.res_rc
|
|
|
|
|
|
|
|
|
|
|
|
class LogModel(QAbstractListModel):
|
|
|
|
|
|
@pyqtSlot(str, str)
|
|
|
|
|
|
def filter_logs(self, level, tag):
|
|
|
|
|
|
self.beginResetModel()
|
|
|
|
|
|
self.filtered_data = [log for log in self.all_logs
|
|
|
|
|
|
if (not level or log["level"] == level)
|
|
|
|
|
|
and (not tag or log["tag"] == tag)]
|
|
|
|
|
|
self.endResetModel()
|
|
|
|
|
|
|
|
|
|
|
|
class AsyncLoader(QThread):
|
|
|
|
|
|
loaded = pyqtSignal()
|
|
|
|
|
|
def run(self):
|
|
|
|
|
|
self.loaded.emit()
|
|
|
|
|
|
class MainWindow(QMainWindow):
|
|
|
|
|
|
windowClose = pyqtSignal()
|
|
|
|
|
|
def __init__(self, parent=None):
|
|
|
|
|
|
super().__init__(parent)
|
|
|
|
|
|
self.initdataDb()
|
|
|
|
|
|
self.loginForm = LoginForm()
|
|
|
|
|
|
self.loginForm.show()
|
|
|
|
|
|
self.setConfig()
|
|
|
|
|
|
self._run()
|
|
|
|
|
|
self.initWindow()
|
|
|
|
|
|
|
|
|
|
|
|
def initdataDb(self):
|
|
|
|
|
|
dataDB = os.path.join(os.path.dirname(__file__),'data.db')
|
|
|
|
|
|
trigger_path = os.path.join(os.path.dirname(__file__),'sqls','trigger')
|
|
|
|
|
|
dev_model_path = os.path.join(os.path.dirname(__file__),'sqls','dev_model')
|
|
|
|
|
|
device_path = os.path.join(os.path.dirname(__file__),'sqls','device')
|
|
|
|
|
|
device_group_path = os.path.join(os.path.dirname(__file__),'sqls','device_group')
|
|
|
|
|
|
device_model_group_path = os.path.join(os.path.dirname(__file__),'sqls','device_model_group')
|
|
|
|
|
|
public_path = os.path.join(os.path.dirname(__file__),'sqls','public')
|
|
|
|
|
|
common.import_sql_to_database(dataDB, trigger_path)
|
|
|
|
|
|
common.import_sql_to_database(dataDB, dev_model_path)
|
|
|
|
|
|
common.import_sql_to_database(dataDB, device_path)
|
|
|
|
|
|
common.import_sql_to_database(dataDB, device_group_path)
|
|
|
|
|
|
common.import_sql_to_database(dataDB, device_model_group_path)
|
|
|
|
|
|
common.import_sql_to_database(dataDB, public_path)
|
|
|
|
|
|
Session.checkId()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def closeEvent(self, event):
|
|
|
|
|
|
self.windowClose.emit()
|
|
|
|
|
|
self._exit()
|
|
|
|
|
|
event.accept() # 接受关闭事件
|
|
|
|
|
|
|
|
|
|
|
|
def initWindow(self):
|
|
|
|
|
|
self.ui = Ui_MainWindow()
|
|
|
|
|
|
self.ui.setupUi(self)
|
|
|
|
|
|
self.ui.tbDefault.setVisible(False)
|
|
|
|
|
|
self.isDebugQML = False #DEBUG
|
|
|
|
|
|
self.setWindowTitle("TG-TestingPlatform "+app_version.data["version"])
|
|
|
|
|
|
self.ui.lbtitle.setText("TG-TestingPlatform "+app_version.data["version"])
|
|
|
|
|
|
self.ui.logWidget.setVisible(True)
|
|
|
|
|
|
self.projectModel = QStandardItemModel()
|
|
|
|
|
|
self.projectHistoryModel = QStandardItemModel()
|
|
|
|
|
|
self.projectForm = ProjectForm()
|
|
|
|
|
|
self.devModelWidget = DevModelForm()
|
|
|
|
|
|
self.deviceWidget = DeviceForm()
|
|
|
|
|
|
self.taskWidget = TaskForm()
|
|
|
|
|
|
self.dataSyncForm = DataSyncForm()
|
|
|
|
|
|
self.userWidget = UserForm()
|
|
|
|
|
|
self.logWidget = LogForm()
|
|
|
|
|
|
|
|
|
|
|
|
self.setWindowFlags(Qt.WindowType.FramelessWindowHint)
|
|
|
|
|
|
# self.setWindowFlags(Qt.WindowType.WindowCloseButtonHint)
|
|
|
|
|
|
self.setMinimumSize(800, 600)
|
|
|
|
|
|
self.setMaximumSize(1920, 1080) # 设置最大大小
|
|
|
|
|
|
self.windowClose.connect(common.onWindowClose)
|
2026-04-17 15:31:41 +08:00
|
|
|
|
self.ui.tbStopAll.clicked.connect(self.onStopAllClicked)
|
|
|
|
|
|
# 连接 stopAllRequested 信号
|
|
|
|
|
|
taskActuatorManager.stopAllRequested.connect(self.onStopAllRequested)
|
2026-03-02 14:29:58 +08:00
|
|
|
|
self.ui.verticalLayout_devModel.addWidget(self.devModelWidget)
|
|
|
|
|
|
self.ui.verticalLayout_device.addWidget(self.deviceWidget)
|
|
|
|
|
|
self.ui.verticalLayout_task.addWidget(self.taskWidget)
|
|
|
|
|
|
self.ui.verticalLayout_dataSync.addWidget(self.dataSyncForm)
|
|
|
|
|
|
self.ui.verticalLayout_pro.addWidget(self.projectForm)
|
|
|
|
|
|
self.ui.verticalLayout_user.addWidget(self.userWidget)
|
|
|
|
|
|
self.ui.verticalLayout_log.addWidget(self.logWidget)
|
|
|
|
|
|
self.async_loader = AsyncLoader()
|
|
|
|
|
|
self.async_loader.loaded.connect(self.setQtQuick)
|
|
|
|
|
|
common.appReady.connect(self.appReady)
|
|
|
|
|
|
common.registQml.connect(self.registQml)
|
|
|
|
|
|
# 创建一个悬浮按钮
|
|
|
|
|
|
self.hide_button = QToolButton(self)
|
|
|
|
|
|
self.taskListForm = TaskListForm(self)
|
|
|
|
|
|
self.ui.toolBar.mousePressEvent = self.toolbar_mousePressEvent
|
|
|
|
|
|
self.ui.toolBar.mouseMoveEvent = self.toolbar_mouseMoveEvent
|
|
|
|
|
|
self.ui.toolBar.mouseReleaseEvent = self.toolbar_mouseReleaseEvent
|
|
|
|
|
|
# 设置按钮的绝对位置
|
|
|
|
|
|
self.hide_button.setGeometry(95, int((self.height() - 30) /2), 30, 30)
|
|
|
|
|
|
self.taskListForm.setGeometry(500, 420, 600, 500)
|
|
|
|
|
|
self.taskListForm.setVisible(False)
|
|
|
|
|
|
self.hide_button.setIcon(QIcon(":/resource/close.svg"))
|
|
|
|
|
|
self.hide_button.setStyleSheet("border-radius: 12px;")
|
|
|
|
|
|
self.hide_button.setIconSize(QSize(30, 30))
|
|
|
|
|
|
self.hide_button.setVisible(True)
|
|
|
|
|
|
self.createMenu()
|
|
|
|
|
|
self.connectBtnHandle()
|
|
|
|
|
|
self.dogIndex = 1
|
|
|
|
|
|
self.dogErrorIndex = 0
|
|
|
|
|
|
self.timer = QTimer(self)
|
|
|
|
|
|
self.timer.timeout.connect(self.updateDateTime)
|
|
|
|
|
|
self.ui.pbMax.setVisible(False)
|
|
|
|
|
|
self.timer.start(1000) # 设置定时器的时间间隔为1秒(1000毫秒)
|
|
|
|
|
|
# 在窗口大小改变事件中设置TaskListForm的位置
|
|
|
|
|
|
self.installEventFilter(self)
|
|
|
|
|
|
self.async_loader.start()
|
|
|
|
|
|
#DEBUG
|
|
|
|
|
|
if self.isDebugQML:
|
|
|
|
|
|
pass
|
|
|
|
|
|
else:
|
|
|
|
|
|
self.ui.tbDebug.setVisible(False)
|
|
|
|
|
|
|
|
|
|
|
|
def toolbar_mousePressEvent(self, event):
|
|
|
|
|
|
if event.button() == Qt.MouseButton.LeftButton:
|
|
|
|
|
|
self.oldPos = event.globalPosition()
|
|
|
|
|
|
|
|
|
|
|
|
def toolbar_mouseMoveEvent(self, event):
|
|
|
|
|
|
if self.oldPos:
|
|
|
|
|
|
delta = event.globalPosition() - self.oldPos
|
|
|
|
|
|
new_pos = self.pos() + QPoint(delta.toPoint())
|
|
|
|
|
|
self.move(new_pos)
|
|
|
|
|
|
self.oldPos = event.globalPosition()
|
|
|
|
|
|
|
|
|
|
|
|
def toolbar_mouseReleaseEvent(self, event):
|
|
|
|
|
|
if event.button() == Qt.MouseButton.LeftButton:
|
|
|
|
|
|
self.oldPos = None
|
|
|
|
|
|
|
|
|
|
|
|
def eventFilter(self, obj, event):
|
|
|
|
|
|
if event.type() == QEvent.Type.Resize:
|
|
|
|
|
|
mainWinWidth = self.width()
|
|
|
|
|
|
mainWinHeight = self.height()
|
|
|
|
|
|
taskListFormHeight = self.taskListForm.height()
|
2026-04-17 15:31:41 +08:00
|
|
|
|
# 确保列表不会超出主窗口底部
|
|
|
|
|
|
maxHeight = mainWinHeight - 100 # 留出顶部空间
|
|
|
|
|
|
if taskListFormHeight > maxHeight:
|
|
|
|
|
|
taskListFormHeight = maxHeight
|
|
|
|
|
|
self.taskListForm.setMinimumHeight(maxHeight)
|
2026-03-02 14:29:58 +08:00
|
|
|
|
self.taskListForm.setGeometry(
|
|
|
|
|
|
int((mainWinWidth - self.taskListForm.width()) / 2), # 水平居中
|
|
|
|
|
|
int(mainWinHeight - taskListFormHeight - 40), # 设置在底部
|
|
|
|
|
|
int(self.taskListForm.width()),
|
|
|
|
|
|
int(taskListFormHeight)
|
|
|
|
|
|
)
|
|
|
|
|
|
self.hide_button.setGeometry(
|
|
|
|
|
|
self.hide_button.pos().x(), # 水平居中
|
|
|
|
|
|
int((mainWinHeight - self.hide_button.height()) /2), # 设置在底部
|
|
|
|
|
|
int(self.hide_button.width()),
|
|
|
|
|
|
int(self.hide_button.height())
|
|
|
|
|
|
)
|
|
|
|
|
|
return super().eventFilter(obj, event)
|
|
|
|
|
|
|
|
|
|
|
|
def appReady(self, instanceName):
|
|
|
|
|
|
self.ui.quickStackView.rootContext().setContextProperty(instanceName, common.qscript[instanceName])
|
|
|
|
|
|
self.ui.quickDebug.rootContext().setContextProperty(instanceName, common.qscript[instanceName])
|
|
|
|
|
|
|
|
|
|
|
|
def registQml(self,instanceName, className):
|
|
|
|
|
|
instance = common.qscript[instanceName]
|
|
|
|
|
|
qmlRegisterType(instance.__class__, className, 1, 0, className)
|
|
|
|
|
|
|
|
|
|
|
|
#qml资源加载
|
|
|
|
|
|
def setQtQuick(self):
|
|
|
|
|
|
|
|
|
|
|
|
self.ui.quickSetting.rootContext().setContextProperty("common", common)
|
|
|
|
|
|
self.ui.quickStackView.rootContext().setContextProperty("projectManager", projectManager)
|
|
|
|
|
|
self.ui.quickStackView.rootContext().setContextProperty("taskActuatorManager", taskActuatorManager)
|
|
|
|
|
|
self.ui.quickStackView.rootContext().setContextProperty("instructionManager", instructionManager)
|
|
|
|
|
|
self.ui.quickStackView.rootContext().setContextProperty("deviceManager", deviceManager)
|
|
|
|
|
|
self.ui.quickStackView.rootContext().setContextProperty("taskGroupManager", taskGroupManager)
|
|
|
|
|
|
self.ui.quickStackView.rootContext().setContextProperty("taskManager", taskManager)
|
|
|
|
|
|
self.ui.quickStackView.rootContext().setContextProperty("interfaceManager", interfaceManager)
|
|
|
|
|
|
self.ui.quickStackView.rootContext().setContextProperty("common", common)
|
|
|
|
|
|
self.ui.quickTaskbar.rootContext().setContextProperty("common", common)
|
|
|
|
|
|
self.ui.quickSetting.rootContext().setContextProperty("interfaceManager", interfaceManager)
|
|
|
|
|
|
self.ui.quickSetting.rootContext().setContextProperty("influxdbManager", influxdbManager)
|
|
|
|
|
|
|
|
|
|
|
|
self.ui.quickTaskbar.setSource(QUrl(common.firstPath()+"/TaskBar.qml"))
|
|
|
|
|
|
self.ui.quickStackView.setSource(QUrl(common.firstPath()+"/main.qml"))
|
|
|
|
|
|
self.ui.quickSetting.setSource(QUrl(common.firstPath()+"/SettingView.qml"))
|
|
|
|
|
|
|
|
|
|
|
|
if self.isDebugQML:
|
|
|
|
|
|
self.setDebugQML()
|
|
|
|
|
|
|
|
|
|
|
|
def setDebugQML(self):
|
|
|
|
|
|
self.ui.quickDebug.engine().clearComponentCache()
|
|
|
|
|
|
self.ui.quickDebug.rootContext().setContextProperty("logModel", LogModel())
|
|
|
|
|
|
self.ui.quickDebug.rootContext().setContextProperty("projectManager", projectManager)
|
|
|
|
|
|
self.ui.quickDebug.rootContext().setContextProperty("taskActuatorManager", taskActuatorManager)
|
|
|
|
|
|
self.ui.quickDebug.rootContext().setContextProperty("instructionManager", instructionManager)
|
|
|
|
|
|
self.ui.quickDebug.rootContext().setContextProperty("deviceManager", deviceManager)
|
|
|
|
|
|
self.ui.quickDebug.rootContext().setContextProperty("taskGroupManager", taskGroupManager)
|
|
|
|
|
|
self.ui.quickDebug.rootContext().setContextProperty("taskManager", taskManager)
|
|
|
|
|
|
self.ui.quickDebug.rootContext().setContextProperty("interfaceManager", interfaceManager)
|
|
|
|
|
|
self.ui.quickDebug.rootContext().setContextProperty("common", common)
|
|
|
|
|
|
self.ui.quickDebug.setSource(QUrl(common.firstPath()+"/debug/gviewer/main.qml"))
|
|
|
|
|
|
|
|
|
|
|
|
def clearContextProperties(self):
|
|
|
|
|
|
# 清除QML引擎缓存
|
|
|
|
|
|
self.ui.quickSetting.engine().clearComponentCache()
|
|
|
|
|
|
self.ui.quickStackView.engine().clearComponentCache()
|
|
|
|
|
|
# self.ui.quickSetting.rootContext().setContextProperty("common", None)
|
|
|
|
|
|
# self.ui.quickStackView.rootContext().setContextProperty("projectManager", None)
|
|
|
|
|
|
# self.ui.quickStackView.rootContext().setContextProperty("taskActuatorManager", None)
|
|
|
|
|
|
# self.ui.quickStackView.rootContext().setContextProperty("instructionManager", None)
|
|
|
|
|
|
# self.ui.quickStackView.rootContext().setContextProperty("deviceManager", None)
|
|
|
|
|
|
# self.ui.quickStackView.rootContext().setContextProperty("interfaceManager", None)
|
|
|
|
|
|
# self.ui.quickStackView.rootContext().setContextProperty("common", None)
|
|
|
|
|
|
# self.ui.quickTaskbar.rootContext().setContextProperty("common", None)
|
|
|
|
|
|
# self.ui.quickSetting.rootContext().setContextProperty("interfaceManager", None)
|
|
|
|
|
|
# self.ui.quickSetting.rootContext().setContextProperty("influxdbManager", None)
|
|
|
|
|
|
|
|
|
|
|
|
# self.ui.quickTaskbar.setSource(QUrl(""))
|
|
|
|
|
|
# self.ui.quickStackView.setSource(QUrl(""))
|
|
|
|
|
|
# self.ui.quickSetting.setSource(QUrl(""))
|
|
|
|
|
|
|
|
|
|
|
|
# if self.isDebugQML:
|
|
|
|
|
|
# self.ui.quickDebug.rootContext().setContextProperty("projectManager", None)
|
|
|
|
|
|
# self.ui.quickDebug.rootContext().setContextProperty("taskActuatorManager", None)
|
|
|
|
|
|
# self.ui.quickDebug.rootContext().setContextProperty("instructionManager", None)
|
|
|
|
|
|
# self.ui.quickDebug.rootContext().setContextProperty("deviceManager", None)
|
|
|
|
|
|
# self.ui.quickDebug.rootContext().setContextProperty("interfaceManager", None)
|
|
|
|
|
|
# self.ui.quickDebug.rootContext().setContextProperty("common", None)
|
|
|
|
|
|
# self.ui.quickDebug.setSource(QUrl(""))
|
|
|
|
|
|
|
|
|
|
|
|
#连接按钮信号
|
|
|
|
|
|
def connectBtnHandle(self):
|
|
|
|
|
|
self.ui.tbModel.clicked.connect(self.showDevModelForm)
|
|
|
|
|
|
self.ui.tbDev.clicked.connect(self.showDeviceForm)
|
|
|
|
|
|
self.ui.tbTask.clicked.connect(self.showTaskForm)
|
|
|
|
|
|
self.ui.tbDataSync.clicked.connect(self.showDataSyncForm)
|
|
|
|
|
|
self.ui.tbAppStore.clicked.connect(self.showAppStore)
|
|
|
|
|
|
self.ui.tbProject.clicked.connect(self.showProject)
|
|
|
|
|
|
self.ui.tbUser.clicked.connect(self.showUser)
|
|
|
|
|
|
self.ui.tbSetting.clicked.connect(self.showSetting)
|
|
|
|
|
|
self.loginForm.loginSuccess.connect(self.login)
|
|
|
|
|
|
self.loginForm.loginClose.connect(self.loginClose)
|
|
|
|
|
|
self.ui.tbDebug.clicked.connect(self.showDebug)
|
|
|
|
|
|
projectManager.sig_projectChanged.connect(self.changeProject)
|
|
|
|
|
|
common.sig_changeQml.connect(self.onChangeQml)
|
|
|
|
|
|
self.hide_button.clicked.connect(self.showHide)
|
|
|
|
|
|
self.ui.tbLog.clicked.connect(self.logControl )
|
|
|
|
|
|
self.ui.tbTaskList.clicked.connect(self.showTaskListForm)
|
|
|
|
|
|
self.ui.tblogOut.clicked.connect(self.logOut)
|
|
|
|
|
|
self.ui.pbClose.clicked.connect(self.closeWind)
|
|
|
|
|
|
self.ui.pbMin.clicked.connect(self.showMin)
|
|
|
|
|
|
self.ui.pbMax.clicked.connect(self.showMax)
|
|
|
|
|
|
self.ui.pbRestore.clicked.connect(self.showNormal)
|
|
|
|
|
|
interfaceManager.connectFailed.connect(self.connectFailed)
|
|
|
|
|
|
|
|
|
|
|
|
def showNormal(self):
|
|
|
|
|
|
self.setWindowState(Qt.WindowState.WindowNoState)
|
|
|
|
|
|
self.ui.pbMax.setVisible(True)
|
|
|
|
|
|
self.ui.pbRestore.setVisible(False)
|
|
|
|
|
|
|
|
|
|
|
|
def showMin(self):
|
|
|
|
|
|
self.showMinimized()
|
|
|
|
|
|
|
|
|
|
|
|
def showMax(self):
|
|
|
|
|
|
self.setWindowState(Qt.WindowState.WindowMaximized)
|
|
|
|
|
|
self.ui.pbMax.setVisible(False)
|
|
|
|
|
|
self.ui.pbRestore.setVisible(True)
|
|
|
|
|
|
|
|
|
|
|
|
def closeWind(self):
|
|
|
|
|
|
self.dataSyncForm.cleanup()
|
|
|
|
|
|
self.close()
|
|
|
|
|
|
|
|
|
|
|
|
def loginClose(self):
|
|
|
|
|
|
self.windowClose.emit()
|
|
|
|
|
|
self._exit()
|
|
|
|
|
|
|
|
|
|
|
|
def onChangeQml(self, qml):
|
|
|
|
|
|
self.ui.stackedWidget.setCurrentIndex(4)
|
|
|
|
|
|
self.ui.tbDefault.setChecked(True)
|
|
|
|
|
|
|
|
|
|
|
|
def showDebug(self):
|
|
|
|
|
|
self.ui.stackedWidget.setCurrentIndex(8)
|
|
|
|
|
|
self.setDebugQML()
|
|
|
|
|
|
common.sig_unChecked.emit()
|
|
|
|
|
|
|
|
|
|
|
|
def showDevModelForm(self):
|
|
|
|
|
|
self.ui.stackedWidget.setCurrentIndex(0)
|
|
|
|
|
|
self.devModelWidget.refreshSelect()
|
|
|
|
|
|
common.sig_unChecked.emit()
|
|
|
|
|
|
|
|
|
|
|
|
def showDeviceForm(self):
|
|
|
|
|
|
self.ui.stackedWidget.setCurrentIndex(1)
|
|
|
|
|
|
self.deviceWidget.refreshSelect()
|
|
|
|
|
|
common.sig_unChecked.emit()
|
|
|
|
|
|
|
|
|
|
|
|
def showTaskForm(self):
|
|
|
|
|
|
self.ui.stackedWidget.setCurrentIndex(2)
|
|
|
|
|
|
self.taskWidget.refreshSelect()
|
|
|
|
|
|
common.sig_unChecked.emit()
|
|
|
|
|
|
|
|
|
|
|
|
def showDataSyncForm(self):
|
|
|
|
|
|
self.ui.stackedWidget.setCurrentIndex(3)
|
|
|
|
|
|
common.sig_unChecked.emit()
|
|
|
|
|
|
def showAppStore(self):
|
|
|
|
|
|
common.sig_changeMainQml.emit("./AppStore.qml")
|
|
|
|
|
|
self.ui.stackedWidget.setCurrentIndex(4)
|
|
|
|
|
|
common.sig_unChecked.emit()
|
|
|
|
|
|
|
|
|
|
|
|
def showSetting(self):
|
|
|
|
|
|
self.ui.stackedWidget.setCurrentIndex(5)
|
|
|
|
|
|
common.sig_unChecked.emit()
|
|
|
|
|
|
|
|
|
|
|
|
def showProject(self):
|
|
|
|
|
|
self.ui.stackedWidget.setCurrentIndex(6)
|
|
|
|
|
|
self.projectForm.refreshSelect()
|
|
|
|
|
|
common.sig_unChecked.emit()
|
|
|
|
|
|
|
|
|
|
|
|
def showUser(self):
|
|
|
|
|
|
self.ui.stackedWidget.setCurrentIndex(7)
|
|
|
|
|
|
self.userWidget.refreshSelect()
|
|
|
|
|
|
common.sig_unChecked.emit()
|
|
|
|
|
|
|
|
|
|
|
|
# 创建菜单
|
|
|
|
|
|
def createMenu(self):
|
|
|
|
|
|
menu = QMenu(self)
|
|
|
|
|
|
# 创建菜单项
|
|
|
|
|
|
# action1 = QAction("系统设置", self)
|
|
|
|
|
|
action1 = QAction("切换用户", self)
|
|
|
|
|
|
action2 = QAction("帮助文档", self)
|
|
|
|
|
|
action3 = QAction("关于", self)
|
|
|
|
|
|
|
|
|
|
|
|
# 连接QAction的triggered信号到槽函数
|
|
|
|
|
|
# action1.triggered.connect(self.showSetting)
|
|
|
|
|
|
|
|
|
|
|
|
action3.triggered.connect(self.showAboutDialog)
|
|
|
|
|
|
# 将菜单项添加到菜单中
|
|
|
|
|
|
# menu.addAction(action1)
|
|
|
|
|
|
menu.addAction(action1)
|
|
|
|
|
|
menu.addAction(action2)
|
|
|
|
|
|
menu.addAction(action3)
|
|
|
|
|
|
# 设置工具按钮的触发事件(点击时显示菜单)
|
|
|
|
|
|
# lambda: menu.exec(self.ui.tbMore.mapToGlobal(QPoint(40, -30)))
|
|
|
|
|
|
self.ui.tbAbout.clicked.connect(self.showAboutDialog)
|
|
|
|
|
|
|
|
|
|
|
|
def logOut(self):
|
|
|
|
|
|
userManager.logOut()
|
|
|
|
|
|
self.hide()
|
|
|
|
|
|
self.loginForm.showNormal()
|
|
|
|
|
|
|
|
|
|
|
|
def changeProject(self, proId):
|
|
|
|
|
|
if proId == common.emputyProId:
|
|
|
|
|
|
self.ui.lbCurrentPro.setText("")
|
|
|
|
|
|
return
|
|
|
|
|
|
info = projectManager.getInfo(proId)
|
|
|
|
|
|
self.ui.lbCurrentPro.setText(info["name"])
|
|
|
|
|
|
|
|
|
|
|
|
def showHide(self):
|
|
|
|
|
|
self.ui.leftFrame.setVisible( not self.ui.leftFrame.isVisible())
|
|
|
|
|
|
if self.ui.leftFrame.isVisible():
|
|
|
|
|
|
self.hide_button.setGeometry(95, int((self.height() - 30) /2), 30, 30)
|
|
|
|
|
|
self.hide_button.setIcon(QIcon(":/resource/close.svg"))
|
|
|
|
|
|
else:
|
|
|
|
|
|
self.hide_button.setGeometry(0, int((self.height() - 30) /2), 30, 30)
|
|
|
|
|
|
self.hide_button.setIcon(QIcon(":/resource/open.svg"))
|
|
|
|
|
|
|
|
|
|
|
|
def connectFailed(self):
|
|
|
|
|
|
reply = QMessageBox.critical(None, "错误", "连接失败", QMessageBox.StandardButton.Ok)
|
|
|
|
|
|
|
|
|
|
|
|
def updateDateTime(self):
|
|
|
|
|
|
self.dogIndex = self.dogIndex + 1
|
|
|
|
|
|
if self.dogIndex >= 10:
|
|
|
|
|
|
self.dogIndex = 1
|
|
|
|
|
|
if dog.isDogAlive() != 1 :
|
|
|
|
|
|
if suDog.isDogAlive() != 1:
|
|
|
|
|
|
self.dogErrorIndex += 1
|
|
|
|
|
|
log.error("error index: %d" % self.dogErrorIndex)
|
|
|
|
|
|
else:
|
|
|
|
|
|
self.dogErrorIndex = 0
|
|
|
|
|
|
else:
|
|
|
|
|
|
self.dogErrorIndex = 0
|
|
|
|
|
|
if self.dogErrorIndex >= 3:
|
|
|
|
|
|
self.timer.stop()
|
|
|
|
|
|
reply = QMessageBox.critical(None, "Error", "请插入加密狗", QMessageBox.StandardButton.Ok)
|
|
|
|
|
|
if reply == QMessageBox.StandardButton.Ok:
|
|
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
self.ui.lbDateTime.setText(QDateTime.currentDateTime().toString("yyyy-MM-dd HH:mm:ss") )
|
|
|
|
|
|
|
|
|
|
|
|
def login(self):
|
|
|
|
|
|
loginData = userManager.getCurrentUser()
|
|
|
|
|
|
if "name" not in loginData:
|
|
|
|
|
|
return
|
|
|
|
|
|
self.ui.lbCurrentUserName.setText(loginData["name"])
|
|
|
|
|
|
|
|
|
|
|
|
if "role" in loginData:
|
|
|
|
|
|
self.setRoleEnable(loginData["role"])
|
|
|
|
|
|
else:
|
|
|
|
|
|
self.setRoleEnable(1)
|
|
|
|
|
|
self.showMaximized()
|
|
|
|
|
|
|
|
|
|
|
|
#DEBUG
|
|
|
|
|
|
if self.isDebugQML:
|
|
|
|
|
|
self.ui.stackedWidget.setCurrentIndex(8)
|
|
|
|
|
|
|
|
|
|
|
|
def setRoleEnable(self, role):
|
|
|
|
|
|
if role == 0:
|
|
|
|
|
|
self.ui.tbModel.setVisible(True)
|
|
|
|
|
|
self.ui.tbAppStore.setVisible(True)
|
|
|
|
|
|
self.ui.tbUser.setVisible(True)
|
|
|
|
|
|
self.ui.tbDev.setVisible(True)
|
|
|
|
|
|
self.ui.tbTask.setVisible(True)
|
|
|
|
|
|
self.ui.tbDataSync.setVisible(True)
|
|
|
|
|
|
self.ui.tbProject.setVisible(True)
|
|
|
|
|
|
self.ui.tbAbout.setVisible(True)
|
|
|
|
|
|
self.ui.tbSetting.setVisible(True)
|
|
|
|
|
|
self.ui.tbModel.setChecked(True)
|
|
|
|
|
|
self.showDevModelForm()
|
|
|
|
|
|
elif role == 1:
|
|
|
|
|
|
self.ui.tbModel.setVisible(False)
|
|
|
|
|
|
self.ui.tbAppStore.setVisible(False)
|
|
|
|
|
|
self.ui.tbUser.setVisible(False)
|
|
|
|
|
|
self.ui.tbDev.setVisible(True)
|
|
|
|
|
|
self.ui.tbDev.setChecked(True)
|
|
|
|
|
|
self.showDeviceForm()
|
|
|
|
|
|
elif role == 2:
|
|
|
|
|
|
self.ui.tbModel.setVisible(False)
|
|
|
|
|
|
self.ui.tbAppStore.setVisible(False)
|
|
|
|
|
|
self.ui.tbUser.setVisible(False)
|
|
|
|
|
|
self.ui.tbDev.setVisible(False)
|
|
|
|
|
|
self.ui.tbTask.setVisible(False)
|
|
|
|
|
|
self.ui.tbDataSync.setVisible(False)
|
|
|
|
|
|
self.ui.tbProject.setChecked(False)
|
|
|
|
|
|
self.showProject()
|
|
|
|
|
|
|
2026-04-17 15:31:41 +08:00
|
|
|
|
def onStopAllClicked(self):
|
|
|
|
|
|
"""结束所有任务按钮点击处理"""
|
|
|
|
|
|
# 立即禁用按钮,防止重复点击
|
|
|
|
|
|
self.ui.tbStopAll.setEnabled(False)
|
|
|
|
|
|
self.ui.tbStopAll.setToolTip("正在停止任务...")
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
# 执行停止
|
|
|
|
|
|
stopped_count = taskActuatorManager.stopAll()
|
|
|
|
|
|
|
|
|
|
|
|
# 显示反馈
|
|
|
|
|
|
if stopped_count > 0:
|
|
|
|
|
|
log.info(f"已停止 {stopped_count} 个运行中的任务")
|
|
|
|
|
|
else:
|
|
|
|
|
|
log.info("没有运行中的任务")
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
log.error(f"停止任务时出错: {e}")
|
|
|
|
|
|
finally:
|
|
|
|
|
|
# 恢复按钮(确保无论成功与否都恢复)
|
|
|
|
|
|
self.ui.tbStopAll.setEnabled(True)
|
|
|
|
|
|
self.ui.tbStopAll.setToolTip("结束所有任务")
|
|
|
|
|
|
|
|
|
|
|
|
def onStopAllRequested(self, requesterTaskId=None):
|
|
|
|
|
|
"""处理脚本请求的 stopAll(由主程序执行)"""
|
|
|
|
|
|
print(f"[DEBUG] 收到 stopAll 请求,请求者任务ID: {requesterTaskId}")
|
|
|
|
|
|
log.info(f"收到 stopAll 请求,请求者任务ID: {requesterTaskId}")
|
|
|
|
|
|
try:
|
|
|
|
|
|
print(f"[DEBUG] 当前任务字典: {list(taskActuatorManager.taskActuatorDict.keys())}")
|
|
|
|
|
|
stopped_count = taskActuatorManager.stopAll(excludeTaskId=requesterTaskId)
|
|
|
|
|
|
print(f"[DEBUG] 已停止 {stopped_count} 个其他任务")
|
|
|
|
|
|
log.info(f"已停止 {stopped_count} 个其他任务")
|
|
|
|
|
|
# 最后停止请求者自身
|
|
|
|
|
|
if requesterTaskId:
|
|
|
|
|
|
print(f"[DEBUG] 停止请求者任务 {requesterTaskId}")
|
|
|
|
|
|
taskActuatorManager.stop(requesterTaskId)
|
|
|
|
|
|
print(f"[DEBUG] 已停止请求者任务 {requesterTaskId}")
|
|
|
|
|
|
log.info(f"已停止请求者任务 {requesterTaskId}")
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
print(f"[DEBUG] 处理 stopAll 请求时出错: {e}")
|
|
|
|
|
|
log.error(f"处理 stopAll 请求时出错: {e}")
|
|
|
|
|
|
import traceback
|
|
|
|
|
|
traceback.print_exc()
|
|
|
|
|
|
|
2026-03-02 14:29:58 +08:00
|
|
|
|
def showTaskListForm(self):
|
|
|
|
|
|
if self.taskListForm.isVisible():
|
|
|
|
|
|
self.taskListForm.setVisible(False)
|
|
|
|
|
|
return
|
|
|
|
|
|
self.taskListForm.setVisible(True)
|
|
|
|
|
|
|
|
|
|
|
|
def alertDialog(self, msg, title = ""):
|
|
|
|
|
|
msgBox = QMessageBox()
|
|
|
|
|
|
reply = msgBox.question(self, title, f"{msg}",
|
|
|
|
|
|
QMessageBox.StandardButton.Yes )
|
|
|
|
|
|
return reply == QMessageBox.StandardButton.Yes
|
|
|
|
|
|
|
|
|
|
|
|
def removeDialog(self, msg, title = "删除指令"):
|
|
|
|
|
|
msgBox = QMessageBox()
|
|
|
|
|
|
reply = msgBox.question(self, title, f"是否删除 {msg}?",
|
|
|
|
|
|
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, QMessageBox.StandardButton.No)
|
|
|
|
|
|
return reply == QMessageBox.StandardButton.Yes
|
|
|
|
|
|
|
|
|
|
|
|
def askDialog(self, msg, title = ""):
|
|
|
|
|
|
msgBox = QMessageBox()
|
|
|
|
|
|
reply = msgBox.question(self, title, msg,
|
|
|
|
|
|
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, QMessageBox.StandardButton.No)
|
|
|
|
|
|
return reply == QMessageBox.StandardButton.Yes
|
|
|
|
|
|
#关于
|
|
|
|
|
|
def showAboutDialog(self):
|
|
|
|
|
|
QMessageBox.about(self, "关于", f"{app_version.data['name']} "+"\n\n版本号: "+app_version.data["version"]+"\n\nID: "+app_version.data["proId"]+"\n\n发布时间: "+app_version.data["releaseTime"])
|
|
|
|
|
|
|
|
|
|
|
|
#日志开关
|
|
|
|
|
|
def logControl(self):
|
|
|
|
|
|
self.ui.logWidget.setVisible(not self.ui.logWidget.isVisible())
|
|
|
|
|
|
|
|
|
|
|
|
def setConfig(self):
|
|
|
|
|
|
log.setConfig(config.data["log"])
|
|
|
|
|
|
grafana.setConfig(config.data["grafana"])
|
|
|
|
|
|
|
|
|
|
|
|
def _run(self):
|
|
|
|
|
|
# influxdb.run()
|
|
|
|
|
|
grafana.run()
|
|
|
|
|
|
|
|
|
|
|
|
def _exit(self):
|
|
|
|
|
|
influxdb.close()
|
|
|
|
|
|
grafana.close()
|