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) self.ui.tbStopAll.clicked.connect(taskActuatorManager.stopAll) 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() # screenGeometry = QApplication.primaryScreen().geometry() # print((screenGeometry.width(),screenGeometry.height(),mainWinHeight,taskListFormHeight,int(screenGeometry.height() - mainWinHeight - taskListFormHeight))) 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() 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()