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.
135 lines
5.8 KiB
Python
135 lines
5.8 KiB
Python
from PyQt5.QtCore import Qt, QAbstractTableModel, QVariant, QTimer, QModelIndex, QEvent, QSize
|
|
from PyQt5.QtGui import QColor
|
|
from PyQt5.QtWidgets import QMessageBox, QPushButton, QItemDelegate, QStyleOptionButton, QStyle, QWidget, QInputDialog, QHBoxLayout
|
|
from utils import Globals
|
|
import qtawesome
|
|
|
|
class RpcVarModel(QAbstractTableModel):
|
|
def __init__(self, header, parent=None):
|
|
# 新顺序:当前值、强制值、变量名、类型、下限、上限、客户端、强制按钮
|
|
self.header = ['当前值', '强制值', '变量名', '类型', '下限', '上限', '客户端', '操作']
|
|
super().__init__(parent)
|
|
self.datas = []
|
|
self.valueCache = {}
|
|
self.inputValues = {} # 行号->输入值
|
|
self.refreshTimer = QTimer()
|
|
self.refreshTimer.timeout.connect(self.refreshData)
|
|
self.refreshTimer.start(500) # 每秒刷新一次
|
|
|
|
def refreshData(self):
|
|
"""刷新所有远程变量数据,并按类型排序"""
|
|
protocolManage = Globals.getValue('protocolManage')
|
|
if protocolManage and protocolManage.RpcServer:
|
|
allVars = protocolManage.RpcServer.broadcastRead()
|
|
temp = []
|
|
for client in allVars:
|
|
clientName = client.get('client', '')
|
|
variables = client.get('variables', {})
|
|
for varName, varInfo in variables.items():
|
|
row = [
|
|
varInfo.get('value', ''), # 当前值
|
|
self.inputValues.get(len(temp), ''),# 强制值(输入缓存)
|
|
varName, # 变量名
|
|
varInfo.get('type', ''), # 类型
|
|
varInfo.get('min', ''), # 下限
|
|
varInfo.get('max', ''), # 上限
|
|
clientName, # 客户端(倒数第二列)
|
|
'', # 强制按钮(最后一列)
|
|
]
|
|
temp.append(row)
|
|
# 按类型排序
|
|
temp.sort(key=lambda x: x[3])
|
|
self.datas = temp
|
|
self.layoutChanged.emit()
|
|
|
|
def rowCount(self, parent=None):
|
|
return len(self.datas)
|
|
|
|
def columnCount(self, parent=None):
|
|
return len(self.header)
|
|
|
|
def data(self, index, role=Qt.DisplayRole):
|
|
if not index.isValid():
|
|
return QVariant()
|
|
row = index.row()
|
|
col = index.column()
|
|
if role == Qt.DisplayRole:
|
|
# 强制值输入列显示缓存值
|
|
if col == 1:
|
|
return self.inputValues.get(row, '')
|
|
return self.datas[row][col]
|
|
if role == Qt.TextAlignmentRole:
|
|
return Qt.AlignCenter
|
|
if role == Qt.BackgroundRole:
|
|
if row % 2 == 0:
|
|
return QColor('#EFEFEF')
|
|
return QVariant()
|
|
|
|
def setData(self, index, value, role=Qt.EditRole):
|
|
if index.isValid() and index.column() == 1:
|
|
self.inputValues[index.row()] = value
|
|
self.dataChanged.emit(index, index)
|
|
return True
|
|
return False
|
|
|
|
def headerData(self, section, orientation, role=Qt.DisplayRole):
|
|
if role == Qt.DisplayRole and orientation == Qt.Horizontal:
|
|
return self.header[section]
|
|
return QVariant()
|
|
|
|
def flags(self, index):
|
|
if not index.isValid():
|
|
return Qt.ItemIsEnabled
|
|
if index.column() == 1:
|
|
return Qt.ItemIsEnabled | Qt.ItemIsEditable
|
|
if index.column() == 7:
|
|
return Qt.ItemIsEnabled # 按钮列不可编辑
|
|
return Qt.ItemIsEnabled
|
|
|
|
from PyQt5.QtWidgets import QStyledItemDelegate, QPushButton, QStyleOptionButton, QStyle, QApplication
|
|
|
|
class RpcVarButtonDelegate(QStyledItemDelegate):
|
|
def __init__(self, parent=None):
|
|
super(RpcVarButtonDelegate, self).__init__(parent)
|
|
|
|
def paint(self, painter, option, index):
|
|
if not self.parent().indexWidget(index) and index.column() == 7:
|
|
button = QPushButton(
|
|
qtawesome.icon('fa.play', color='#1fbb6f'),
|
|
'',
|
|
self.parent()
|
|
)
|
|
button.setIconSize(QSize(15, 15))
|
|
button.setStyleSheet('border:none;')
|
|
button.index = [index.row(), index.column()]
|
|
button.clicked.connect(lambda: self.force_action(button))
|
|
h_box_layout = QHBoxLayout()
|
|
h_box_layout.addWidget(button)
|
|
h_box_layout.setContentsMargins(2, 0, 0, 2)
|
|
h_box_layout.setAlignment(Qt.AlignCenter)
|
|
widget = QWidget()
|
|
widget.setLayout(h_box_layout)
|
|
self.parent().setIndexWidget(index, widget)
|
|
# 不再用QStyleOptionButton绘制
|
|
|
|
def force_action(self, sender):
|
|
model = self.parent().model
|
|
row = sender.index[0]
|
|
varName = model.datas[row][2]
|
|
minValue = model.datas[row][4]
|
|
maxValue = model.datas[row][5]
|
|
forceValue = model.inputValues.get(row, '')
|
|
if forceValue == '':
|
|
QMessageBox.warning(self.parent(), '提示', '请先输入强制值')
|
|
return
|
|
try:
|
|
protocolManage = Globals.getValue('protocolManage')
|
|
if protocolManage and protocolManage.RpcServer:
|
|
resp = protocolManage.RpcServer.writeVar(varName, float(forceValue))
|
|
if resp.get('result') == 'success':
|
|
QMessageBox.information(self.parent(), '提示', f'{varName} 强制成功!')
|
|
else:
|
|
reason = resp.get('reason', '')
|
|
QMessageBox.warning(self.parent(), '失败', f'{varName} 强制失败: {reason}')
|
|
except Exception as e:
|
|
QMessageBox.warning(self.parent(), '错误', f'强制失败: {e}') |