forked from M-Labs/artiq
1
0
Fork 0

gui.applets: add EntryArea

This commit is contained in:
Simon Renblad 2023-09-13 11:41:26 +08:00 committed by Sébastien Bourdeauducq
parent 13271cea64
commit 4f3e58db52
1 changed files with 164 additions and 1 deletions

View File

@ -14,11 +14,174 @@ from sipyco.pipe_ipc import AsyncioParentComm
from sipyco.logging_tools import LogParser from sipyco.logging_tools import LogParser
from sipyco import pyon from sipyco import pyon
from artiq.gui.tools import QDockWidgetCloseDetect, LayoutWidget from artiq.gui.entries import procdesc_to_entry
from artiq.gui.tools import (QDockWidgetCloseDetect, LayoutWidget,
WheelFilter)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class EntryArea(QtWidgets.QTreeWidget):
def __init__(self):
QtWidgets.QTreeWidget.__init__(self)
self.setColumnCount(3)
self.header().setStretchLastSection(False)
if hasattr(self.header(), "setSectionResizeMode"):
set_resize_mode = self.header().setSectionResizeMode
else:
set_resize_mode = self.header().setResizeMode
set_resize_mode(0, QtWidgets.QHeaderView.ResizeToContents)
set_resize_mode(1, QtWidgets.QHeaderView.Stretch)
self.header().setVisible(False)
self.setSelectionMode(self.NoSelection)
self.setHorizontalScrollMode(self.ScrollPerPixel)
self.setVerticalScrollMode(self.ScrollPerPixel)
self.setStyleSheet("QTreeWidget {background: " +
self.palette().midlight().color().name() + " ;}")
self.viewport().installEventFilter(WheelFilter(self.viewport(), True))
self._groups = dict()
self._arg_to_widgets = dict()
self._arguments = dict()
self.gradient = QtGui.QLinearGradient(
0, 0, 0, QtGui.QFontMetrics(self.font()).lineSpacing()*2.5)
self.gradient.setColorAt(0, self.palette().base().color())
self.gradient.setColorAt(1, self.palette().midlight().color())
reset_all_button = QtWidgets.QPushButton("Restore defaults")
reset_all_button.setToolTip("Reset all to default values")
reset_all_button.setIcon(
QtWidgets.QApplication.style().standardIcon(
QtWidgets.QStyle.SP_BrowserReload))
reset_all_button.clicked.connect(self.reset_all)
buttons = LayoutWidget()
buttons.layout.setColumnStretch(0, 1)
buttons.layout.setColumnStretch(1, 0)
buttons.layout.setColumnStretch(2, 1)
buttons.addWidget(reset_all_button, 0, 1)
self.bottom_item = QtWidgets.QTreeWidgetItem()
self.addTopLevelItem(self.bottom_item)
self.setItemWidget(self.bottom_item, 1, buttons)
self.bottom_item.setHidden(True)
def setattr_argument(self, name, proc, group=None, tooltip=None):
argument = dict()
desc = proc.describe()
argument["desc"] = desc
argument["group"] = group
argument["tooltip"] = tooltip
self._arguments[name] = argument
widgets = dict()
self._arg_to_widgets[name] = widgets
entry_class = procdesc_to_entry(argument["desc"])
argument["state"] = entry_class.default_state(argument["desc"])
entry = entry_class(argument)
widget_item = QtWidgets.QTreeWidgetItem([name])
if argument["tooltip"]:
widget_item.setToolTip(0, argument["tooltip"])
widgets["entry"] = entry
widgets["widget_item"] = widget_item
if len(self._arguments) > 1:
self.bottom_item.setHidden(False)
for col in range(3):
widget_item.setBackground(col, self.gradient)
font = widget_item.font(0)
font.setBold(True)
widget_item.setFont(0, font)
if argument["group"] is None:
self.insertTopLevelItem(self.indexFromItem(self.bottom_item).row(), widget_item)
else:
self._get_group(argument["group"]).addChild(widget_item)
self.bottom_item.setHidden(False)
fix_layout = LayoutWidget()
widgets["fix_layout"] = fix_layout
fix_layout.addWidget(entry)
self.setItemWidget(widget_item, 1, fix_layout)
reset_value = QtWidgets.QToolButton()
reset_value.setToolTip("Reset to default value")
reset_value.setIcon(
QtWidgets.QApplication.style().standardIcon(
QtWidgets.QStyle.SP_BrowserReload))
reset_value.clicked.connect(partial(self.reset_value, name))
tool_buttons = LayoutWidget()
tool_buttons.addWidget(reset_value, 0)
self.setItemWidget(widget_item, 2, tool_buttons)
def _get_group(self, name):
if name in self._groups:
return self._groups[name]
group = QtWidgets.QTreeWidgetItem([name])
for col in range(3):
group.setBackground(col, self.palette().mid())
group.setForeground(col, self.palette().brightText())
font = group.font(col)
font.setBold(True)
group.setFont(col, font)
self.insertTopLevelItem(self.indexFromItem(self.bottom_item).row(), group)
self._groups[name] = group
return group
def __getattr__(self, name):
return self.get_value(name)
def get_value(self, name):
entry = self._arg_to_widgets[name]["entry"]
argument = self._arguments[name]
return entry.state_to_value(argument["state"])
def set_value(self, name, value):
ty = self._arguments[name]["desc"]["ty"]
if ty == "Scannable":
desc = value.describe()
self._arguments[name]["state"][desc["ty"]] = desc
self._arguments[name]["state"]["selected"] = desc["ty"]
else:
self._arguments[name]["state"] = value
self.update_value(name)
def get_values(self):
d = dict()
for name in self._arguments.keys():
d[name] = self.get_value(name)
return d
def set_values(self, values):
for name, value in values.items():
self.set_value(name, value)
def update_value(self, name):
widgets = self._arg_to_widgets[name]
argument = self._arguments[name]
# Qt needs a setItemWidget() to handle layout correctly,
# simply replacing the entry inside the LayoutWidget
# results in a bug.
widgets["entry"].deleteLater()
widgets["entry"] = procdesc_to_entry(argument["desc"])(argument)
widgets["fix_layout"].deleteLater()
widgets["fix_layout"] = LayoutWidget()
widgets["fix_layout"].addWidget(widgets["entry"])
self.setItemWidget(widgets["widget_item"], 1, widgets["fix_layout"])
self.updateGeometries()
def reset_value(self, name):
procdesc = self._arguments[name]["desc"]
self._arguments[name]["state"] = procdesc_to_entry(procdesc).default_state(procdesc)
self.update_value(name)
def reset_all(self):
for name in self._arguments.keys():
self.reset_value(name)
class AppletIPCServer(AsyncioParentComm): class AppletIPCServer(AsyncioParentComm):
def __init__(self, dataset_sub, dataset_ctl, expmgr): def __init__(self, dataset_sub, dataset_ctl, expmgr):