|
|
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)
|
|
|
|