import re import qtawesome from PyQt5 import QtGui from PyQt5.QtCore import Qt, QVariant, QTimer from PyQt5.QtWidgets import QMessageBox # from websocket import send from protocol.TCP.Analog import getRealAO from model.ProjectModel.VarManage import * from UI.VarManages.ModbusModel import * from UI.VarManages.TCRTDModel import * from utils import Globals class AnalogModel(VarTableModel): def __init__(self, header, data: list, table = None): ''' header : 表头变量 data : 表格内容 table : 缺省参数 ''' VarTableModel.__init__(self, header, data, table = table) # 修改为驼峰命名 self.valueCache = {} self.cacheTimer = QTimer() self.cacheTimer.timeout.connect(self.refreshValueCache) self.cacheTimer.start(300) # 每秒刷新一次缓存 # 方法名改为驼峰命名 def refreshValueCache(self): """刷新所有变量的值缓存""" for row in self.datas: varName = row[3] try: self.valueCache[varName] = Globals.getValue('protocolManage').readVariableValue(varName) except: self.valueCache[varName] = None def initTable(self): self.datas = [] proType = Globals.getValue('currentProType') # if proType in ['6']: varDatas = AnalogManage.getAllVar() if not varDatas: # self.layoutChanged.emit() self.table.proxy.invalidate() return for x in varDatas: x.insert(1, '') x.insert(2, '') self.datas.append(x) x.append('') self.checkList = ['Unchecked'] * len(self.datas) # self.layoutChanged.emit() self.table.proxy.invalidate() # 初始化后立即刷新缓存 self.refreshValueCache() def data(self, QModelIndex, role=None): # print(Qt.__dict__.items()) if role == Qt.TextAlignmentRole: return Qt.AlignCenter if not QModelIndex.isValid(): print("行或者列有问题") return QVariant() if role == Qt.BackgroundRole: # if QModelIndex.row() % 2 == 0 and self.datas[QModelIndex.row()][3] not in Globals.getValue('forceVars'): # return QtGui.QColor('#EFEFEF') if self.datas[QModelIndex.row()][3] in Globals.getValue('forceVars'): # print(111111) return QtGui.QColor('#00FF7F') if role == Qt.TextColorRole: return QtGui.QColor('#1A1A1A') if role == Qt.CheckStateRole: if QModelIndex.column() == 0: return Qt.Checked if self.checkList[QModelIndex.row()] == 'Checked' else Qt.Unchecked else: return None if role == Qt.ToolTipRole: if QModelIndex.column() == 0: return self.checkList[QModelIndex.row()] if role == Qt.DisplayRole or role == Qt.EditRole: if QModelIndex.row() in self.editableList: return self.datas[QModelIndex.row()][QModelIndex.column()] if role != Qt.DisplayRole: return QVariant() # # 获取变量值并插入表格 if QModelIndex.column() == 2: varName = self.datas[QModelIndex.row()][3] # 使用修改后的缓存变量名 return self.valueCache.get(varName, None) return QVariant(self.datas[QModelIndex.row()][QModelIndex.column()]) def flags(self, index): if index.column() == 0: return Qt.ItemIsEnabled | Qt.ItemIsUserCheckable if index.row() in self.editableList and index.column() or index.column() == 1: if index.column() == 6 or index.column() == 4: return Qt.ItemIsEnabled return Qt.ItemIsEnabled | Qt.ItemIsUserCheckable | Qt.ItemIsEditable return Qt.ItemIsEnabled class AnalogButtonDelegate(TcRtdButtonDelegate): """该类用于向单元格中添加按钮 任务表格""" def __init__(self, parent=None): super(AnalogButtonDelegate, self).__init__(parent) self.trendWindows = {} # 保存所有打开的趋势窗口 def trend_action(self): sender = self.sender() model = self.parent().model # 使用基类的验证方法获取行索引 view_row, source_row = self._validate_button_indices(sender) if view_row is None: return varName = model.datas[source_row][3] # 以变量名为key,避免重复打开 if varName not in self.trendWindows or self.trendWindows[varName] is None: self.trendWindows[varName] = ActualTrend(varName=varName) self.trendWindows[varName].show() self.trendWindows[varName].raise_() self.trendWindows[varName].activateWindow() def edit_action(self): sender = self.sender() model = self.parent().model # 使用基类的验证方法获取行索引 view_row, source_row = self._validate_button_indices(sender) if view_row is None: return if sender.isEdit: sender.setIcon(qtawesome.icon('fa.save', color='#1fbb6f')) sender.isEdit = False sender.oldName = model.datas[source_row][3] model.editableList.append(source_row) else: varMes = model.datas[source_row] name,channelNumber, des, varType, min, max, unit = str(varMes[3]), str(varMes[4]), str(varMes[5]),str(varMes[6]), str(varMes[7]), str(varMes[8]), str(varMes[9]) if not name or not varType: reply = QMessageBox.question(self.parent(), '警告', "有字段为空", QMessageBox.Yes) return sender.isEdit = True model.editableList.remove(source_row) if sender.oldName: if sender.oldName == name: AnalogManage.editVar(name=sender.oldName, Nname=name, channelNumber = channelNumber, des=des, varType=varType, min=min, max=max, unit=unit) else: if GlobalVarManager.isVarNameExist(name): QMessageBox.information(self.parent(), '提示', '已有同名变量') return else: AnalogManage.editVar(name=sender.oldName, Nname=name, channelNumber = channelNumber, des=des, varType=varType, min=min, max=max, unit=unit) else: if GlobalVarManager.isVarNameExist(name): QMessageBox.information(self.parent(), '提示', '已有同名变量') return else: AnalogManage.editVar(name=sender.oldName, Nname=name, channelNumber = channelNumber, des=des, varType=varType, min=min, max=max, unit=unit) sender.setIcon(qtawesome.icon('fa.pencil', color='#4c8cf2')) varMes = AnalogManage.getByName(name) varMes.insert(1, '') varMes.insert(2, '') varMes.append('') model.insert_data(varMes, source_row) model.remove_row(source_row + 1) def start_action(self): sender = self.sender() model = self.parent().model # 使用基类的验证方法获取行索引 view_row, source_row = self._validate_button_indices(sender) if view_row is None: return # 获取强制值(从视图)和其他数据(从源模型) value = self._get_view_data(view_row, 1) # 强制值列 varType = model.datas[source_row][6] min = model.datas[source_row][7] max = model.datas[source_row][8] # print(model.datas[source_row][9]) pattern = re.compile(r'[^0-9\.-]+') if varType in ['AI', 'DI'] and model.datas[source_row][9] != '模拟值': reply = QMessageBox.question(self.parent(), '警告', "AI,DI类型变量不允许强制值", QMessageBox.Yes) return if varType in ['DO'] and int(value) not in [0, 1]: reply = QMessageBox.question(self.parent(), '警告', "DO类型变量强制值只能为0或1", QMessageBox.Yes) return if not value or re.findall(pattern, str(value)): reply = QMessageBox.question(self.parent(), '警告', "请输入强制值或数字", QMessageBox.Yes) return if source_row > 15: if not value.isdigit: reply = QMessageBox.question(self.parent(), '警告', "请输入0或1", QMessageBox.Yes) return if min and max and source_row < 16: if float(value) < float(min) or float(value) > float(max): reply = QMessageBox.question(self.parent(), '警告', "超出量程范围", QMessageBox.Yes) return else: min = None max = None # print(value, source_row) if (float(value) > 20 or float(value)) < 4 and source_row < 8: reply = QMessageBox.question(self.parent(), '警告', "超出量程范围1", QMessageBox.Yes) return if float(value) > 10000 or float(value) < 0.1 and 8 < source_row < 16: reply = QMessageBox.question(self.parent(), '警告', "超出量程范围2", QMessageBox.Yes) return # if source_row < 8: # model.table.realList[source_row] = getRealAO(float(value), max, min) # model.table.valueList[source_row] = float(value) # else: # model.table.realList[source_row] = float(value) # model.table.valueList[source_row] = float(value) # print(model.datas[source_row][3]) res = Globals.getValue('protocolManage').writeVariableValue(model.datas[source_row][3], float(value)) if res: forceVars = Globals.getValue('forceVars') forceVars.add(model.datas[source_row][3]) Globals.setValue('forceVars', forceVars) else: QMessageBox.information(self.parent(), '提示', '写入失败', QMessageBox.Yes)