|
|
|
|
|
|
|
|
import typing
|
|
|
import sys
|
|
|
|
|
|
import qtawesome
|
|
|
from PyQt5 import QtGui,QtCore,QtWidgets
|
|
|
from PyQt5.QtCore import QAbstractTableModel, QModelIndex, Qt, QVariant, QSize
|
|
|
|
|
|
from PyQt5.QtWidgets import QItemDelegate, QHBoxLayout, QWidget, QMessageBox, QComboBox
|
|
|
from UI.VarManages.BaseButtonDelegate import BaseButtonDelegate
|
|
|
|
|
|
|
|
|
|
|
|
# 移除 Celery 相关导入,现在使用 ProtocolManage 和 ModbusManager
|
|
|
from ..TrendManage.ActualTrendWidget import ActualTrend
|
|
|
|
|
|
from model.ProjectModel.VarManage import *
|
|
|
|
|
|
from utils import Globals
|
|
|
import re
|
|
|
|
|
|
|
|
|
sys.path.append('protocol/Celery/MBTCPMaster')
|
|
|
|
|
|
class QPushButton(QtWidgets.QPushButton):
|
|
|
def __init__(self, *__args: any,clicked = None):
|
|
|
super(QPushButton,self).__init__(*__args)
|
|
|
self.setCursor(Qt.PointingHandCursor)
|
|
|
self.setIconSize(QSize(25, 25))
|
|
|
|
|
|
class VarTableModel(QAbstractTableModel):
|
|
|
''' 变量表模型类'''
|
|
|
def __init__(self, header, data: list, modbusType = None, table = None):
|
|
|
'''
|
|
|
header : 表头变量
|
|
|
data : 表格内容
|
|
|
table : 缺省参数
|
|
|
'''
|
|
|
QAbstractTableModel.__init__(self, parent=None)
|
|
|
self.header = header
|
|
|
self.datas = data
|
|
|
self.checkList = ['Unchecked'] * len(self.datas)
|
|
|
self.supportedDragActions()
|
|
|
self.table = table
|
|
|
self.editableList = [] # 表格中可编辑项
|
|
|
self.modbusType = modbusType
|
|
|
def initTable(self, initVar = None):
|
|
|
self.datas = []
|
|
|
self.editableList = []
|
|
|
if self.table:
|
|
|
self.table.parent.initIcon()
|
|
|
varDatas = ModbusVarManage.getAllVar(self.modbusType)
|
|
|
|
|
|
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)
|
|
|
self.checkList = ['Unchecked'] * len(self.datas)
|
|
|
# self.layoutChanged.emit()
|
|
|
self.table.proxy.invalidate()
|
|
|
# self.refreshComboBox(10)
|
|
|
|
|
|
|
|
|
def append_data(self, x):
|
|
|
|
|
|
self.datas.append(x)
|
|
|
self.checkList = ['Unchecked'] * len(self.datas)
|
|
|
self.table.proxy.invalidate()
|
|
|
# self.layoutChanged.emit()
|
|
|
|
|
|
def insert_data(self, x, index):
|
|
|
self.datas.insert(index, x)
|
|
|
self.checkList = ['Unchecked'] * len(self.datas)
|
|
|
self.table.proxy.invalidate()
|
|
|
|
|
|
def remove_row(self, row):
|
|
|
self.datas.pop(row)
|
|
|
self.checkList = ['UnChecked'] * len(self.datas)
|
|
|
self.table.proxy.invalidate()
|
|
|
|
|
|
def rowCount(self, parent: QModelIndex = ...) -> int:
|
|
|
if len(self.datas) > 0:
|
|
|
return len(self.datas)
|
|
|
return 0
|
|
|
|
|
|
def columnCount(self, parent: QModelIndex = ...) -> int:
|
|
|
return len(self.header)
|
|
|
|
|
|
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 self.datas[QModelIndex.row()][3] in Globals.getValue('forceVars'):
|
|
|
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]
|
|
|
if varName != '':
|
|
|
try:
|
|
|
protocolManage = Globals.getValue('protocolManage')
|
|
|
if protocolManage:
|
|
|
result = protocolManage.readVariableValue(varName)
|
|
|
if result is not None:
|
|
|
self.datas[QModelIndex.row()][QModelIndex.column()] = result
|
|
|
except Exception as e:
|
|
|
pass
|
|
|
return QVariant(self.datas[QModelIndex.row()][QModelIndex.column()])
|
|
|
|
|
|
def headerData(self, section: int, orientation: Qt.Orientation, role: int = ...) -> typing.Any: # 表头
|
|
|
if role != Qt.DisplayRole:
|
|
|
return None
|
|
|
|
|
|
if orientation == Qt.Horizontal:
|
|
|
return self.header[section]
|
|
|
|
|
|
def setData(self, index, value, role):
|
|
|
row = index.row()
|
|
|
col = index.column()
|
|
|
if role == Qt.CheckStateRole and col == 0:
|
|
|
self.checkList[row] = 'Checked' if value == Qt.Checked else 'Unchecked'
|
|
|
return True
|
|
|
if role == Qt.EditRole:
|
|
|
self.datas[row][col] = value
|
|
|
return True
|
|
|
return True
|
|
|
|
|
|
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:
|
|
|
return Qt.ItemIsEnabled | Qt.ItemIsUserCheckable | Qt.ItemIsEditable
|
|
|
return Qt.ItemIsEnabled
|
|
|
|
|
|
def headerClick(self, isOn):
|
|
|
self.beginResetModel()
|
|
|
if isOn:
|
|
|
self.checkList = []
|
|
|
self.checkList = ['Checked'] * len(self.datas)
|
|
|
else:
|
|
|
self.checkList = []
|
|
|
self.checkList = ['UnChecked'] * len(self.datas)
|
|
|
self.endResetModel()
|
|
|
|
|
|
def dragMoveEvent(self, event):
|
|
|
event.setDropAction(QtCore.Qt.MoveAction)
|
|
|
event.accept()
|
|
|
|
|
|
def moveRow(self, sourceParent: QModelIndex, sourceRow: int, destinationParent: QModelIndex,
|
|
|
destinationChild: int) -> bool:
|
|
|
if self.datas[destinationChild] == self.datas[sourceRow]:
|
|
|
return
|
|
|
self.datas[sourceRow], self.datas[destinationChild] = self.datas[destinationChild], self.datas[sourceRow]
|
|
|
self.table.proxy.invalidate()
|
|
|
|
|
|
def refreshComboBox(self, comboBoxColumn):
|
|
|
#功能类型的index是5,通讯类型index是10
|
|
|
|
|
|
for i in range(len(self.datas)):
|
|
|
cbRow = str('cb' + str(i) + str(comboBoxColumn))
|
|
|
index = self.index(i, int(comboBoxColumn))
|
|
|
delegate = self.table.itemDelegate(index)
|
|
|
|
|
|
# 方法1:尝试通过indexWidget获取已存在的comboBox
|
|
|
widget = self.table.indexWidget(index)
|
|
|
if widget is not None:
|
|
|
# 从容器widget中获取comboBox
|
|
|
comboBox = widget.findChild(QComboBox)
|
|
|
else:
|
|
|
# 方法2:尝试通过getattr获取委托中的comboBox
|
|
|
try:
|
|
|
comboBox = getattr(delegate, cbRow, None)
|
|
|
except AttributeError:
|
|
|
# 如果属性不存在,跳过这一行
|
|
|
continue
|
|
|
|
|
|
if comboBox is None:
|
|
|
# 如果comboBox不存在,跳过这一行
|
|
|
continue
|
|
|
|
|
|
# 检查comboBox对象是否仍然有效,避免RuntimeError
|
|
|
if not comboBox or comboBox.isHidden():
|
|
|
continue
|
|
|
|
|
|
|
|
|
# 根据数据类型设置comboBox的值
|
|
|
comboBox.setCurrentText(str(self.datas[i][comboBoxColumn]))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ModbusButtonDelegate(BaseButtonDelegate):
|
|
|
"""该类用于向单元格中添加按钮 任务表格"""
|
|
|
trendWidgetDict = {}
|
|
|
|
|
|
def __init__(self, parent=None):
|
|
|
super(ModbusButtonDelegate, self).__init__(parent)
|
|
|
|
|
|
def trendWidget(self, varName):
|
|
|
if varName not in self.trendWidgetDict:
|
|
|
trendWidget = ActualTrend(varName = varName)
|
|
|
self.trendWidgetDict[varName] = trendWidget
|
|
|
return self.trendWidgetDict[varName]
|
|
|
|
|
|
def paint(self, painter, option, index):
|
|
|
# 首先绘制背景颜色,与其他委托保持一致
|
|
|
if index.data(Qt.BackgroundRole):
|
|
|
height = option.rect.height()
|
|
|
top = option.rect.top()
|
|
|
paint_rect = option.rect
|
|
|
paint_rect.setHeight(max(46, height - 4))
|
|
|
paint_rect.moveTop(top + 2)
|
|
|
painter.fillRect(paint_rect, index.data(Qt.BackgroundRole))
|
|
|
|
|
|
if not self.parent().indexWidget(index):
|
|
|
button1 = QPushButton()
|
|
|
button1.setIcon(qtawesome.icon('fa.play', color='#1fbb6f'))
|
|
|
button1.setToolTip("启动强制")
|
|
|
|
|
|
button2 = QPushButton()
|
|
|
button2.setIcon(qtawesome.icon('fa.pencil', color='#4c8cf2'))
|
|
|
button2.setToolTip("编辑变量")
|
|
|
|
|
|
button3 = QPushButton()
|
|
|
button3.setIcon(qtawesome.icon('fa.trash', color='#ff6d6d'))
|
|
|
button3.setToolTip("删除变量")
|
|
|
|
|
|
button4 = QPushButton()
|
|
|
button4.setIcon(qtawesome.icon('fa.line-chart', color='#393c4e'))
|
|
|
button4.setToolTip("趋势图")
|
|
|
|
|
|
comboBox = QComboBox(self.parent())
|
|
|
comboBox.addItem('int', 0)
|
|
|
comboBox.addItem('ABCD', 1)
|
|
|
comboBox.addItem('CDAB', 2)
|
|
|
comboBox.addItem('BADC', 3)
|
|
|
comboBox.addItem('DCBA', 4)
|
|
|
comboBox.setCurrentText(str(self.parent().model.datas[index.row()][index.column()]))
|
|
|
comboBox.setToolTip("字节序")
|
|
|
|
|
|
comboBox.currentIndexChanged.connect(self.indexChange)
|
|
|
button1.clicked.connect(self.start_action)
|
|
|
button2.clicked.connect(self.edit_action)
|
|
|
button3.clicked.connect(self.delete_action)
|
|
|
button4.clicked.connect(self.trend_action)
|
|
|
|
|
|
button2.oldName = False
|
|
|
button2.isEdit = True
|
|
|
button3.editButton = button2
|
|
|
|
|
|
button1.index = [index.row(), index.column()]
|
|
|
button2.index = [index.row(), index.column()]
|
|
|
button3.index = [index.row(), index.column()]
|
|
|
button4.index = [index.row(), index.column()]
|
|
|
comboBox.index = [index.row(), index.column()]
|
|
|
|
|
|
data = self.parent().model.datas[index.row()]
|
|
|
for x in data[:-3]:
|
|
|
if x != '':
|
|
|
break
|
|
|
else:
|
|
|
button2.isEdit = False
|
|
|
button2.setIcon(qtawesome.icon('fa.save', color='#1fbb6f'))
|
|
|
button2.setToolTip("保存变量")
|
|
|
self.parent().model.editableList.append(button2.index[0])
|
|
|
|
|
|
hboxLayout = QHBoxLayout()
|
|
|
hboxLayout.addWidget(comboBox)
|
|
|
hboxLayout.addWidget(button1)
|
|
|
hboxLayout.addWidget(button2)
|
|
|
hboxLayout.addWidget(button3)
|
|
|
hboxLayout.addWidget(button4)
|
|
|
hboxLayout.setContentsMargins(2, 2, 2, 2)
|
|
|
hboxLayout.setAlignment(Qt.AlignCenter)
|
|
|
hboxLayout.setSpacing(3)
|
|
|
|
|
|
widget = QWidget()
|
|
|
widget.setLayout(hboxLayout)
|
|
|
widget.setStyleSheet("QComboBox { background-color: transparent; }")
|
|
|
# 所有下拉框使用统一样式
|
|
|
widget.setObjectName('ModbusButtonWidget')
|
|
|
comboBox.setObjectName('ModbusOrderBox')
|
|
|
|
|
|
self.parent().setIndexWidget(index, widget)
|
|
|
|
|
|
def indexChange(self):
|
|
|
sender = self.sender()
|
|
|
modbusType = self.parent().modbusType
|
|
|
index = sender.currentIndex()
|
|
|
text = sender.itemText(index)
|
|
|
name = self.parent().model.datas[sender.index[0]][3]
|
|
|
ModbusVarManage.editOrder(name, text, modbusType)
|
|
|
self.parent().model.datas[sender.index[0]][sender.index[1]] = text
|
|
|
|
|
|
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 = str(self._get_view_data(view_row, 1)) # 强制值列
|
|
|
varMes = model.datas[source_row]
|
|
|
name, des, varType, slaveID, address, min, max, order = str(varMes[3]), str(varMes[4]), str(varMes[5]), str(varMes[6]), str(varMes[7]), str(varMes[8]), str(varMes[9]), str(varMes[10])
|
|
|
pattern = re.compile(r'[^0-9\.-]+')
|
|
|
if not value or re.findall(pattern, str(value)):
|
|
|
reply = QMessageBox.question(self.parent(),
|
|
|
'警告',
|
|
|
"请输入强制值或数字",
|
|
|
QMessageBox.Yes)
|
|
|
return
|
|
|
|
|
|
|
|
|
if min and max:
|
|
|
if float(value) < float(min) or float(value) > float(max):
|
|
|
reply = QMessageBox.question(self.parent(),
|
|
|
'警告',
|
|
|
"超出量程范围",
|
|
|
QMessageBox.Yes)
|
|
|
return
|
|
|
elif min and not max:
|
|
|
if float(value) < float(min):
|
|
|
reply = QMessageBox.question(self.parent(),
|
|
|
'警告',
|
|
|
"超出量程范围",
|
|
|
QMessageBox.Yes)
|
|
|
return
|
|
|
elif max and not min:
|
|
|
if float(value) > float(max):
|
|
|
reply = QMessageBox.question(self.parent(),
|
|
|
'警告',
|
|
|
"超出量程范围",
|
|
|
QMessageBox.Yes)
|
|
|
return
|
|
|
|
|
|
# 使用新的 ProtocolManage 进行变量写入
|
|
|
protocolManage = Globals.getValue('protocolManage')
|
|
|
if protocolManage:
|
|
|
try:
|
|
|
result = protocolManage.writeVariableValue(name, value)
|
|
|
if result:
|
|
|
forceVars = Globals.getValue('forceVars')
|
|
|
if forceVars is None:
|
|
|
forceVars = set()
|
|
|
forceVars.add(name)
|
|
|
Globals.setValue('forceVars', forceVars)
|
|
|
else:
|
|
|
QMessageBox.warning(self.parent(), '错误', f'变量 {name} 写入失败', QMessageBox.Yes)
|
|
|
except Exception as e:
|
|
|
QMessageBox.warning(self.parent(), '错误', f'写入变量时发生错误: {str(e)}', QMessageBox.Yes)
|
|
|
else:
|
|
|
QMessageBox.warning(self.parent(), '错误', '协议管理器未初始化', QMessageBox.Yes)
|
|
|
|
|
|
def edit_action(self):
|
|
|
sender = self.sender()
|
|
|
model = self.parent().model
|
|
|
modbusType = self.parent().modbusType
|
|
|
pattern = re.compile(r'[^0-9\.-]+')
|
|
|
# 使用基类的验证方法获取行索引
|
|
|
view_row, source_row = self._validate_button_indices(sender)
|
|
|
if view_row is None:
|
|
|
return
|
|
|
|
|
|
fucationCbRow = str('cb' + str(source_row) + str(5))
|
|
|
fucationIndex = self.parent().model.index(source_row, 5)
|
|
|
fucationDelegate = self.parent().itemDelegate(fucationIndex)
|
|
|
fucationCheckbox = getattr(fucationDelegate, fucationCbRow)
|
|
|
|
|
|
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)
|
|
|
fucationCheckbox.setEnabled(True)
|
|
|
self.parent().viewport().update()
|
|
|
|
|
|
else:
|
|
|
varMes = model.datas[source_row]
|
|
|
name, des, varType, slaveID, address, min, max, varModel, order = str(varMes[3]), str(varMes[4]), str(varMes[5]), str(varMes[6]), str(varMes[7]), str(varMes[8]), str(varMes[9]), str(varMes[-2]), str(varMes[-1])
|
|
|
if varType == '':
|
|
|
varType = 0
|
|
|
|
|
|
if not name or not slaveID or not address:
|
|
|
reply = QMessageBox.question(self.parent(),
|
|
|
'警告',
|
|
|
"有字段为空或输入错误",
|
|
|
QMessageBox.Yes)
|
|
|
return
|
|
|
|
|
|
# 验证slaveID、address、min、max是否为有效数字
|
|
|
# 检查slaveID是否为有效数字
|
|
|
if slaveID and re.findall(pattern, slaveID):
|
|
|
reply = QMessageBox.question(self.parent(),
|
|
|
'警告',
|
|
|
"从站地址必须为数字",
|
|
|
QMessageBox.Yes)
|
|
|
return
|
|
|
|
|
|
# 检查address是否为有效数字
|
|
|
if address and re.findall(pattern, address):
|
|
|
reply = QMessageBox.question(self.parent(),
|
|
|
'警告',
|
|
|
"寄存器地址必须为数字",
|
|
|
QMessageBox.Yes)
|
|
|
return
|
|
|
|
|
|
# 检查min是否为有效数字(如果存在)
|
|
|
if min and re.findall(pattern, min):
|
|
|
reply = QMessageBox.question(self.parent(),
|
|
|
'警告',
|
|
|
"工程量下限必须为数字",
|
|
|
QMessageBox.Yes)
|
|
|
return
|
|
|
|
|
|
# 检查max是否为有效数字(如果存在)
|
|
|
if max and re.findall(pattern, max):
|
|
|
reply = QMessageBox.question(self.parent(),
|
|
|
'警告',
|
|
|
"工程量上限必须为数字",
|
|
|
QMessageBox.Yes)
|
|
|
return
|
|
|
|
|
|
|
|
|
if sender.oldName and ModbusVarManage.getByName(sender.oldName, modbusType):
|
|
|
if sender.oldName == name:
|
|
|
# 名称未改变,直接执行修改变量操作
|
|
|
ModbusVarManage.editVar(name=sender.oldName, Nname=name, des=des,
|
|
|
varType=varType, slaveID=slaveID, address=address,
|
|
|
min=min, max=max, order=order, modbusType=modbusType, varModel=varModel)
|
|
|
else:
|
|
|
# 名称改变,检查新名称是否已存在
|
|
|
if GlobalVarManager.isVarNameExist(name):
|
|
|
QMessageBox.information(self.parent(), '提示', '已有同名变量')
|
|
|
return
|
|
|
else:
|
|
|
# 执行修改变量操作
|
|
|
ModbusVarManage.editVar(name=sender.oldName, Nname=name, des=des,
|
|
|
varType=varType, slaveID=slaveID, address=address,
|
|
|
min=min, max=max, order=order, modbusType=modbusType, varModel=varModel)
|
|
|
|
|
|
else:
|
|
|
if GlobalVarManager.isVarNameExist(name):
|
|
|
QMessageBox.information(self.parent(), '提示', '已有同名变量')
|
|
|
return
|
|
|
else:
|
|
|
ModbusVarManage.createVar(varName = name, varType = varType, des = des,
|
|
|
address = address, slaveID = slaveID, min = min,
|
|
|
max = max, order = order, modbusType = modbusType, varModel= varModel)
|
|
|
|
|
|
|
|
|
sender.setIcon(qtawesome.icon('fa.pencil', color='#4c8cf2'))
|
|
|
varMes = ModbusVarManage.getByName(name, modbusType)
|
|
|
varMes.append('本地值')
|
|
|
varMes.append('int')
|
|
|
varMes.insert(1, '')
|
|
|
varMes.insert(2, '')
|
|
|
model.insert_data(varMes, source_row)
|
|
|
model.remove_row(source_row + 1)
|
|
|
|
|
|
sender.isEdit = True
|
|
|
fucationCheckbox.setEnabled(False)
|
|
|
# varModelCheckbox.setEnabled(False)
|
|
|
model.editableList.remove(source_row)
|
|
|
self.parent().viewport().update()
|
|
|
|
|
|
|
|
|
def delete_action(self):
|
|
|
sender = self.sender()
|
|
|
model = self.parent().model
|
|
|
|
|
|
# 使用基类的验证方法获取行索引
|
|
|
view_row, source_row = self._validate_button_indices(sender)
|
|
|
if view_row is None:
|
|
|
return
|
|
|
|
|
|
name = str(model.datas[source_row][3])
|
|
|
modbusType = self.parent().modbusType
|
|
|
if sender.editButton.isEdit:
|
|
|
ModbusVarManage.deleteVar(name = name, modbusType = modbusType)
|
|
|
model.remove_row(source_row)
|
|
|
|
|
|
def trend_action(self):
|
|
|
model = self.parent().model
|
|
|
if model.table.parent._isPopenOpen:
|
|
|
sender = self.sender()
|
|
|
|
|
|
# 使用基类的验证方法获取行索引
|
|
|
view_row, source_row = self._validate_button_indices(sender)
|
|
|
if view_row is None:
|
|
|
return
|
|
|
|
|
|
name = str(model.datas[source_row][3])
|
|
|
trend = self.trendWidget(varName = name)
|
|
|
trend.show()
|
|
|
|
|
|
class ModbusTypeBox(QItemDelegate):
|
|
|
def __init__(self, parent=None):
|
|
|
super(ModbusTypeBox, self).__init__(parent)
|
|
|
|
|
|
def paint(self, painter, option, index):
|
|
|
# 首先绘制背景颜色,与其他委托保持一致
|
|
|
if index.data(Qt.BackgroundRole):
|
|
|
height = option.rect.height()
|
|
|
top = option.rect.top()
|
|
|
paint_rect = option.rect
|
|
|
paint_rect.setHeight(max(46, height - 4))
|
|
|
paint_rect.moveTop(top + 2)
|
|
|
painter.fillRect(paint_rect, index.data(Qt.BackgroundRole))
|
|
|
|
|
|
if (index.column() == 5) and index.row() not in self.parent().model.editableList:
|
|
|
data = self.parent().model.datas[index.row()]
|
|
|
comBox = str('cb' + str(index.row()) + str(index.column()))
|
|
|
setattr(self, comBox, QComboBox())
|
|
|
comboBox = getattr(self, comBox)
|
|
|
items = ['Coil Status', 'Input Status', 'Input Register', 'Holding Register']
|
|
|
comboBox.addItems(items)
|
|
|
if self.parent().model.datas[index.row()][index.column()] in [0, 1]:
|
|
|
comboBox.setCurrentIndex(self.parent().model.datas[index.row()][index.column()])
|
|
|
elif self.parent().model.datas[index.row()][index.column()] in [3, 4]:
|
|
|
comboBox.setCurrentIndex(self.parent().model.datas[index.row()][index.column()] - 1)
|
|
|
else:
|
|
|
comboBox.setCurrentIndex(0)
|
|
|
|
|
|
comboBox.currentIndexChanged.connect(self.indexChange)
|
|
|
comboBox.setObjectName('ModbusTypeBox')
|
|
|
comboBox.setEditable(True)
|
|
|
comboBox.lineEdit().setAlignment(Qt.AlignCenter)
|
|
|
|
|
|
hboxLayout = QHBoxLayout()
|
|
|
hboxLayout.addWidget(comboBox)
|
|
|
hboxLayout.setContentsMargins(2, 2, 2, 2)
|
|
|
comboBox.index = [index.row(), index.column()]
|
|
|
|
|
|
# 所有下拉框使用统一样式
|
|
|
comboBox.setObjectName('ModbusTypeBox')
|
|
|
|
|
|
if str(data[index.column()]):
|
|
|
comboBox.setEnabled(False)
|
|
|
comboBox.setProperty('disabled', True)
|
|
|
else:
|
|
|
comboBox.setEnabled(True)
|
|
|
comboBox.setProperty('disabled', False)
|
|
|
|
|
|
widget = QWidget()
|
|
|
widget.setStyleSheet("QComboBox { background-color: transparent; }")
|
|
|
widget.setLayout(hboxLayout)
|
|
|
self.parent().setIndexWidget(index, widget)
|
|
|
self.parent().openPersistentEditor(index)
|
|
|
|
|
|
def indexChange(self):
|
|
|
sender = self.sender()
|
|
|
index = sender.currentIndex()
|
|
|
if index in [2, 3]:
|
|
|
index += 1
|
|
|
self.parent().model.datas[sender.index[0]][sender.index[1]] = index
|
|
|
|
|
|
|
|
|
class ModbusVarModelBox(QItemDelegate):
|
|
|
def __init__(self, parent=None, comBoxColumn = 10):
|
|
|
super(ModbusVarModelBox, self).__init__(parent)
|
|
|
self.comBoxColumn = comBoxColumn
|
|
|
|
|
|
def paint(self, painter, option, index):
|
|
|
# 首先绘制背景颜色,与其他委托保持一致
|
|
|
if index.data(Qt.BackgroundRole):
|
|
|
height = option.rect.height()
|
|
|
top = option.rect.top()
|
|
|
paint_rect = option.rect
|
|
|
paint_rect.setHeight(max(46, height - 4))
|
|
|
paint_rect.moveTop(top + 2)
|
|
|
painter.fillRect(paint_rect, index.data(Qt.BackgroundRole))
|
|
|
|
|
|
# 本地值、模拟值、远程值 对应 0, 1, 2
|
|
|
if (index.column() == self.comBoxColumn) and not self.parent().indexWidget(index):
|
|
|
data = self.parent().model.datas[index.row()]
|
|
|
comBox = str('cb' + str(index.row()) + str(index.column()))
|
|
|
setattr(self, comBox, QComboBox())
|
|
|
comboBox = getattr(self, comBox)
|
|
|
items = ['本地值', '模拟值', '远程值']
|
|
|
comboBox.addItems(items)
|
|
|
comboBox.setCurrentText(str(self.parent().model.datas[index.row()][index.column()]))
|
|
|
|
|
|
comboBox.currentIndexChanged.connect(self.indexChange)
|
|
|
comboBox.setObjectName('ModbusVarModelBox')
|
|
|
comboBox.setEditable(True)
|
|
|
comboBox.lineEdit().setAlignment(Qt.AlignCenter)
|
|
|
|
|
|
hboxLayout = QHBoxLayout()
|
|
|
hboxLayout.addWidget(comboBox)
|
|
|
hboxLayout.setContentsMargins(2, 2, 2, 2)
|
|
|
comboBox.index = [index.row(), index.column()]
|
|
|
widget = QWidget()
|
|
|
widget.setStyleSheet("QComboBox { background-color: transparent; }")
|
|
|
widget.setLayout(hboxLayout)
|
|
|
self.parent().setIndexWidget(index, widget)
|
|
|
self.parent().openPersistentEditor(index)
|
|
|
|
|
|
def indexChange(self):
|
|
|
sender = self.sender()
|
|
|
modbusType = self.parent().modbusType
|
|
|
index = sender.currentIndex()
|
|
|
text = sender.itemText(index)
|
|
|
name = self.parent().model.datas[sender.index[0]][3]
|
|
|
ModbusVarManage.editVarModel(name, text, modbusType)
|
|
|
self.parent().model.datas[sender.index[0]][sender.index[1]] = text
|
|
|
|
|
|
class HartVarModelBox(ModbusVarModelBox):
|
|
|
def __init__(self, parent=None, comBoxColumn = 8):
|
|
|
super(HartVarModelBox, self).__init__(parent)
|
|
|
self.comBoxColumn = comBoxColumn
|
|
|
def indexChange(self):
|
|
|
sender = self.sender()
|
|
|
index = sender.currentIndex()
|
|
|
text = sender.itemText(index)
|
|
|
name = self.parent().model.datas[sender.index[0]][1]
|
|
|
HartVarManage.editVarModel(name, text)
|
|
|
self.parent().model.datas[sender.index[0]][sender.index[1]] = text
|
|
|
|
|
|
class TcRtdVarModelBox(ModbusVarModelBox):
|
|
|
def __init__(self, parent=None, comBoxColumn = 11):
|
|
|
super(TcRtdVarModelBox, self).__init__(parent)
|
|
|
self.comBoxColumn = comBoxColumn
|
|
|
def indexChange(self):
|
|
|
sender = self.sender()
|
|
|
index = sender.currentIndex()
|
|
|
text = sender.itemText(index)
|
|
|
name = self.parent().model.datas[sender.index[0]][3]
|
|
|
TcRtdManage.editVarModel(name, text)
|
|
|
self.parent().model.datas[sender.index[0]][sender.index[1]] = text
|
|
|
|
|
|
|
|
|
class AnalogVarModelBox(ModbusVarModelBox):
|
|
|
def __init__(self, parent=None, comBoxColumn = 10):
|
|
|
super(AnalogVarModelBox, self).__init__(parent)
|
|
|
self.comBoxColumn = comBoxColumn
|
|
|
def indexChange(self):
|
|
|
sender = self.sender()
|
|
|
index = sender.currentIndex()
|
|
|
text = sender.itemText(index)
|
|
|
name = self.parent().model.datas[sender.index[0]][3]
|
|
|
AnalogManage.editVarModel(name, text, )
|
|
|
self.parent().model.datas[sender.index[0]][sender.index[1]] = text
|
|
|
|
|
|
class HartSimulateVarModelBox(ModbusVarModelBox):
|
|
|
def __init__(self, parent=None, comBoxColumn = 9):
|
|
|
super(HartSimulateVarModelBox, self).__init__(parent)
|
|
|
self.comBoxColumn = comBoxColumn
|
|
|
|
|
|
|
|
|
def indexChange(self):
|
|
|
sender = self.sender()
|
|
|
index = sender.currentIndex()
|
|
|
text = sender.itemText(index)
|
|
|
name = self.parent().model.datas[sender.index[0]][1]
|
|
|
HartSimulateVarManage.editVarModel(name, text)
|
|
|
self.parent().model.datas[sender.index[0]][sender.index[1]] = text |