Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 20b6749ed4 | |||
| fa33a4479d | |||
| 54b332f69d | |||
| 0ff5ca7b49 | |||
| 76a6f28136 | |||
| 3c408ebcbd |
55
pvgateway.py
55
pvgateway.py
@@ -113,7 +113,7 @@ class PVGateway(QWidget):
|
||||
1000 / self.notify_freq_hz
|
||||
|
||||
self.notify_unison = bool(notify_unison) and bool(self.notify_freq_hz)
|
||||
|
||||
|
||||
self.parent = parent
|
||||
self.settings = self.parent.settings
|
||||
|
||||
@@ -121,6 +121,8 @@ class PVGateway(QWidget):
|
||||
|
||||
self.color_mode = None
|
||||
|
||||
self.check_rtyp = False
|
||||
|
||||
if color_mode is not None:
|
||||
if color_mode in (self.ACT_ON_BEAM,
|
||||
self.NOT_ACT_ON_BEAM,
|
||||
@@ -148,9 +150,13 @@ class PVGateway(QWidget):
|
||||
self.cafe = self.parent.cafe
|
||||
self.cyca = self.parent.cyca
|
||||
|
||||
self.url_archiver = None
|
||||
self.url_databuffer = None
|
||||
|
||||
if self.parent.settings is not None:
|
||||
self.url_archiver = self.parent.settings.data["url"]["archiver"]
|
||||
self.url_databuffer = self.parent.settings.data["url"]["databuffer"]
|
||||
if "databuffer" in self.parent.settings.data["url"]:
|
||||
self.url_databuffer = self.parent.settings.data["url"]["databuffer"]
|
||||
self.bg_readback = self.parent.settings.data["StyleGuide"][
|
||||
"bgReadback"]
|
||||
self.fg_alarm_major = self.parent.settings.data["StyleGuide"][
|
||||
@@ -163,10 +169,10 @@ class PVGateway(QWidget):
|
||||
"fgAlarmNoAlarm"]
|
||||
else:
|
||||
#self.settings = ReadJSON(self.parent.appname)
|
||||
self.url_archiver = ("https://ui-data-api.psi.ch/prepare?channel=" +
|
||||
self.url_archiver = ("https://data-ui.psi.ch/preselect?c1=" +
|
||||
"sf-archiverappliance/")
|
||||
self.url_databuffer \
|
||||
= "https://ui-data-api.psi.ch/prepare?channel=sf-databuffer/"
|
||||
= "https://data-ui.psi.ch/preselect?c1=sf-databuffer/"
|
||||
|
||||
self.daq_group_name = self._DAQ_CAFE_SG_NAME
|
||||
self.desc = None
|
||||
@@ -272,23 +278,20 @@ class PVGateway(QWidget):
|
||||
|
||||
action1 = QAction("Text Info", self)
|
||||
action1.triggered.connect(self.pv_status_text)
|
||||
|
||||
self.context_menu.addAction(action1)
|
||||
action2 = QAction("Lookup in Archiver", self)
|
||||
action2.triggered.connect(self.lookup_archiver)
|
||||
|
||||
action3 = QAction("Lookup in Databuffer", self)
|
||||
action3.triggered.connect(self.lookup_databuffer)
|
||||
|
||||
self.context_menu.addAction(action2)
|
||||
if self.url_databuffer is not None:
|
||||
action3 = QAction("Lookup in Databuffer", self)
|
||||
action3.triggered.connect(self.lookup_databuffer)
|
||||
self.context_menu.addAction(action3)
|
||||
action4 = QAction("Strip Chart (PShell)", self)
|
||||
action4.triggered.connect(self.strip_chart)
|
||||
|
||||
self.context_menu.addAction(action4)
|
||||
action6 = QAction("Configure Display Parameters", self)
|
||||
action6.triggered.connect(self.display_parameters)
|
||||
|
||||
self.context_menu.addAction(action1)
|
||||
self.context_menu.addAction(action2)
|
||||
self.context_menu.addAction(action3)
|
||||
self.context_menu.addAction(action4)
|
||||
|
||||
action5 = QAction("Reconnect: {0}".format(self.pv_name), self)
|
||||
action5.triggered.connect(self.reconnect_channel)
|
||||
@@ -385,7 +388,7 @@ class PVGateway(QWidget):
|
||||
|
||||
if self.pv_info is None:
|
||||
self.pv_info = self.cafe.getChannelInfo(self.pv_name)
|
||||
if "Not Supported" in self.pv_info.className:
|
||||
if "Not Supported" in self.pv_info.className and self.check_rtyp:
|
||||
_rtype = self.cafe.get(self.pv_name.split(".")[0] + ".RTYP")
|
||||
self.record_type = _rtype if _rtype is not None else \
|
||||
self.pv_info.className
|
||||
@@ -418,8 +421,9 @@ class PVGateway(QWidget):
|
||||
_max_control_abs = 0
|
||||
|
||||
if self.pv_ctrl is not None:
|
||||
_lower_control_abs = abs(int(self.pv_ctrl.lowerControlLimit))
|
||||
_upper_control_abs = abs(int(self.pv_ctrl.upperControlLimit))
|
||||
#DisplayLimit preferred over ControlLimit as latter n/a for ao
|
||||
_lower_control_abs = abs(int(self.pv_ctrl.lowerDisplayLimit))
|
||||
_upper_control_abs = abs(int(self.pv_ctrl.upperDisplayLimit))
|
||||
_max_control_abs = max(_lower_control_abs, _upper_control_abs)
|
||||
if _max_control_abs is None:
|
||||
_max_control_abs = 0
|
||||
@@ -494,7 +498,7 @@ class PVGateway(QWidget):
|
||||
time.sleep(0.01)
|
||||
self.initialize_meta_data()
|
||||
icount += 1
|
||||
if icount > 50:
|
||||
if icount > 5: #50
|
||||
return False
|
||||
return True
|
||||
|
||||
@@ -583,7 +587,7 @@ class PVGateway(QWidget):
|
||||
self.pv_ctrl = self.cafe.getCtrlCache(self.handle)
|
||||
self.pv_info = self.cafe.getChannelInfo(self.handle)
|
||||
if self.pv_info is not None and self.record_type is None:
|
||||
if "Not Supported" in self.pv_info.className:
|
||||
if "Not Supported" in self.pv_info.className and self.check_rtyp:
|
||||
_rtype = self.cafe.get(self.pv_name.split(".")[0] + ".RTYP")
|
||||
self.record_type = _rtype if _rtype is not None else \
|
||||
self.pv_info.className
|
||||
@@ -630,7 +634,7 @@ class PVGateway(QWidget):
|
||||
DAQ may be in BS mode, but channels within DAQ stream that
|
||||
are not BS enabled will be flagged as CA Mode, i.e., CARead
|
||||
'''
|
||||
|
||||
|
||||
_current_qt_dynamic_property = self.qt_dynamic_property_get()
|
||||
|
||||
alarm_severity = daq_pvd.alarmSeverity
|
||||
@@ -704,12 +708,13 @@ class PVGateway(QWidget):
|
||||
|
||||
|
||||
def receive_monitor_dbr_time(self, pvdata, alarm_severity):
|
||||
print("called from gateway", self.pv_name, alarm_severity)
|
||||
print("called from gateway", self.pv_name, alarm_severity, flush=True)
|
||||
pvdata.show()
|
||||
|
||||
def receive_monitor_update(self, value, status, alarm_severity):
|
||||
'''Triggered by monitor signal. For Widget to overload.'''
|
||||
|
||||
|
||||
self.mutex_post_display.lock()
|
||||
_current_qt_dynamic_property = self.qt_dynamic_property_get()
|
||||
|
||||
@@ -761,6 +766,7 @@ class PVGateway(QWidget):
|
||||
'''Callback function to be invoked on change of pv value.
|
||||
cafe.getCache and cafe.set operations permitted within callback.
|
||||
'''
|
||||
|
||||
self.mutex.lock()
|
||||
|
||||
pv_name = pvname
|
||||
@@ -1342,7 +1348,7 @@ class PVGateway(QWidget):
|
||||
if self.pv_info is None:
|
||||
self.pv_info = self.cafe.getChannelInfo(self.handle)
|
||||
if self.pv_info is not None and self.record_type is None:
|
||||
if "Not Supported" in self.pv_info.className:
|
||||
if "Not Supported" in self.pv_info.className and self.check_rtyp:
|
||||
_rtype = self.cafe.get(self.pv_name.split(".")[0] + ".RTYP")
|
||||
self.record_type = _rtype if _rtype is not None else \
|
||||
self.pv_info.className
|
||||
@@ -1386,7 +1392,7 @@ class PVGateway(QWidget):
|
||||
if self.pv_info is None:
|
||||
self.pv_info = self.cafe.getChannelInfo(self.handle)
|
||||
if self.pv_info is not None and self.record_type is None:
|
||||
if "Not Supported" in self.pv_info.className:
|
||||
if "Not Supported" in self.pv_info.className and self.check_rtyp:
|
||||
_rtype = self.cafe.get(self.pv_name.split(".")[0] + ".RTYP")
|
||||
self.record_type = _rtype if _rtype is not None else \
|
||||
self.pv_info.className
|
||||
@@ -1491,8 +1497,7 @@ class PVGateway(QWidget):
|
||||
self.pv_status_text_display_limits())
|
||||
|
||||
self.pv_message_in_a_box.setText(
|
||||
self.pv_status_text_header(source=_source) + _text_data
|
||||
)
|
||||
self.pv_status_text_header(source=_source) + _text_data)
|
||||
QApplication.processEvents()
|
||||
self.pv_message_in_a_box.exec()
|
||||
|
||||
|
||||
1696
pvgateway.py-
1696
pvgateway.py-
File diff suppressed because it is too large
Load Diff
1910
pvgateway.py:2.9
1910
pvgateway.py:2.9
File diff suppressed because it is too large
Load Diff
454
pvwidgets.py
454
pvwidgets.py
@@ -12,18 +12,17 @@ from sklearn.linear_model import LinearRegression
|
||||
from distutils.version import LooseVersion
|
||||
from functools import reduce as func_reduce
|
||||
|
||||
from qtpy.QtCore import (QEventLoop, QMutex, QPoint, Qt, QThread, QTimer,
|
||||
Signal, Slot)
|
||||
from qtpy.QtGui import (QCloseEvent, QColor, QCursor, QFont, QFontMetricsF,
|
||||
QIcon, QKeySequence)
|
||||
from qtpy.QtCore import (
|
||||
QEventLoop, QMutex, QPoint, Qt, QThread, QTimer, Signal, Slot)
|
||||
from qtpy.QtGui import (
|
||||
QCloseEvent, QColor, QCursor, QFont, QFontMetricsF, QIcon, QKeySequence)
|
||||
from qtpy.QtCore import __version__ as QT_VERSION_STR
|
||||
from qtpy.QtWidgets import (QAbstractItemView, QAbstractSpinBox, QAction,
|
||||
QApplication, QBoxLayout, QCheckBox, QComboBox,
|
||||
QDialog, QDockWidget, QDoubleSpinBox, QFrame,
|
||||
QGroupBox, QHBoxLayout, QLabel, QLineEdit,
|
||||
QListWidget, QMenu, QMessageBox, QPushButton,
|
||||
QSpinBox, QStyle, QStyleOptionSpinBox, QTableWidget,
|
||||
QTableWidgetItem, QVBoxLayout, QWidget)
|
||||
from qtpy.QtWidgets import (
|
||||
QAbstractItemView, QAbstractSpinBox, QAction, QApplication, QBoxLayout,
|
||||
QCheckBox, QComboBox, QDialog, QDockWidget, QDoubleSpinBox, QFrame,
|
||||
QGroupBox, QHBoxLayout, QLabel, QLineEdit, QListWidget, QMenu, QMessageBox,
|
||||
QPushButton, QSpinBox, QStyle, QStyleOptionSpinBox, QTableWidget,
|
||||
QTableWidgetItem, QVBoxLayout, QWidget)
|
||||
|
||||
import pyqtgraph as pg
|
||||
from pyqtgraph import PlotWidget
|
||||
@@ -287,7 +286,6 @@ class CAQMenu(QComboBox, PVGateway):
|
||||
|
||||
def post_display_value(self, value):
|
||||
|
||||
|
||||
'''Convert value to index'''
|
||||
if "setCurrentIndex" in dir(self):
|
||||
|
||||
@@ -297,7 +295,6 @@ class CAQMenu(QComboBox, PVGateway):
|
||||
if isinstance(value, str):
|
||||
self.setCurrentIndex(self.cafe.getEnumFromString(self.handle,
|
||||
value))
|
||||
|
||||
elif isinstance(value, int):
|
||||
self.setCurrentIndex(value)
|
||||
#Should not happen
|
||||
@@ -542,12 +539,14 @@ class CAQTextEntry(QLineEdit, PVGateway):
|
||||
trigger_monitor = Signal(object, int)
|
||||
trigger_connect = Signal(int, str, int)
|
||||
|
||||
def __init__(self, parent=None, pv_name: str = "", monitor_callback=None,
|
||||
def __init__(self, parent=None, pv_name: str="", monitor_callback=None,
|
||||
pv_within_daq_group: bool = False, color_mode=None,
|
||||
show_units=False, prefix: str = "", suffix: str = ""):
|
||||
show_units=False, prefix: str="", suffix: str="",
|
||||
precision: int=0):
|
||||
super().__init__(parent, pv_name, monitor_callback, pv_within_daq_group,
|
||||
color_mode, show_units, prefix, suffix,
|
||||
connect_callback=self.py_connect_callback)
|
||||
connect_callback=self.py_connect_callback,
|
||||
precision=precision)
|
||||
|
||||
self.is_initialize_complete() #waits a fraction of a second
|
||||
|
||||
@@ -577,13 +576,21 @@ class CAQTextEntry(QLineEdit, PVGateway):
|
||||
def configure_widget(self):
|
||||
self.setFocusPolicy(Qt.StrongFocus)
|
||||
|
||||
fm = QFontMetricsF(QFont("Sans Serif", 12))
|
||||
|
||||
|
||||
f = QFont("Sans Serif")
|
||||
f.setPixelSize(11)
|
||||
|
||||
fm = QFontMetricsF(f)
|
||||
|
||||
qrect = fm.boundingRect(self.suggested_text)
|
||||
|
||||
_width_scaling_factor = 1.15
|
||||
|
||||
self.setFixedHeight((fm.lineSpacing()*1.8))
|
||||
self.setFixedWidth(((qrect.width()+10) * _width_scaling_factor))
|
||||
_width_scaling_factor = 1.2
|
||||
|
||||
|
||||
|
||||
self.setFixedHeight(18) #(fm.lineSpacing()*1.6))
|
||||
self.setFixedWidth((qrect.width()+20) * _width_scaling_factor)
|
||||
|
||||
self.qt_property_initial_values(qt_object_name=self.PV_CONTROLLER)
|
||||
|
||||
@@ -601,7 +608,7 @@ class CAQTextEntry(QLineEdit, PVGateway):
|
||||
else:
|
||||
valStr = ("{: .%sf}" % self.precision)
|
||||
strText = valStr.format(round(val, self.precision))
|
||||
print(strText, " precision ", self.precision)
|
||||
#print(strText, " precision ", self.precision)
|
||||
self.setText(strText)
|
||||
else:
|
||||
#Do this for TextInfo cache
|
||||
@@ -646,7 +653,7 @@ class CAQTextEntry(QLineEdit, PVGateway):
|
||||
|
||||
|
||||
class CAQSpinBox(QSpinBox, PVGateway):
|
||||
'''Channel access enabled QTextEntry widget'''
|
||||
'''Channel access enabled QSpinBox widget'''
|
||||
trigger_monitor_float = Signal(float, int, int)
|
||||
trigger_monitor_int = Signal(int, int, int)
|
||||
trigger_monitor_str = Signal(str, int, int)
|
||||
@@ -990,6 +997,8 @@ class CAQDoubleSpinBox(QDoubleSpinBox, PVGateway):
|
||||
|
||||
def mouseReleaseEvent(self, event):
|
||||
self.clearFocus()
|
||||
self.lineEdit().clearFocus()
|
||||
|
||||
|
||||
def setValue(self, value):
|
||||
self.currentValue = self.value()
|
||||
@@ -1047,14 +1056,18 @@ class CAQDoubleSpinBox(QDoubleSpinBox, PVGateway):
|
||||
self.qt_style_polish()
|
||||
|
||||
self.clearFocus()
|
||||
self.lineEdit().clearFocus()
|
||||
self.lineEdit().setFocusPolicy(Qt.NoFocus)
|
||||
self.setFocusPolicy(Qt.NoFocus)
|
||||
del event
|
||||
|
||||
def keyPressEvent(self, event):
|
||||
|
||||
if event.key() in (Qt.Key_Return, Qt.Key_Enter):
|
||||
QDoubleSpinBox.keyPressEvent(self, event)
|
||||
self.clearFocus()
|
||||
self.lineEdit().clearFocus()
|
||||
self.lineEdit().setFocusPolicy(Qt.NoFocus)
|
||||
self.setFocusPolicy(Qt.NoFocus)
|
||||
elif event.key() in (Qt.Key_Up, Qt.Key_Down):
|
||||
QDoubleSpinBox.keyPressEvent(self, event)
|
||||
else:
|
||||
@@ -1101,16 +1114,25 @@ class reconnectQPushButton(QPushButton, QThread):
|
||||
def reconnect(self):
|
||||
QApplication.processEvents()
|
||||
|
||||
|
||||
self.isdirty = True
|
||||
if self._handles_to_reconnect:
|
||||
|
||||
self.parent.cafe.reconnect(self._handles_to_reconnect)
|
||||
|
||||
self.isdirty = False
|
||||
#Uncheck reconnected channels
|
||||
for i in range(0, len(self.parent.pv_gateway)):
|
||||
|
||||
if self.parent.item(
|
||||
i, self.parent.no_columns-1).checkState() == Qt.Checked:
|
||||
if self.parent.cafe.isConnected(
|
||||
self.parent.pv_gateway[i].handle):
|
||||
|
||||
self.parent.item(
|
||||
i, self.parent.no_columns-1).setCheckState(False)
|
||||
else:
|
||||
#Even if not connected - uncheck box as action is complete
|
||||
self.parent.item(
|
||||
i, self.parent.no_columns-1).setCheckState(False)
|
||||
|
||||
@@ -1142,12 +1164,15 @@ class CAQTableWidget(QTableWidget):
|
||||
return newDataFlag
|
||||
|
||||
|
||||
def paint_rows(self, row_range: list = [], reset=False, last_row=[" ", " "],
|
||||
def paint_rows(self, row_range: list=[], reset=False, last_row=[" ", " "],
|
||||
columns=[0]):
|
||||
|
||||
_qcolor_last_line = QColor("#d1e8e9")
|
||||
self.font_pts11 = QTableWidgetItem().font()
|
||||
self.font_pts11.setPixelSize(11)
|
||||
self.font_pts8 = QTableWidgetItem().font()
|
||||
self.font_pts8.setPointSize(8)
|
||||
if not row_range:
|
||||
row_range = [0, self.rowCount()-1]
|
||||
|
||||
if reset:
|
||||
_qcolor = self.item(0, self.columnCount()-1).background()
|
||||
_start = 0
|
||||
@@ -1158,45 +1183,45 @@ class CAQTableWidget(QTableWidget):
|
||||
_end = row_range[1]
|
||||
|
||||
for _row in range(_start, _end):
|
||||
_cell = QTableWidgetItem("{0}".format(_row+1))
|
||||
if not reset:
|
||||
_cell.setFont(self.font_pts11)
|
||||
_cell.setBackground(_qcolor)
|
||||
|
||||
#if not reset:
|
||||
#_cell.setFont(self.font_pts8)
|
||||
if 1 in columns:
|
||||
self.item(_row, 0).setBackground(_qcolor)
|
||||
self.item(_row, 0).setFont(self.font_pts11)
|
||||
self.item(_row, 0).setFont(self.font_pts8)
|
||||
if 0 in columns:
|
||||
_cell = QTableWidgetItem("{0}".format(_row+1))
|
||||
#if not reset:
|
||||
_cell.setFont(self.font_pts8)
|
||||
#_cell.setTextAlignment(Qt.AlignCenter)
|
||||
self.setVerticalHeaderItem(_row, _cell)
|
||||
|
||||
|
||||
|
||||
#last row
|
||||
|
||||
if reset and 0 in columns:
|
||||
_cell = QTableWidgetItem("{0}".format(last_row[0]))
|
||||
_cell.setFont(self.font_pts11)
|
||||
_cell.setFont(self.font_pts8)
|
||||
self.setVerticalHeaderItem(self.rowCount()-1, _cell)
|
||||
|
||||
self.item(self.rowCount()-1, 0).setTextAlignment(Qt.AlignCenter)
|
||||
self.item(self.rowCount()-1, 0).setText(str(last_row[1]))
|
||||
self.item(self.rowCount()-1, 0).setBackground(_qcolor)
|
||||
self.item(self.rowCount()-1, 0).setFont(self.font_pts11)
|
||||
self.item(self.rowCount()-1, 0).setFont(self.font_pts8)
|
||||
elif last_row[0] != " ":
|
||||
_cell = QTableWidgetItem("{0}".format(last_row[0]))
|
||||
_cell.setBackground(_qcolor_last_line)
|
||||
_cell.setFont(self.font_pts11)
|
||||
_cell.setFont(self.font_pts8)
|
||||
self.setVerticalHeaderItem(self.rowCount()-1, _cell)
|
||||
|
||||
if columns:
|
||||
self.item(self.rowCount()-1, 0).setTextAlignment(Qt.AlignCenter)
|
||||
self.item(self.rowCount()-1, 0).setText(str(last_row[1]))
|
||||
self.item(self.rowCount()-1, 0).setBackground(_qcolor_last_line)
|
||||
self.item(self.rowCount()-1, 0).setFont(self.font_pts11)
|
||||
self.item(self.rowCount()-1, 0).setFont(self.font_pts8)
|
||||
|
||||
|
||||
def widget_update(self):
|
||||
|
||||
|
||||
""" Called when self.notif_unison is True """
|
||||
for _row, pvgate in enumerate(self.pv_gateway):
|
||||
|
||||
if not pvgate.notify_unison:
|
||||
@@ -1214,6 +1239,8 @@ class CAQTableWidget(QTableWidget):
|
||||
|
||||
#if timestamps the same - then skip
|
||||
_value = _pvd.value[0]
|
||||
if self.scale_factor != 1:
|
||||
_value = _value * self.scale_factor
|
||||
_value = pvgate.format_display_value(_value)
|
||||
|
||||
qtwi = QTableWidgetItem(str(_value)+ " ")
|
||||
@@ -1289,6 +1316,8 @@ class CAQTableWidget(QTableWidget):
|
||||
|
||||
self.item(_row, val_col_no).setBackground(
|
||||
QColor(pvgate.bg_readback))
|
||||
#self.item(_row, val_col_no).setBackground(
|
||||
# QColor('#aeae66'))
|
||||
if self.show_timestamp:
|
||||
self.item(_row, ts_col_no).setBackground(
|
||||
QColor(pvgate.bg_readback))
|
||||
@@ -1313,6 +1342,8 @@ class CAQTableWidget(QTableWidget):
|
||||
color_mode=None, show_units: bool = True, prefix: str = "",
|
||||
suffix: str = "", ts_res: str = "milli",
|
||||
init_column: bool = False, init_list: list = [],
|
||||
standby_column: bool = False, standby_list: list = [],
|
||||
standby_values: list = [], set_delay: float = 0.0,
|
||||
notify_freq_hz: int = 0, notify_unison: bool = True,
|
||||
precision: int = 0, scale_factor: float = 1,
|
||||
show_timestamp: bool = True, pv_list_show: list = None):
|
||||
@@ -1332,6 +1363,10 @@ class CAQTableWidget(QTableWidget):
|
||||
if init_column:
|
||||
self.columns_dict['Init'] = _column_dict_value
|
||||
_column_dict_value += 1
|
||||
|
||||
if standby_column:
|
||||
self.columns_dict['Standby'] = _column_dict_value
|
||||
_column_dict_value += 1
|
||||
|
||||
self.columns_dict['Value'] = _column_dict_value
|
||||
|
||||
@@ -1346,11 +1381,17 @@ class CAQTableWidget(QTableWidget):
|
||||
self.no_columns = _column_dict_value + 1
|
||||
|
||||
self.init_column = init_column
|
||||
|
||||
self.init_list = init_list
|
||||
if self.init_column and not self.init_list:
|
||||
self.init_list = pv_list
|
||||
|
||||
self.standby_column = standby_column
|
||||
self.standby_list = standby_list
|
||||
if self.standby_column and not self.standby_list:
|
||||
self.standby_list = pv_list
|
||||
self.standby_values = standby_values
|
||||
self.set_delay = set_delay
|
||||
|
||||
self.icount = 0
|
||||
self.notify_freq_hz = abs(notify_freq_hz)
|
||||
self.notify_freq_hz_default = self.notify_freq_hz
|
||||
@@ -1408,6 +1449,7 @@ class CAQTableWidget(QTableWidget):
|
||||
connect_triggers=False, notify_freq_hz=self.notify_freq_hz,
|
||||
notify_unison=self.notify_unison, precision=self.precision)
|
||||
|
||||
|
||||
self.pv_gateway[i].is_initialize_complete()
|
||||
self.pv_gateway[i].trigger_connect.connect(
|
||||
self.receive_connect_update)
|
||||
@@ -1434,6 +1476,7 @@ class CAQTableWidget(QTableWidget):
|
||||
self.timer.singleShot(0, self.widget_update)
|
||||
self.timer.start(self.notify_milliseconds)
|
||||
|
||||
self.reconnect_button = None
|
||||
self.configure_widget()
|
||||
|
||||
#Connect only deals with colours - only helps on reconnect
|
||||
@@ -1452,6 +1495,9 @@ class CAQTableWidget(QTableWidget):
|
||||
if init_column:
|
||||
self.update_init_values()
|
||||
|
||||
if standby_column:
|
||||
self.update_standby_values()
|
||||
|
||||
self.configure_context_menu()
|
||||
|
||||
|
||||
@@ -1473,7 +1519,106 @@ class CAQTableWidget(QTableWidget):
|
||||
QApplication.processEvents()
|
||||
|
||||
|
||||
|
||||
def set_standby_values(self, pv_list: list = []):
|
||||
if self.init_column:
|
||||
self.init_value_button.setEnabled(False)
|
||||
self.restore_value_button.setEnabled(False)
|
||||
|
||||
_text = self.standby_value_button.text()
|
||||
self.standby_value_button.setText("Downing")
|
||||
self.standby_value_button.setEnabled(False)
|
||||
|
||||
if self.reconnect_button is not None:
|
||||
self.reconnect_button.setEnabled(False)
|
||||
|
||||
|
||||
_set_values_dict = self.get_standby_values()
|
||||
|
||||
#return 1,2,3
|
||||
|
||||
if not pv_list:
|
||||
_pvs_to_set, _values_to_set = zip(*_set_values_dict.items())
|
||||
#zip returns tuples
|
||||
_pvs_to_set = list(_pvs_to_set)
|
||||
_values_to_set = list(_values_to_set)
|
||||
else:
|
||||
_pvs_to_set = []
|
||||
_values_to_set = []
|
||||
for pv in pv_list:
|
||||
if pv in _set_values_dict.keys():
|
||||
_pvs_to_set.append(pv)
|
||||
_values_to_set.append(_set_values_dict[pv])
|
||||
|
||||
#self.standby_value_button.setEnabled(False)
|
||||
#QApplication.processEvents(QEventLoop.AllEvents, 1.0)
|
||||
|
||||
if self.set_delay <= 0:
|
||||
status, status_list = self.cafe.setScalarList(_pvs_to_set,
|
||||
_values_to_set)
|
||||
else:
|
||||
status_list = [self.cyca.ICAFE_NORMAL] * len(_pvs_to_set)
|
||||
status = self.cyca.ICAFE_NORMAL
|
||||
for i, (pv, val) in enumerate(zip(_pvs_to_set, _values_to_set)):
|
||||
status_list[i] = self.cafe.set(pv, val)
|
||||
if status_list[i] != self.cyca.ICAFE_NORMAL:
|
||||
status = status_list[i]
|
||||
|
||||
##self.standby_value_button.setEnabled(False)
|
||||
##QApplication.processEvents(QEventLoop.AllEvents, 1.0)
|
||||
time.sleep(self.set_delay)
|
||||
##self.standby_value_button.setEnabled(False)
|
||||
#QApplication.sendPostedEvents()
|
||||
QApplication.processEvents(QEventLoop.AllEvents, 1.0)
|
||||
|
||||
if status != self.cyca.ICAFE_NORMAL:
|
||||
_mess = ("The following devices reported an error " +
|
||||
"in 'set' operation:")
|
||||
for i, status_value in enumerate(status_list):
|
||||
if status_value != self.cyca.ICAFE_NORMAL:
|
||||
_mess += ("\n" + _pvs_to_set[i] + " has status = " +
|
||||
str(status_value) + " " +
|
||||
self.cafe.getStatusCodeAsString(status_value)
|
||||
+ " " + self.cafe.getStatusInfo(status_value))
|
||||
qm = QMessageBox()
|
||||
qm.setText(_mess)
|
||||
#qm.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
|
||||
#qm.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
||||
#qm.setFixedWidth(800)
|
||||
##self.standby_value_button.setEnabled(False)
|
||||
##QApplication.sendPostedEvents()
|
||||
qm.exec()
|
||||
#QApplication.processEvents()
|
||||
|
||||
|
||||
if self.init_column:
|
||||
self.init_value_button.setEnabled(True)
|
||||
self.restore_value_button.setEnabled(True)
|
||||
|
||||
|
||||
self.standby_value_button.setText(_text)
|
||||
self.standby_value_button.setEnabled(True)
|
||||
if self.reconnect_button is not None:
|
||||
self.reconnect_button.setEnabled(True)
|
||||
|
||||
return status, status_list, _pvs_to_set
|
||||
|
||||
|
||||
def restore_init_values(self, pv_list: list = []):
|
||||
|
||||
_text = self.restore_value_button.text()
|
||||
self.restore_value_button.setText("Restoring")
|
||||
self.restore_value_button.setEnabled(False)
|
||||
|
||||
if self.init_column:
|
||||
self.init_value_button.setEnabled(False)
|
||||
|
||||
if self.standby_column:
|
||||
self.standby_value_button.setEnabled(False)
|
||||
|
||||
if self.reconnect_button is not None:
|
||||
self.reconnect_button.setEnabled(False)
|
||||
|
||||
_set_values_dict = self.get_init_values()
|
||||
|
||||
if not pv_list:
|
||||
@@ -1489,8 +1634,19 @@ class CAQTableWidget(QTableWidget):
|
||||
_pvs_to_set.append(pv)
|
||||
_values_to_set.append(_set_values_dict[pv])
|
||||
|
||||
status, status_list = self.cafe.setScalarList(_pvs_to_set,
|
||||
_values_to_set)
|
||||
|
||||
if self.set_delay <= 0:
|
||||
status, status_list = self.cafe.setScalarList(_pvs_to_set,
|
||||
_values_to_set)
|
||||
else:
|
||||
status_list = [self.cyca.ICAFE_NORMAL] * len(_pvs_to_set)
|
||||
status = self.cyca.ICAFE_NORMAL
|
||||
for i, (pv, val) in enumerate(zip(_pvs_to_set, _values_to_set)):
|
||||
status_list[i] = self.cafe.set(pv, val)
|
||||
if status_list[i] != self.cyca.ICAFE_NORMAL:
|
||||
status = status_list[i]
|
||||
time.sleep(self.set_delay)
|
||||
QApplication.processEvents(QEventLoop.AllEvents, 1.0)
|
||||
|
||||
if status != self.cyca.ICAFE_NORMAL:
|
||||
_mess = ("The following device(s) reported an error " +
|
||||
@@ -1503,12 +1659,23 @@ class CAQTableWidget(QTableWidget):
|
||||
" " + self.cafe.getStatusInfo(status_value))
|
||||
qm = QMessageBox()
|
||||
qm.setText(_mess)
|
||||
|
||||
|
||||
qm.exec()
|
||||
QApplication.processEvents()
|
||||
|
||||
self.init_value_button.setEnabled(True)
|
||||
if self.init_column:
|
||||
self.init_value_button.setEnabled(True)
|
||||
|
||||
self.restore_value_button.setText(_text)
|
||||
self.restore_value_button.setEnabled(True)
|
||||
|
||||
if self.standby_column:
|
||||
self.standby_value_button.setEnabled(True)
|
||||
|
||||
if self.reconnect_button is not None:
|
||||
self.reconnect_button.setEnabled(True)
|
||||
|
||||
return status, status_list, _pvs_to_set
|
||||
|
||||
def is_same_as_init_values(self):
|
||||
_init_values_dict = self.get_column_values(self.columns_dict['Init'])
|
||||
@@ -1551,6 +1718,8 @@ class CAQTableWidget(QTableWidget):
|
||||
|
||||
if _pvs[_row] in self.pv_list_show:
|
||||
_values_dict[self.pv_gateway[_row].pv_name] = _values[_row]
|
||||
else:
|
||||
_values_dict[_row] = _values[_row]
|
||||
|
||||
return _values_dict #_pvs_to_set, _values_to_set
|
||||
|
||||
@@ -1558,6 +1727,9 @@ class CAQTableWidget(QTableWidget):
|
||||
def get_init_values(self):
|
||||
return self.get_column_values(self.columns_dict['Init'])
|
||||
|
||||
def get_standby_values(self):
|
||||
return self.get_column_values(self.columns_dict['Standby'])
|
||||
|
||||
def get_init_values_previous(self):
|
||||
_set_values_dict = {}
|
||||
_start = 0
|
||||
@@ -1585,21 +1757,69 @@ class CAQTableWidget(QTableWidget):
|
||||
_set_values_dict[
|
||||
self.pv_gateway[_row].pv_name] = _values_to_set[_row]
|
||||
|
||||
|
||||
|
||||
return _set_values_dict
|
||||
|
||||
|
||||
def update_init_values(self):
|
||||
|
||||
def update_standby_values(self):
|
||||
_start = 0
|
||||
_end = len(self.pv_gateway)
|
||||
_end = len(self.standby_values)
|
||||
if 'Standby' in self.columns_dict:
|
||||
_column_no = self.columns_dict['Standby']
|
||||
else:
|
||||
return
|
||||
|
||||
for _row in range(_start, _end):
|
||||
_value = self.standby_values[_row]
|
||||
|
||||
if self.scale_factor != 1:
|
||||
_value = _value * self.scale_factor
|
||||
_value = self.pv_gateway[_row].format_display_value(_value)
|
||||
qtwi = QTableWidgetItem(str(_value)+ " ")
|
||||
_f = qtwi.font()
|
||||
_f.setPointSize(8)
|
||||
qtwi.setFont(_f)
|
||||
self.setItem(_row, _column_no, qtwi)
|
||||
self.item(_row, _column_no).setTextAlignment(Qt.AlignRight |
|
||||
Qt.AlignVCenter)
|
||||
|
||||
|
||||
def set_init_values(self, values):
|
||||
_start = 0
|
||||
_end = min(len(self.pv_gateway), len(values))
|
||||
|
||||
if 'Init' in self.columns_dict:
|
||||
_column_no = self.columns_dict['Init']
|
||||
else:
|
||||
return
|
||||
|
||||
for _row in range(_start, _end):
|
||||
_value = self.pv_gateway[_row].format_display_value(values[_row])
|
||||
qtwi = QTableWidgetItem(str(_value)+ " ")
|
||||
_f = qtwi.font()
|
||||
_f.setPointSize(8)
|
||||
qtwi.setFont(_f)
|
||||
self.setItem(_row, _column_no, qtwi)
|
||||
self.item(_row, _column_no).setTextAlignment(Qt.AlignRight |
|
||||
Qt.AlignVCenter)
|
||||
|
||||
|
||||
def update_init_values(self):
|
||||
_start = 0
|
||||
_end = len(self.pv_gateway)
|
||||
|
||||
if 'Init' in self.columns_dict:
|
||||
_column_no = self.columns_dict['Init']
|
||||
else:
|
||||
return
|
||||
|
||||
for _row in range(_start, _end):
|
||||
|
||||
|
||||
_handle = self.pv_gateway[_row].handle
|
||||
_value = self.pv_gateway[_row].cafe.getCache(_handle)
|
||||
|
||||
|
||||
if _value is not None:
|
||||
if self.scale_factor != 1:
|
||||
_value = _value * self.scale_factor
|
||||
@@ -1609,10 +1829,11 @@ class CAQTableWidget(QTableWidget):
|
||||
_f = qtwi.font()
|
||||
_f.setPointSize(8)
|
||||
qtwi.setFont(_f)
|
||||
self.setItem(_row, 1, qtwi)
|
||||
self.setItem(_row, _column_no, qtwi)
|
||||
|
||||
self.item(_row, _column_no).setTextAlignment(Qt.AlignRight |
|
||||
Qt.AlignVCenter)
|
||||
|
||||
|
||||
|
||||
def configure_widget(self):
|
||||
|
||||
@@ -1621,6 +1842,9 @@ class CAQTableWidget(QTableWidget):
|
||||
_column_width_timestamp = 210
|
||||
_column_width_checkbox = 22
|
||||
|
||||
item_font = QTableWidgetItem().font()
|
||||
item_font.setPixelSize(13)
|
||||
|
||||
self.setRowCount(len(self.pv_gateway)+1)
|
||||
self.setColumnCount(self.no_columns)
|
||||
self.setEditTriggers(QAbstractItemView.NoEditTriggers)
|
||||
@@ -1648,7 +1872,6 @@ class CAQTableWidget(QTableWidget):
|
||||
f = qtwt.font()
|
||||
f.setPointSize(8)
|
||||
qtwt.setFont(f)
|
||||
|
||||
self.setItem(i, _pv_column, qtwt)
|
||||
self.item(i, _pv_column).setTextAlignment(Qt.AlignHCenter |
|
||||
Qt.AlignVCenter)
|
||||
@@ -1672,41 +1895,70 @@ class CAQTableWidget(QTableWidget):
|
||||
|
||||
if self.init_column:
|
||||
self.init_widget = QWidget()
|
||||
_init_layout = QHBoxLayout(self.init_widget)
|
||||
self.init_layout = QHBoxLayout(self.init_widget)
|
||||
self.init_value_button = QPushButton()
|
||||
self.init_value_button.setText("Update")
|
||||
_f = self.init_value_button.font()
|
||||
_f.setPointSize(8)
|
||||
self.init_value_button.setFont(_f)
|
||||
f = self.init_value_button.font()
|
||||
f.setPointSize(8)
|
||||
self.init_value_button.setFont(f)
|
||||
self.init_value_button.setFixedWidth(64)
|
||||
self.init_value_button.clicked.connect(self.update_init_values)
|
||||
self.init_value_button.setToolTip(
|
||||
("Stores initial, pre-measurement value. Update is also " +
|
||||
"typically executed automatically before analysis procedure."))
|
||||
_init_layout.addWidget(self.init_value_button)
|
||||
_init_layout.setAlignment(Qt.AlignCenter)
|
||||
_init_layout.setContentsMargins(1, 1, 1, 0) #Required
|
||||
self.init_widget.setLayout(_init_layout)
|
||||
self.setCellWidget(len(self.pv_gateway), 1, self.init_widget)
|
||||
self.init_layout.addWidget(self.init_value_button)
|
||||
self.init_layout.setAlignment(Qt.AlignCenter)
|
||||
self.init_layout.setContentsMargins(1, 1, 1, 0) #Required
|
||||
self.init_widget.setLayout(self.init_layout)
|
||||
|
||||
if 'PV' in self.columns_dict:
|
||||
self.setCellWidget(len(self.pv_gateway), 0, self.init_widget)
|
||||
else:
|
||||
self.setCellWidget(len(self.pv_gateway), self.columns_dict['Init'], self.init_widget)
|
||||
|
||||
_restore_widget = QWidget()
|
||||
_restore_layout = QHBoxLayout(_restore_widget)
|
||||
self.restore_widget = QWidget()
|
||||
self.restore_layout = QHBoxLayout(self.restore_widget)
|
||||
self.restore_value_button = QPushButton()
|
||||
self.restore_value_button.setStyleSheet(
|
||||
"QPushButton{background-color: rgb(212, 219, 157);}")
|
||||
self.restore_value_button.setText("Restore")
|
||||
_f = self.restore_value_button.font()
|
||||
_f.setPointSize(8)
|
||||
self.restore_value_button.setFont(_f)
|
||||
f = self.restore_value_button.font()
|
||||
f.setPointSize(8)
|
||||
self.restore_value_button.setFont(f)
|
||||
self.restore_value_button.setFixedWidth(80)
|
||||
self.restore_value_button.clicked.connect(self.restore_init_values)
|
||||
self.restore_value_button.setToolTip(
|
||||
("Restore devices to their pre-measurement values"))
|
||||
_restore_layout.addWidget(self.restore_value_button)
|
||||
_restore_layout.setAlignment(Qt.AlignCenter)
|
||||
_restore_layout.setContentsMargins(1, 1, 0, 0)
|
||||
_restore_widget.setLayout(_restore_layout)
|
||||
self.setCellWidget(len(self.pv_gateway), 2, _restore_widget)
|
||||
self.restore_layout.addWidget(self.restore_value_button)
|
||||
self.restore_layout.setAlignment(Qt.AlignCenter)
|
||||
self.restore_layout.setContentsMargins(1, 1, 0, 0)
|
||||
self.restore_widget.setLayout(self.restore_layout)
|
||||
if 'PV' in self.columns_dict:
|
||||
self.setCellWidget(len(self.pv_gateway),
|
||||
self.columns_dict['Init'],
|
||||
self.restore_widget)
|
||||
|
||||
if self.standby_column:
|
||||
|
||||
_standby_widget = QWidget()
|
||||
_standby_layout = QHBoxLayout(_standby_widget)
|
||||
self.standby_value_button = QPushButton()
|
||||
self.standby_value_button.setStyleSheet(
|
||||
"QPushButton{background-color: rgb(212, 219, 157);}")
|
||||
self.standby_value_button.setText("Standby")
|
||||
f = self.standby_value_button.font()
|
||||
f.setPointSize(8)
|
||||
self.standby_value_button.setFont(f)
|
||||
self.standby_value_button.setFixedWidth(80)
|
||||
self.standby_value_button.clicked.connect(self.set_standby_values)
|
||||
self.standby_value_button.setToolTip(
|
||||
("Set devices to their pre-set standby values"))
|
||||
_standby_layout.addWidget(self.standby_value_button)
|
||||
_standby_layout.setAlignment(Qt.AlignCenter)
|
||||
_standby_layout.setContentsMargins(1, 1, 0, 0)
|
||||
_standby_widget.setLayout(_standby_layout)
|
||||
self.setCellWidget(len(self.pv_gateway), self.columns_dict['Standby'], _standby_widget)
|
||||
|
||||
|
||||
#Do not display no for last row (Reconnect button)
|
||||
_row_digit_last_cell = QTableWidgetItem(str(""))
|
||||
@@ -1720,16 +1972,16 @@ class CAQTableWidget(QTableWidget):
|
||||
f = self.reconnect_button.font()
|
||||
|
||||
if 'Timestamp' in self.columns_dict.keys():
|
||||
f.setPointSize(8)
|
||||
f.setPixelSize(11) #previous 13
|
||||
self.reconnect_button.setFixedWidth(100)
|
||||
else:
|
||||
f.setPointSize(7) #6
|
||||
f.setPixelSize(11) #6
|
||||
self.reconnect_button.setFixedWidth(66) #58
|
||||
|
||||
self.reconnect_button.setFont(f)
|
||||
|
||||
self.reconnect_button.setText("Reconnect")
|
||||
|
||||
self.reconnect_button.setToolTip("Reconnect selected/checked channels")
|
||||
_layout = QHBoxLayout(_qwb)
|
||||
_layout.addWidget(self.reconnect_button)
|
||||
_layout.setAlignment(Qt.AlignCenter)
|
||||
@@ -1747,22 +1999,43 @@ class CAQTableWidget(QTableWidget):
|
||||
self.cb_item_all)
|
||||
|
||||
|
||||
|
||||
if 'PV' in self.columns_dict.keys():
|
||||
header_item = QTableWidgetItem("Process Variable")
|
||||
f = header_item.font()
|
||||
f.setPixelSize(13)
|
||||
header_item.setFont(f)
|
||||
self.setHorizontalHeaderItem(self.columns_dict['PV'], header_item)
|
||||
|
||||
if 'Init' in self.columns_dict.keys():
|
||||
self.setHorizontalHeaderItem(self.columns_dict['Init'],
|
||||
QTableWidgetItem("Initial Value"))
|
||||
|
||||
self.setHorizontalHeaderItem(self.columns_dict['Value'],
|
||||
QTableWidgetItem("Value"))
|
||||
header_item = QTableWidgetItem("Initial Value")
|
||||
f = header_item.font()
|
||||
f.setPixelSize(13)
|
||||
header_item.setFont(f)
|
||||
self.setHorizontalHeaderItem(self.columns_dict['Init'], header_item)
|
||||
|
||||
header_item = QTableWidgetItem("Value")
|
||||
f = header_item.font()
|
||||
f.setPixelSize(13)
|
||||
header_item.setFont(f)
|
||||
self.setHorizontalHeaderItem(self.columns_dict['Value'], header_item)
|
||||
|
||||
|
||||
if 'Timestamp' in self.columns_dict.keys():
|
||||
header_item = QTableWidgetItem("Timestamp")
|
||||
f = header_item.font()
|
||||
f.setPixelSize(13)
|
||||
header_item.setFont(f)
|
||||
self.setHorizontalHeaderItem(self.columns_dict['Timestamp'],
|
||||
QTableWidgetItem("Timestamp"))
|
||||
self.setHorizontalHeaderItem(self.columns_dict['Reconnect'],
|
||||
QTableWidgetItem("R"))
|
||||
header_item)
|
||||
|
||||
header_item = QTableWidgetItem("R")
|
||||
f = header_item.font()
|
||||
f.setPixelSize(13)
|
||||
header_item.setFont(f)
|
||||
self.setHorizontalHeaderItem(self.columns_dict['Reconnect'],
|
||||
header_item)
|
||||
|
||||
self.setFocusPolicy(Qt.NoFocus)
|
||||
self.setEditTriggers(QAbstractItemView.NoEditTriggers)
|
||||
self.setSelectionMode(QAbstractItemView.NoSelection)
|
||||
@@ -1826,15 +2099,24 @@ class CAQTableWidget(QTableWidget):
|
||||
if self.scale_factor != 1:
|
||||
value = value * self.scale_factor
|
||||
_value = self.pv_gateway[_row].format_display_value(value)
|
||||
|
||||
#if 'QMD10' in self.pv_gateway[_row].pv_name:
|
||||
# print(_value + " from widgets.py" + self.pv_gateway[_row].pv_name)
|
||||
|
||||
|
||||
qtwi = QTableWidgetItem(str(_value) + " ")
|
||||
f = qtwi.font()
|
||||
f.setPointSize(8)
|
||||
qtwi.setFont(f)
|
||||
qtwi.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable)
|
||||
#qtwi.setEditTriggers(QAbstractItemView.AllEditTriggers)
|
||||
self.setItem(_row, self.columns_dict['Value'], qtwi)
|
||||
#self.item(_row, self.columns_dict['Value']).setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable)
|
||||
#self.item(_row, self.columns_dict['Value']).setEditTriggers(QAbstractItemView.AllEditTriggers)
|
||||
self.item(_row, self.columns_dict['Value']).setTextAlignment(
|
||||
Qt.AlignRight | Qt.AlignVCenter)
|
||||
|
||||
|
||||
|
||||
if 'Timestamp' in self.columns_dict.keys():
|
||||
_handle = self.pv_gateway[_row].handle
|
||||
_pvd = self.pv_gateway[_row].cafe.getPVCache(_handle)
|
||||
@@ -1870,6 +2152,8 @@ class CAQTableWidget(QTableWidget):
|
||||
|
||||
_prop = self.pv_gateway[_row].qt_dynamic_property_get()
|
||||
|
||||
|
||||
|
||||
if _prop == self.pv_gateway[_row].READBACK_ALARM:
|
||||
|
||||
if alarm_severity == self.pv_gateway[_row].cyca.SEV_MAJOR:
|
||||
@@ -1914,6 +2198,10 @@ class CAQTableWidget(QTableWidget):
|
||||
elif _prop == self.pv_gateway[_row].READBACK_STATIC:
|
||||
self.item(_row, self.columns_dict['Value']).setBackground(
|
||||
QColor(self.pv_gateway[_row].bg_readback))
|
||||
#self.item(_row, self.columns_dict['Value']).setBackground(
|
||||
# QColor("#ffffe1"))
|
||||
#self.item(_row, self.columns_dict['Value']).setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable)
|
||||
|
||||
if 'Timestamp' in self.columns_dict.keys():
|
||||
self.item(_row, self.columns_dict['Timestamp']).setBackground(
|
||||
QColor(self.pv_gateway[_row].bg_readback))
|
||||
|
||||
3142
pvwidgets.py-
3142
pvwidgets.py-
File diff suppressed because it is too large
Load Diff
3461
pvwidgets.py:2.9
3461
pvwidgets.py:2.9
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user