qtab composite widget update
This commit is contained in:
340
guiframe.py
340
guiframe.py
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user