You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			320 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
			
		
		
	
	
			320 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
| 
 | |
| import time
 | |
| import typing
 | |
| import re
 | |
| # from matplotlib.pyplot import box
 | |
| import qtawesome
 | |
| from PyQt5 import QtGui,QtCore,QtWidgets
 | |
| from PyQt5.QtCore import QAbstractTableModel, QModelIndex, Qt, QVariant, QSize, QTimer
 | |
| from PyQt5.QtWidgets import QItemDelegate, QHBoxLayout, QWidget, QPushButton, QMessageBox, QLineEdit,  \
 | |
| QComboBox, QStyledItemDelegate, QVBoxLayout, QSplitter
 | |
| 
 | |
| from UI.ProfibusWidgets.LoadingDataWidget import LoadingDataWidget
 | |
| from UI.ProfibusWidgets.ObjectTypeEditlayout import ObjectTypeEditlayout
 | |
| from UI.VarManages.BaseButtonDelegate import BaseButtonDelegate
 | |
| 
 | |
| from utils import Globals
 | |
| 
 | |
| from utils.DBModels.DeviceParModels import *
 | |
| 
 | |
| class VarTableModel(QAbstractTableModel):
 | |
|     ''' 变量表模型类'''
 | |
|     def __init__(self, header, data: list, 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 = [] # 表格中可编辑项
 | |
| 
 | |
| 
 | |
|    
 | |
|     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 updateColumn(self, row, value):
 | |
|         if row < 0 or row >= self.rowCount():
 | |
|             print("列索引超出范围")
 | |
|             return
 | |
|         # for row in range(self.rowCount()):
 | |
| 
 | |
|         if 'unit'  in self.datas[row][2].lower() or 'unt' in self.datas[row][2].lower():
 | |
|             unit = UnitTable.getUnitSymbolByUnitValue(value)
 | |
|             value = unit if unit else value
 | |
|         self.datas[row][6] = value
 | |
|         self.table.proxy.invalidate()
 | |
|         # self.layoutChanged.emit()  # 通知视图数据已更改
 | |
|         # self.dataChanged.emit()
 | |
| 
 | |
|     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():
 | |
|            
 | |
|             return QVariant()
 | |
| 
 | |
|         if role == Qt.TextColorRole:
 | |
|             return QtGui.QColor('#1A1A1A')
 | |
| 
 | |
|         if role == Qt.DisplayRole or role == Qt.EditRole:
 | |
|             if QModelIndex.row() in self.editableList or 'w' in self.datas[QModelIndex.row()][5]:
 | |
|                 return self.datas[QModelIndex.row()][QModelIndex.column()]
 | |
|         if role != Qt.DisplayRole:
 | |
|             return QVariant()
 | |
| 
 | |
| 
 | |
|         return 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 role == Qt.SizeHintRole:
 | |
|             # print(self.datas[QModelIndex.row()][QModelIndex.column()].find('\r\n'))
 | |
|             return QSize(500, 500)
 | |
| 
 | |
|         if orientation == Qt.Horizontal:
 | |
|             return self.header[section]
 | |
| 
 | |
|         # if orientation == Qt.Vertical:
 | |
|         #     return str(section + 1)
 | |
| 
 | |
|     def setData(self, index, value, role):
 | |
|         row = index.row()
 | |
|         col = index.column()
 | |
|         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() == 7:
 | |
|             return Qt.ItemIsEnabled | Qt.ItemIsUserCheckable | Qt.ItemIsEditable
 | |
|       
 | |
| 
 | |
|         if 'w' in self.datas[index.row()][5] and index.column() == 6:
 | |
|             return Qt.ItemIsEnabled | Qt.ItemIsEditable
 | |
|      
 | |
|         return Qt.ItemIsEnabled
 | |
| 
 | |
|     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 updateValue(self, valueList):
 | |
|         for index, value in enumerate(valueList):
 | |
|             if 'unit' in self.datas[index][2].lower() or 'unt'  in self.datas[index][2].lower():
 | |
|                 unit = UnitTable.getUnitSymbolByUnitValue(value)
 | |
|                 value = unit if unit else value
 | |
|             self.datas[index][6] = value
 | |
|         self.table.proxy.invalidate()
 | |
| 
 | |
| 
 | |
| 
 | |
| class ProfibusButtonDelegate(BaseButtonDelegate):
 | |
|     """该类用于向单元格中添加按钮  任务表格"""
 | |
|     def __init__(self, parent=None):
 | |
|         super(ProfibusButtonDelegate, self).__init__(parent)
 | |
| 
 | |
|     def paint(self, painter, option, index):
 | |
|         if not self.parent().indexWidget(index):
 | |
|             startActionBtn = QPushButton(
 | |
|                 qtawesome.icon('fa.play', color='#1fbb6f'),
 | |
|                 "",
 | |
|                 self.parent()
 | |
|             )
 | |
|             
 | |
|             boxLayout = QHBoxLayout()
 | |
|             
 | |
|             refreshButton = QPushButton(
 | |
|                 qtawesome.icon('fa.refresh', color='#1fbb6f'),
 | |
|                 "",
 | |
|                 self.parent()
 | |
|             )
 | |
| 
 | |
|             refreshButton.setToolTip('刷新')
 | |
|             refreshButton.setObjectName("refreshButton")
 | |
|             refreshButton.clicked.connect(self.refreshData)
 | |
|             refreshButton.index = [index.row(), index.column()]
 | |
|             refreshButton.setIconSize(QSize(50,50))
 | |
| 
 | |
|             readORwirte = self.parent().model.datas[index.row()][5]
 | |
|             if 'w' not in readORwirte:
 | |
|                 boxLayout.addWidget(QSplitter())
 | |
|                 boxLayout.addWidget(refreshButton)
 | |
|                 boxLayout.addWidget(QSplitter())
 | |
|             else:
 | |
|                 dataType = self.parent().model.datas[index.row()][4]
 | |
|                 objectType =  self.parent().model.datas[index.row()][2]
 | |
| 
 | |
|                 editlineLayout = ObjectTypeEditlayout(objectType, dataType)
 | |
| 
 | |
|                 startActionBtn.index = [index.row(), index.column()]
 | |
|                 startActionBtn.setToolTip('强制')
 | |
| 
 | |
|                 
 | |
| 
 | |
|                     
 | |
|                 if objectType == 'TARGET_MODE':
 | |
|                     combox = QComboBox()
 | |
|                     combox.setObjectName('modeCombox')
 | |
|                     combox.addItems(["非服务", "手动初始化", "本地超驰", '手动', '自动', '级联', '远程级联', '远程输出'])
 | |
|                     combox.setCurrentIndex(-1)
 | |
|                     combox.currentIndexChanged.connect(lambda index: self.startAction(modelIndex = index))
 | |
|                     boxLayout.addWidget(combox, 10)
 | |
|                     boxLayout.addWidget(refreshButton,1)
 | |
|                     combox.index = [index.row(), index.column()]
 | |
| 
 | |
|                 elif 'unit'  in objectType.lower() or 'unt' in objectType.lower():
 | |
|                     comboxUnit = QComboBox()
 | |
|                     comboxUnit.setObjectName('modeCombox')
 | |
|                     comboxUnit.addItem('下拉选择')
 | |
|                     comboxUnit.addItems([x[1] for x in self.parent().allUnitList])
 | |
| 
 | |
|                     
 | |
|                     comboxUnit.currentIndexChanged.connect(lambda index, comboxUnit = comboxUnit : self.startAction(modelIndex = index, comboxUnit = comboxUnit))
 | |
|                     boxLayout.addWidget(comboxUnit, 10)
 | |
|                     boxLayout.addWidget(refreshButton,1)
 | |
|                     comboxUnit.index = [index.row(), index.column()]
 | |
| 
 | |
|                 else:
 | |
|                     boxLayout.addLayout(editlineLayout)     
 | |
|                     startActionBtn.clicked.connect(lambda: self.startAction(objectTypeEditlayout = editlineLayout))
 | |
|                     boxLayout.addWidget(startActionBtn)
 | |
|                     boxLayout.addWidget(refreshButton)
 | |
| 
 | |
| 
 | |
|                 
 | |
|                 startActionBtn.setObjectName('startActionBtn')
 | |
|                 startActionBtn.setIconSize(QSize(50,50))
 | |
| 
 | |
| 
 | |
|             boxLayout.setContentsMargins(0, 0, 0, 0)
 | |
|             widget = QWidget()
 | |
|             # widget.setMinimumHeight(200)
 | |
|             widget.setLayout(boxLayout)
 | |
|             self.parent().setIndexWidget(
 | |
|                 index,
 | |
|                 widget
 | |
|             )
 | |
|              
 | |
|         
 | |
|     def startAction(self, objectTypeEditlayout = None, modelIndex = None, comboxUnit = None):
 | |
|         sender = self.sender()
 | |
|         blockView = self.parent()
 | |
|         model = blockView.model
 | |
|         
 | |
|         # 使用基类的验证方法获取行索引
 | |
|         view_row, source_row = self._validate_button_indices(sender)
 | |
|         if view_row is None:
 | |
|             return
 | |
|         
 | |
|         blockType = blockView.blockType
 | |
|         blockIndex = blockView.blcokIndex
 | |
|         parmIndex = model.datas[source_row][1]
 | |
|         blockManage = Globals.getValue('blockManage')
 | |
|         values = []
 | |
|         #修改单位
 | |
|         if comboxUnit:
 | |
|             if modelIndex == 0:
 | |
|                 return
 | |
|             else:
 | |
|                 values = [self.parent().allUnitList[modelIndex - 1][0]]
 | |
|             # print(values)
 | |
|         #修改操作模式
 | |
|         else: 
 | |
|             if modelIndex or str(modelIndex) == '0' :
 | |
|               
 | |
|                 values.append(str(modelIndex))
 | |
|             #正常修改其他值
 | |
|             else:
 | |
|                 
 | |
|                 values = objectTypeEditlayout.getEditlineValue()
 | |
|                 
 | |
|                 dataType = model.datas[source_row][4]
 | |
|                 if not values:
 | |
|                         reply = QMessageBox.question(self.parent(),
 | |
|                                                         '警告',
 | |
|                                                         "请输入强制值",
 | |
|                                                         QMessageBox.Yes)
 | |
|                         return
 | |
|                 if dataType in ['Float', 'DS-36', 'Unsigned16', 'Unsigned8']:
 | |
|                         pattern = re.compile(r'^[+-]?(\d+(\.\d*)?|\.\d+)$')
 | |
|                         for value in values:
 | |
|                             if not value or not re.findall(pattern, str(value)):
 | |
|                                 reply = QMessageBox.question(self.parent(),
 | |
|                                                             '警告',
 | |
|                                                             "请输入强制值或数字",
 | |
|                                                             QMessageBox.Yes)
 | |
|                                 return
 | |
|         # print(values,555)
 | |
|         res = blockManage.writeParmValue(blockType, blockIndex, parmIndex, values)
 | |
|         time.sleep(0.4)
 | |
|         self.refreshData()
 | |
|     
 | |
|     def refreshData(self):
 | |
|         sender = self.sender()
 | |
|         blockView = self.parent()
 | |
|         model = blockView.model
 | |
|         
 | |
|         # 使用基类的验证方法获取行索引
 | |
|         view_row, source_row = self._validate_button_indices(sender)
 | |
|         if view_row is None:
 | |
|             return
 | |
|         
 | |
|         parmIndex = model.datas[source_row][1]
 | |
|         blockType = blockView.blockType
 | |
|         blockIndex = blockView.blcokIndex
 | |
|         # print(blockName, blcokIndex, index)
 | |
|         blockManage = Globals.getValue('blockManage')
 | |
|         value = blockManage.getBlockParmValue(blockType, blockIndex, parmIndex)
 | |
|         # self.loadingDataWidget = LoadingDataWidget()
 | |
|         # self.loadingDataWidget.show()
 | |
|         # self.loadingDataWidget.loadData(1, 1)
 | |
|         self.loadingDataWidget = LoadingDataWidget(refreshType = True)
 | |
|         self.loadingDataWidget.exec_()
 | |
|         model.updateColumn(source_row, value)
 | |
|         # self.parent().resizeHeader()
 | |
|         blockView.proxy.invalidate()
 | |
| 
 | |
|     
 | |
| 
 | |
| 
 |