|
|
|
|
|
from PyQt5 import QtCore
|
|
|
from PyQt5.QtWidgets import QHeaderView, QStyle, QStyleOptionButton, QTableView, QAbstractItemView, QDesktopWidget
|
|
|
from PyQt5.QtCore import (pyqtSignal, Qt, QRect)
|
|
|
|
|
|
|
|
|
from PyQt5.QtWidgets import QTableView
|
|
|
|
|
|
from .ModbusModel import *
|
|
|
from .AnalogModel import *
|
|
|
from .HartModel import *
|
|
|
from .HartSimulateModel import *
|
|
|
from .TCRTDModel import *
|
|
|
from .RpcVarModel import RpcVarModel, RpcVarButtonDelegate
|
|
|
|
|
|
|
|
|
from model.ProjectModel.VarManage import *
|
|
|
from UI.VarManages.Thread import RTDTCThread, AnalogThread, HartSimulateThread
|
|
|
# from UI.ProjectManages.ProjectModel import BackgroundDelegate
|
|
|
|
|
|
from utils import Globals
|
|
|
|
|
|
class BackgroundDelegate(QtWidgets.QStyledItemDelegate):
|
|
|
def __init__(self, *args):
|
|
|
super(BackgroundDelegate, self).__init__(*args)
|
|
|
self.setObjectName('item')
|
|
|
|
|
|
def sizeHint(self, option, index):
|
|
|
"""设置项目的尺寸提示,确保足够的高度"""
|
|
|
size = super().sizeHint(option, index)
|
|
|
size.setHeight(max(46, size.height())) # 最小高度60px
|
|
|
return size
|
|
|
|
|
|
def paint(self, painter, option, index):
|
|
|
# 确保绘制区域有足够的高度
|
|
|
if index.data(QtCore.Qt.BackgroundRole):
|
|
|
height = option.rect.height()
|
|
|
top = option.rect.top()
|
|
|
# 减少高度调整,保持更多的绘制区域
|
|
|
option.rect.setHeight(max(46, height - 4)) # 最小保持56px高度
|
|
|
option.rect.moveTop(top + 2)
|
|
|
painter.fillRect(option.rect, index.data(QtCore.Qt.BackgroundRole))
|
|
|
super().paint(painter, option, index)
|
|
|
|
|
|
class CheckBoxHeader(QHeaderView):
|
|
|
checkClicked = pyqtSignal(bool)
|
|
|
sectionClicked = pyqtSignal(int)
|
|
|
|
|
|
_x_offset = 15
|
|
|
_y_offset = 15
|
|
|
_width = 25
|
|
|
_height = 25
|
|
|
|
|
|
def __init__(self, orientation=Qt.Horizontal, parent=None, changeY = None):
|
|
|
self.isOn = False
|
|
|
self.changeY = changeY
|
|
|
super(CheckBoxHeader, self).__init__(orientation, parent)
|
|
|
|
|
|
def paintSection(self, painter, rect, logicalIndex):
|
|
|
painter.save()
|
|
|
super(CheckBoxHeader, self).paintSection(painter, rect, logicalIndex)
|
|
|
painter.restore()
|
|
|
|
|
|
|
|
|
if self.changeY:
|
|
|
self._y_offset = int((rect.height()-self._width)/2.)
|
|
|
else:
|
|
|
self._y_offset = int((rect.height()-self._width)/2.)
|
|
|
|
|
|
if logicalIndex == 0:
|
|
|
option = QStyleOptionButton()
|
|
|
option.rect = QRect(rect.x() + self._x_offset, rect.y() + self._y_offset, self._width, self._height)
|
|
|
option.state = QStyle.State_Enabled | QStyle.State_Active
|
|
|
if self.isOn:
|
|
|
option.state |= QStyle.State_On
|
|
|
else:
|
|
|
option.state |= QStyle.State_Off
|
|
|
self.style().drawControl(QStyle.CE_CheckBox, option, painter)
|
|
|
|
|
|
def mousePressEvent(self, event):
|
|
|
index = self.logicalIndexAt(event.pos())
|
|
|
if 0 == index:
|
|
|
x = self.sectionPosition(index)
|
|
|
if x + self._x_offset < event.pos().x() < x + self._x_offset + self._width and self._y_offset < event.pos().y() < self._y_offset + self._height:
|
|
|
if self.isOn:
|
|
|
self.isOn = False
|
|
|
else:
|
|
|
self.isOn = True
|
|
|
self.checkClicked.emit(self.isOn)
|
|
|
self.update()
|
|
|
else:
|
|
|
self.sectionClicked.emit(index)
|
|
|
super(CheckBoxHeader, self).mousePressEvent(event)
|
|
|
|
|
|
|
|
|
class VarTableView(QTableView):
|
|
|
def __init__(self, modbusType, parent=None):
|
|
|
super(VarTableView, self).__init__(parent)
|
|
|
self.parent = parent
|
|
|
self.modbusType = modbusType
|
|
|
self.setHeader()
|
|
|
self.setupUi()
|
|
|
|
|
|
def setHeader(self):
|
|
|
self.delegate = BackgroundDelegate(self)
|
|
|
self.setItemDelegate(self.delegate)
|
|
|
self.setItemDelegateForColumn(11, ModbusButtonDelegate(self))
|
|
|
self.setItemDelegateForColumn(5, ModbusTypeBox(self))
|
|
|
self.setItemDelegateForColumn(10, ModbusVarModelBox(self))
|
|
|
self.model = VarTableModel([' ID', '强制值', '当前值', '变量名', '变量描述', '变量类型',
|
|
|
'从站地址', '寄存器地址', '工程量下限', '工程量上限', '值类型', '操作'],
|
|
|
[], modbusType = self.modbusType, table = self)
|
|
|
|
|
|
|
|
|
def setupUi(self):
|
|
|
self.setShowGrid(False)
|
|
|
# self.setAlternatingRowColors(True)
|
|
|
self.setSelectionBehavior(QAbstractItemView.SelectRows)
|
|
|
|
|
|
|
|
|
self.setModel(self.model)
|
|
|
self.header = CheckBoxHeader()
|
|
|
self.header.setStretchLastSection(True)
|
|
|
self.header.checkClicked.connect(self.model.headerClick)
|
|
|
self.setHorizontalHeader(self.header)
|
|
|
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
|
|
|
|
|
self.setupColumnWidths()
|
|
|
self.header.setObjectName('paramHeader')
|
|
|
|
|
|
|
|
|
self.header.setSectionResizeMode(0, QHeaderView.Fixed)
|
|
|
self.header.resizeSection(0, 70)
|
|
|
|
|
|
# 设置行高
|
|
|
self.verticalHeader().setDefaultSectionSize(50)
|
|
|
self.verticalHeader().setMinimumSectionSize(50)
|
|
|
|
|
|
self.verticalHeader().hide()
|
|
|
def setupColumnWidths(self):
|
|
|
|
|
|
self.setCustomColumnWidths([0.9, 0.9, 0.9, 1, 1, 1.4, 1, 1, 1, 1, 0.9, 1.3])
|
|
|
|
|
|
def setCustomColumnWidths(self, ratios):
|
|
|
# 计算总比例
|
|
|
totalRatio = sum(ratios)
|
|
|
# 获取窗口宽度
|
|
|
screen = QDesktopWidget().screenGeometry()
|
|
|
width = screen.width() - 300
|
|
|
|
|
|
# 根据比例设置每列的宽度
|
|
|
for i, ratio in enumerate(ratios):
|
|
|
columnWidth = int(width * (ratio / totalRatio))
|
|
|
self.setColumnWidth(i, columnWidth)
|
|
|
|
|
|
|
|
|
|
|
|
class HartTableView(VarTableView):
|
|
|
def __init__(self, parent=None):
|
|
|
super(HartTableView, self).__init__(parent)
|
|
|
|
|
|
def setHeader(self):
|
|
|
self.delegate = BackgroundDelegate(self)
|
|
|
self.setItemDelegate(self.delegate)
|
|
|
self.setItemDelegateForColumn(9, HartButtonDelegate(self))
|
|
|
self.setItemDelegateForColumn(8, HartVarModelBox(self))
|
|
|
self.model = HartModel([' ID', '仪器名', '描述', '电流值', '参数1', '参数2','参数3', '参数4', '值类型','操作'], [], table=self)
|
|
|
def setupColumnWidths(self):
|
|
|
self.header.setSectionResizeMode(QHeaderView.Stretch)
|
|
|
|
|
|
class TcRtdTableView(VarTableView):
|
|
|
def __init__(self, parent=None):
|
|
|
super(TcRtdTableView, self).__init__(parent)
|
|
|
self.delegate = BackgroundDelegate(self)
|
|
|
self.setItemDelegate(self.delegate)
|
|
|
self.setItemDelegateForColumn(6, TcRtdTypeDelegate(self))
|
|
|
|
|
|
self.valueList = [0] * 16
|
|
|
self.mvList = [0] * 16
|
|
|
self.setupColumnWidths()
|
|
|
# self.workThread = RTDTCThread(self)
|
|
|
# Globals.setValue('RTDTCThread', self.workThread)
|
|
|
# self.workThread.getValueList.connect(self.getValueList)
|
|
|
def setupColumnWidths(self):
|
|
|
self.header.setSectionResizeMode(QHeaderView.Stretch)
|
|
|
self.setCustomColumnWidths([1.2, 0.9, 0.9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
|
|
|
|
|
|
def setHeader(self):
|
|
|
self.setItemDelegateForColumn(12, TcRtdButtonDelegate(self))
|
|
|
self.setItemDelegateForColumn(11, TcRtdVarModelBox(self))
|
|
|
self.model = TcRtdModel([' ID', '强制值', '当前值', '变量名', '通道序号', '变量描述', '变量类型', '工程量下限', '工程量上限', '单位', '补偿值', '值类型', '操作'], [], table=self)
|
|
|
|
|
|
class AnalogTableView(VarTableView):
|
|
|
def __init__(self, parent=None):
|
|
|
super(AnalogTableView, self).__init__(parent)
|
|
|
# self.valueList = [0] * 8 + [0] * 8 + [0] * 16 + [0] * 8 + [0] * 8 + [0] * 8
|
|
|
# self.realList = [0] * 8 + [0] * 8 + [0] * 16 + [0] * 8 + [0] * 8 + [0] * 8
|
|
|
# self.workThread = AnalogThread(self)
|
|
|
# Globals.setValue('AnalogThread', self.workThread)
|
|
|
self.delegate = BackgroundDelegate(self)
|
|
|
self.setItemDelegate(self.delegate)
|
|
|
self.setupColumnWidths()
|
|
|
|
|
|
def setupColumnWidths(self):
|
|
|
self.setCustomColumnWidths([0.8, 0.8, 0.8, 1.8, 1, 1.4, 0.8, 0.8, 1, 1, 1, 1])
|
|
|
|
|
|
def setHeader(self):
|
|
|
self.setItemDelegateForColumn(11, AnalogButtonDelegate(self))
|
|
|
self.setItemDelegateForColumn(10, AnalogVarModelBox(self))
|
|
|
self.model = AnalogModel([' ID', '强制值', '当前值', '变量名', '通道序号', '变量描述', '变量类型', '工程量下限', '工程量上限', '单位', '值类型', '操作'], [], table=self)
|
|
|
|
|
|
|
|
|
class HartSimulateTableView(VarTableView):
|
|
|
def __init__(self, parent=None):
|
|
|
super(HartSimulateTableView, self).__init__(parent)
|
|
|
self.delegate = BackgroundDelegate(self)
|
|
|
self.setItemDelegate(self.delegate)
|
|
|
self.valueList = []
|
|
|
# self.realList = [0] * 8 + [0] * 8 + [0] * 8
|
|
|
self.workThread = HartSimulateThread(self)
|
|
|
Globals.setValue('HartSimulateThread', self.workThread)
|
|
|
|
|
|
def setupColumnWidths(self):
|
|
|
self.header.setSectionResizeMode(QHeaderView.Stretch)
|
|
|
|
|
|
def setHeader(self):
|
|
|
self.setItemDelegateForColumn(10, HartSimulateButtonDelegate(self))
|
|
|
self.setItemDelegateForColumn(9, HartSimulateVarModelBox(self))
|
|
|
self.model = HartSimulateModel([' ID', '仪器名', '描述', '主变量', '过程变量1', '过程变量2', '过程变量3', '工程量下限', '工程量上限', '值类型','操作'], [], table=self)
|
|
|
|
|
|
class RpcVarTableView(QTableView):
|
|
|
def __init__(self, parent=None):
|
|
|
super(RpcVarTableView, self).__init__(parent)
|
|
|
self.delegate = BackgroundDelegate(self)
|
|
|
self.setItemDelegate(self.delegate)
|
|
|
self.setShowGrid(False)
|
|
|
# self.setAlternatingRowColors(True)
|
|
|
self.setSelectionBehavior(QAbstractItemView.SelectRows)
|
|
|
self.setItemDelegateForColumn(7, RpcVarButtonDelegate(self))
|
|
|
self.model = RpcVarModel(['客户端', '变量名', '类型', '下限', '上限', '当前值', '操作'], self)
|
|
|
|
|
|
# 添加代理模型用于搜索过滤
|
|
|
self.proxy = QtCore.QSortFilterProxyModel(self)
|
|
|
self.proxy.setSourceModel(self.model)
|
|
|
self.setModel(self.proxy)
|
|
|
|
|
|
self.header = QHeaderView(Qt.Horizontal, self)
|
|
|
self.header.setStretchLastSection(True)
|
|
|
self.setHorizontalHeader(self.header)
|
|
|
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
|
|
self.setupColumnWidths()
|
|
|
|
|
|
def setupColumnWidths(self):
|
|
|
self.header.setSectionResizeMode(QHeaderView.Stretch)
|
|
|
|
|
|
def performSearch(self, searchText):
|
|
|
"""RPC变量表格搜索接口"""
|
|
|
try:
|
|
|
# 设置搜索列为变量名列(索引1)
|
|
|
self.proxy.setFilterKeyColumn(2)
|
|
|
search = QtCore.QRegExp(searchText, QtCore.Qt.CaseInsensitive, QtCore.QRegExp.RegExp)
|
|
|
self.proxy.setFilterRegExp(search)
|
|
|
return True
|
|
|
except Exception as e:
|
|
|
print(f"RPC变量搜索失败: {e}")
|
|
|
return False
|