qtab composite widget update

This commit is contained in:
2023-02-24 07:26:49 +01:00
parent 9c2c5d7d37
commit cb7a74d189

View File

@@ -10,7 +10,9 @@ from matplotlib.backends.backend_qt5agg import (
FigureCanvasQTAgg, NavigationToolbar2QT as NavigationToolbar)
from qtpy.QtCore import QSize, Qt, Slot
from qtpy.QtGui import QColor, QFont, QFontMetricsF, QIcon, QPainter, QPixmap
from qtpy.QtGui import (
QColor, QDoubleValidator, QFont, QFontMetricsF, QIcon, QIntValidator,
QPainter, QPixmap)
from qtpy.QtWidgets import (
QCheckBox, QComboBox, QDoubleSpinBox, QFrame, QGridLayout, QGroupBox,
QHBoxLayout, QLabel, QLineEdit, QPushButton, QRadioButton, QSpinBox,
@@ -1121,32 +1123,206 @@ class GUIFrame(QWidget):
self.nav[i] = None
def prepare_qlineedit(self, line, value):
def prepare_qlineread(self, line, value):
line.setObjectName("Read")
line.setFixedHeight(24)
line.setText(str(value))
line.setAlignment(Qt.AlignRight | Qt.AlignBottom)
line.setStyleSheet("QLabel{text-align: right}")
fm = QFontMetricsF(line.font())
param_width = fm.maxWidth() * (len(str(value))*0.5) + 20
line.setMaximumWidth(param_width)
def prepare_qlineedit(self, line, value, link, title, key):
has_min = False
has_max = False
is_float = False
is_int = False
no_decimals = 0
try:
min_val = self.settings.data[link][title][key]["data"]["min"]
has_min = True
if isinstance(min_val, float):
is_float = True
d = abs(Decimal(str(min_val)).as_tuple().exponent)
no_decimals = max(no_decimals, d)
elif isinstance(min_val, int):
is_int = True
except KeyError:
pass
try:
max_val = self.settings.data[link][title][key]["data"]["max"]
has_max = True
if isinstance(max_val, float):
is_float = True
d = abs(Decimal(str(max_val)).as_tuple().exponent)
no_decimals = max(no_decimals, d)
elif isinstance(max_val, int):
is_int = True
except KeyError:
pass
validator = None
#QDoubleValidate only controls the number of digits
if is_float:
validator = QDoubleValidator()
validator.setNotation(QDoubleValidator.StandardNotation)
validator.setDecimals(no_decimals)
elif is_int:
validator = QIntValidator()
if validator:
validator_str = "Valid range "
if has_min:
validator.setBottom(min_val)
validator_str += "from {} ".format(min_val)
if has_max:
validator.setTop(max_val)
validator_str += "to {}".format(max_val)
line.setToolTip(validator_str)
line.setValidator(validator)
line.setObjectName("Write")
line.setFixedHeight(24)
line.setText(str(value))
fm = QFontMetricsF(line.font())
param_width = fm.width(str(value))
extra_width = 22 if len(str(value)) < 16 else 26
line.setFixedWidth(param_width + extra_width)
#param_width = fm.width(str(value))
#extra_width = 22 if len(str(value)) < 16 else 26
#line.setFixedWidth(param_width + extra_width)
param_width = fm.maxWidth() * (len(str(value))*0.5) + 20
line.setMaximumWidth(param_width)
return line
def prepare_qspinbox(self, line, value, link, title, key):
print(link, title, key)
min_val = self.settings.data[link][title][key]["data"]["min"]
max_val = self.settings.data[link][title][key]["data"]["max"]
step = self.settings.data[link][title][key]["data"]["step"]
step = self.settings.data[link][title][key]["data"]["step"]
line.setObjectName("Write")
line.setFixedHeight(24)
line.setRange(min_val, max_val)
line.setSingleStep(step)
line.setValue(value)
line.setAlignment(Qt.AlignRight)
line.setAlignment(Qt.AlignRight) #required
fm = QFontMetricsF(line.font())
param_width = fm.maxWidth() * len(str(max_val))
print("param_width", param_width, flush=True)
param_width = fm.maxWidth() * (len(str(max_val)) + 0.2)
line.setMaximumWidth(param_width)
return line
def prepare_qdoublespinbox(self, line, value, link, title, key):
min_val = self.settings.data[link][title][key]["data"]["min"]
max_val = self.settings.data[link][title][key]["data"]["max"]
step = self.settings.data[link][title][key]["data"]["step"]
line.setObjectName("Write")
line.setFixedHeight(24)
decimal = Decimal(str(step))
line.setDecimals(abs(decimal.as_tuple().exponent)) #precision
line.setRange(min_val, max_val)
line.setSingleStep(step)
line.setValue(value)
line.setAlignment(Qt.AlignRight) #required
fm = QFontMetricsF(line.font())
param_width = fm.maxWidth() * (len(str(max_val))) # + len(str(step)))
line.setMaximumWidth(param_width)
return line
def prepare_qcombobox(self, line, value, link, title, key):
line.clear()
line.addItems(value)
line.setFixedHeight(26)
line.setObjectName("Write")
value_for_width = max(value, key=len)
fm = QFontMetricsF(line.font())
param_width = fm.maxWidth() * (len(str(value_for_width)) * 0.5) # + len(str(step)))
line.setFixedWidth(param_width)
return line
def prepare_qcheckbox(self, line, value, link, title, key):
line.setChecked(Qt.Checked if value else Qt.Unchecked)
line.setMaximumWidth(320)
line.setMinimumWidth(100)
line.setFixedHeight(28)
try:
orientation = self.settings.data[link][title][key]["data"][
"orientation"]
orientation = Qt.RightToLeft if "RightToLeft" in orientation \
else Qt.LeftToRight
line.setLayoutDirection(orientation)
except KeyError as ex:
print(ex, flush=True)
pass
return line
def prepare_qradiobutton(self, value, link, title, key):
widget = QWidget()
layout = QGridLayout()
layout.setContentsMargins(5, 0, 5, 20)
widget.setMaximumWidth(len(value)*100)
target_list = value
color_list = ["#894961", "teal", "darkblue"]
width_list = [70, 70, 70]
self.radiobutton = [None] * len(target_list)
for i, name in enumerate(target_list):
self.radiobutton[i] = QRadioButton(name)
full_width = len(target_list) + 1
layout.addWidget(QHLine(), 0, 0, 1, full_width)
layout.addWidget(QLabel(
self.settings.data[link][title][key]['data']['text']), 1, 0, 1,
full_width, Qt.AlignCenter)
for i, (radio, target, color, width) in enumerate(
zip(self.radiobutton, target_list, color_list, width_list)):
radio.setFont(self.font_pts10)
radio.setStyleSheet("color : {0};".format(color))
radio.val = target
radio.title = title
radio.key = key
layout.addWidget(radio, 2, i, 1, 1, Qt.AlignCenter)
layout.addWidget(QHLine(), 3, 0, 1, layout.columnCount())
layout.setSpacing(0)
widget.setLayout(layout)
return widget
'''
line.setContentsMargins(0, 0, 0, 0)
rblist = line.findChildren(QRadioButton)
for rb in rblist:
rb.toggled.connect(on_radiobutton_change)
wgt_grid.addWidget(line, irow, 0, 1, 4, Qt.AlignLeft)
_idx=0
try:
if key in self.settings.data["Expert"].keys():
top_key = "Expert"
elif key in self.settings.data["Parameters"].keys():
top_key = "Parameters"
_choice =self.settings.data[top_key][key]['data']['default']
_values = self.settings.data[top_key][key]['data']['value']
if isinstance(_choice, (str, bytes)):
_idx = _values.index(_choice)
elif isinstance(_choice, int):
_idx = _choice if _choice < len(_values) else 0
except KeyError:
pass
rblist[_idx].setChecked(True)
rblist[_idx].toggled.emit(True)
return line
'''
def qtab_wgt(self, key, irow, wgt_grid):
@@ -1160,81 +1336,164 @@ class GUIFrame(QWidget):
line.key = inner_key
line.val = value
def check_cb(new_value):
sender= self.sender()
self.parent.input_parameters[sender.title][sender.key] = new_value
def line_cb(new_value):
sender= self.sender()
self.parent.input_parameters[sender.title][sender.key] = new_value
def on_radiobutton_change(new_value):
sender = self.sender()
#print("rb callback ", new_value, sender.isChecked(), sender.val, flush=True)
if sender.isChecked():
self.parent.input_parameters[sender.title][sender.key] = sender.val
def on_tab_change(new_idx):
sender_tab = self.sender().qtab_widget_dict[new_idx].title
meas_line.setText(sender_tab)
try:
_color = self.settings.data[top_key][key]["data"]["color"][new_idx]
_color = self.settings.data[top_key][key]["data"]["color"][
new_idx]
except KeyError as ex:
_color = "black"
except IndexError as ex:
_color = "black"
meas_line.setStyleSheet("color: {0}".format(_color))
self.sender().tabBar().setTabTextColor(new_idx, QColor(_color))
for i in range (0, self.sender().count()):
if i == new_idx:
self.sender().tabBar().setTabTextColor(new_idx,
QColor(_color))
else:
self.sender().tabBar().setTabTextColor(i, QColor("black"))
self.parent.input_parameters[key] = sender_tab
qtab_widget = QTabWidget()
qtab_widget_dict = {}
itab = 0
longest_title = "short"
link = self.settings.data[top_key][key]["data"]["link"]
for title, tab in self.settings.data[link].items():
lo = QGridLayout()
qw = QWidget()
_irow = 0
_irowspan = 1
tab_height = 0
if len(title) > len(longest_title):
longest_title = title
self.parent.input_parameters[title] = {}
for inner_key, param in tab.items():
tab_height +=32
wgt_type = param["data"]["widget"]
text = param["data"]["text"]
value = param["data"]["value"]
label = QLabel(text)
label.setFixedHeight(24)
label.setFont(self.font_pts10)
label.setContentsMargins(5, 0, 0, 0)
if "value" in param["data"]:
value = param["data"]["value"]
elif "link" in param["data"]:
link_list = param["data"]["link"]
print("ll", link_list, flush=True)
if len(link_list) == 1:
value = self.settings.data[link_list[0]]
print("values", value, flush=True)
else:
bottom_leaf = self.settings.data[link_list[0]]
for link_item in link_list[1:]:
bottom_leaf = bottom_leaf[link_item]
value = bottom_leaf
label = None
def add_label():
label = QLabel(text)
label.setFixedHeight(24)
label.setFont(self.font_pts10)
label.setContentsMargins(5, 0, 0, 0)
return label
if "QSpinBox" in wgt_type:
line = QSpinBox()
label = add_label()
emboss()
print("top key", top_key, inner_key, flush=True)
self.prepare_qspinbox(line, value, link, title, inner_key)
line.valueChanged.connect(line_cb)
line.valueChanged.emit(value)
elif "QDoubleSpinBox" in wgt_type:
line = QDoubleSpinBox()
label = add_label()
emboss()
self.prepare_qdoublespinbox(line, value, link, title,
inner_key)
line.valueChanged.connect(line_cb)
line.valueChanged.emit(value)
elif "QLineEdit" in wgt_type:
line = QLineEdit()
label = add_label()
emboss()
self.prepare_qlineedit(line, value)
self.prepare_qlineedit(line, value, link, title, inner_key)
line.textEdited.connect(line_cb)
line.textEdited.emit(str(value))
elif "QLineRead" in wgt_type:
line = QLineEdit()
label = add_label()
emboss()
self.prepare_qlineread(line, value)
line.textEdited.connect(line_cb)
line.textEdited.emit(str(value))
elif "QCheckBox" in wgt_type:
line = QCheckBox(text)
emboss()
self.prepare_qcheckbox(line, value, link, title, inner_key)
line.stateChanged.connect(check_cb)
line.stateChanged.emit(bool(value))
elif "QComboBox" in wgt_type:
line = QComboBox()
label = add_label()
emboss()
self.prepare_qcombobox(line, value, link, title, inner_key)
line.currentTextChanged.connect(line_cb)
line.setCurrentIndex(0)
line.currentTextChanged.emit(value[0])
elif "QRadioButton" in wgt_type:
tab_height += 32
_irowspan = 2
line = self.prepare_qradiobutton(value, link, title,
inner_key)
#emboss()
rblist = line.findChildren(QRadioButton)
for rb in rblist:
rb.toggled.connect(on_radiobutton_change)
if "startIdx" in param["data"]:
start_idx = param["data"]["startIdx"]
else:
start_idx = 0
rblist[start_idx].setChecked(True)
rblist[start_idx].toggled.emit(True)
lo.addWidget(label, _irow, 0, 1, 1, Qt.AlignLeft | Qt.AlignVCenter)
lo.addWidget(line, _irow, 1, 1, 4, Qt.AlignLeft | Qt.AlignVCenter)
icol = 0
icolspan = 3
if label:
lo.addWidget(label, _irow, icol, _irowspan, 1,
Qt.AlignLeft | Qt.AlignVCenter)
icol += 1
lo.addWidget(line, _irow, icol, _irowspan, icolspan,
Qt.AlignLeft | Qt.AlignVCenter)
#print(title, tab)
#print(key, line, icolumn, wgt_type, text, flush=True)
_irow += 1
qw.setLayout(lo)
qw.setLayout(lo)
qw.setFixedHeight(tab_height)
qtab_widget_dict[itab] = qw
qtab_widget_dict[itab].title = title
qtab_widget.addTab(qtab_widget_dict[itab], title)
itab += 1
qtab_widget.qtab_widget_dict = qtab_widget_dict
meas_label = QLabel(text)
meas_label.setFixedHeight(24)
meas_label.setFont(self.font_pts10)
@@ -1244,10 +1503,11 @@ class GUIFrame(QWidget):
meas_line.setObjectName("Read")
fm = QFontMetricsF(meas_line.font())
param_width = fm.width(longest_title)
extra_width = 22 if len(str(value)) < 15 else 28
meas_line.setFixedWidth(param_width + extra_width)
#param_width = fm.width(longest_title)
#extra_width = 22 if len(str(value)) < 15 else 28
#meas_line.setFixedWidth(param_width + extra_width)
param_width = fm.maxWidth() * len(longest_title)
meas_line.setMaximumWidth(param_width*0.5)
qtab_widget.setContentsMargins(0, 40, 0, 0)
qtab_widget.currentChanged.connect(on_tab_change)
@@ -1343,16 +1603,12 @@ class GUIFrame(QWidget):
pv_local = pv
monitor_pv = None
def cb_pv_selector(value):
value_str = radio_buddy_text_dict[self.sender()].text()
#print("cb_pv_selector", value_str)
#Find which group the radio button belongs to:
#Find which stack the group belongs to:
#Set this to the current stack?
for k, v in self.stack_radiolist_dict.items():
if self.sender() in v:
#get groupbox from key
@@ -1425,7 +1681,7 @@ class GUIFrame(QWidget):
monitor_pv = CAQLabel(self, pv_name=pv, monitor_callback=mon_cb,
show_units=True)
monitor_pv.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
monitor_pv.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
monitor_pv.setFont(self.font_pts10)
monitor_pv.setFixedHeight(self.widget_height)
monitor_pv.setFixedWidth(122)
@@ -1443,8 +1699,6 @@ class GUIFrame(QWidget):
if init_value is not None:
val = read_pv.format_display_value(init_value)
#else:
# val = 0.0
read_pv.setText(str(val))
read_pv.setFixedHeight(self.widget_height)
read_pv.setFixedWidth(122)
@@ -1887,8 +2141,8 @@ class GUIFrame(QWidget):
else:
wgt_list = ["QCheckBox", "QComboBox", "QDoubleSpinBox", "QFrame",
"QHLine", "QLabel", "QLineEdit", "QLineRead",
"QRadioButton", "QSpinBox", "QPhaseStackedWidget",
"QEnergyStackedWidget"]
"QRadioButton", "QSpinBox", "QTabWidget",
"QPhaseStackedWidget", "QEnergyStackedWidget"]
print("Widget {0} is not Supported".format(buddy))
print("Supported widgets are: {0}".format(wgt_list))
pass