forked from M-Labs/artiq
1
0
Fork 0

Compare commits

...

6 Commits

5 changed files with 194 additions and 368 deletions

View File

@ -10,87 +10,24 @@ import h5py
from sipyco import pyon
from artiq import __artiq_dir__ as artiq_dir
from artiq.gui.tools import (LayoutWidget, WheelFilter,
log_level_to_name, get_open_file_name)
from artiq.gui.entries import procdesc_to_entry
from artiq.gui.tools import (LayoutWidget, log_level_to_name, get_open_file_name)
from artiq.gui.entries import procdesc_to_entry, EntryTreeWidget
from artiq.master.worker import Worker, log_worker_exception
logger = logging.getLogger(__name__)
class _ArgumentEditor(QtWidgets.QTreeWidget):
class _ArgumentEditor(EntryTreeWidget):
def __init__(self, dock):
QtWidgets.QTreeWidget.__init__(self)
self.setColumnCount(3)
self.header().setStretchLastSection(False)
try:
set_resize_mode = self.header().setSectionResizeMode
except AttributeError:
set_resize_mode = self.header().setResizeMode
set_resize_mode(0, QtWidgets.QHeaderView.ResizeToContents)
set_resize_mode(1, QtWidgets.QHeaderView.Stretch)
set_resize_mode(2, QtWidgets.QHeaderView.ResizeToContents)
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()
EntryTreeWidget.__init__(self)
self._dock = dock
if not self._dock.arguments:
self.addTopLevelItem(QtWidgets.QTreeWidgetItem(["No arguments"]))
gradient = QtGui.QLinearGradient(
0, 0, 0, QtGui.QFontMetrics(self.font()).lineSpacing()*2.5)
gradient.setColorAt(0, self.palette().base().color())
gradient.setColorAt(1, self.palette().midlight().color())
for name, argument in self._dock.arguments.items():
widgets = dict()
self._arg_to_widgets[name] = widgets
self.set_argument(name, argument)
entry = procdesc_to_entry(argument["desc"])(argument)
widget_item = QtWidgets.QTreeWidgetItem([name])
if argument["tooltip"]:
widget_item.setToolTip(0, argument["tooltip"])
widgets["entry"] = entry
widgets["widget_item"] = widget_item
for col in range(3):
widget_item.setBackground(col, gradient)
font = widget_item.font(0)
font.setBold(True)
widget_item.setFont(0, font)
if argument["group"] is None:
self.addTopLevelItem(widget_item)
else:
self._get_group(argument["group"]).addChild(widget_item)
fix_layout = LayoutWidget()
widgets["fix_layout"] = fix_layout
fix_layout.addWidget(entry)
self.setItemWidget(widget_item, 1, fix_layout)
recompute_argument = QtWidgets.QToolButton()
recompute_argument.setToolTip("Re-run the experiment's build "
"method and take the default value")
recompute_argument.setIcon(
QtWidgets.QApplication.style().standardIcon(
QtWidgets.QStyle.SP_BrowserReload))
recompute_argument.clicked.connect(
partial(self._recompute_argument_clicked, name))
fix_layout = LayoutWidget()
fix_layout.addWidget(recompute_argument)
self.setItemWidget(widget_item, 2, fix_layout)
widget_item = QtWidgets.QTreeWidgetItem()
self.addTopLevelItem(widget_item)
recompute_arguments = QtWidgets.QPushButton("Recompute all arguments")
recompute_arguments.setIcon(
QtWidgets.QApplication.style().standardIcon(
@ -100,7 +37,7 @@ class _ArgumentEditor(QtWidgets.QTreeWidget):
load = QtWidgets.QPushButton("Set arguments from HDF5")
load.setToolTip("Set arguments from currently selected HDF5 file")
load.setIcon(QtWidgets.QApplication.style().standardIcon(
QtWidgets.QStyle.SP_DialogApplyButton))
QtWidgets.QStyle.SP_DialogApplyButton))
load.clicked.connect(self._load_clicked)
buttons = LayoutWidget()
@ -108,21 +45,7 @@ class _ArgumentEditor(QtWidgets.QTreeWidget):
buttons.addWidget(load, 1, 2)
for i, s in enumerate((1, 0, 0, 1)):
buttons.layout.setColumnStretch(i, s)
self.setItemWidget(widget_item, 1, 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.addTopLevelItem(group)
self._groups[name] = group
return group
self.setItemWidget(self.bottom_item, 1, buttons)
def _load_clicked(self):
asyncio.ensure_future(self._dock.load_hdf5_task())
@ -130,8 +53,8 @@ class _ArgumentEditor(QtWidgets.QTreeWidget):
def _recompute_arguments_clicked(self):
asyncio.ensure_future(self._dock._recompute_arguments())
def _recompute_argument_clicked(self, name):
asyncio.ensure_future(self._recompute_argument(name))
def reset_entry(self, key):
asyncio.ensure_future(self._recompute_argument(key))
async def _recompute_argument(self, name):
try:
@ -146,29 +69,7 @@ class _ArgumentEditor(QtWidgets.QTreeWidget):
state = procdesc_to_entry(procdesc).default_state(procdesc)
argument["desc"] = procdesc
argument["state"] = state
widgets = self._arg_to_widgets[name]
widgets["entry"].deleteLater()
widgets["entry"] = procdesc_to_entry(procdesc)(argument)
widgets["fix_layout"] = LayoutWidget()
widgets["fix_layout"].addWidget(widgets["entry"])
self.setItemWidget(widgets["widget_item"], 1, widgets["fix_layout"])
self.updateGeometries()
def save_state(self):
expanded = []
for k, v in self._groups.items():
if v.isExpanded():
expanded.append(k)
return {"expanded": expanded}
def restore_state(self, state):
for e in state["expanded"]:
try:
self._groups[e].setExpanded(True)
except KeyError:
pass
self.update_argument(name, argument)
log_levels = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
@ -277,8 +178,8 @@ class _ExperimentDock(QtWidgets.QMdiSubWindow):
state = self.argeditor.save_state()
self.argeditor.deleteLater()
self.argeditor = _ArgumentEditor(self)
self.argeditor.restore_state(state)
self.layout.addWidget(self.argeditor, 0, 0, 1, 5)
self.argeditor.restore_state(state)
async def load_hdf5_task(self, filename=None):
if filename is None:

View File

@ -9,10 +9,9 @@ import h5py
from sipyco import pyon
from artiq.gui.entries import procdesc_to_entry, ScanEntry
from artiq.gui.entries import procdesc_to_entry, EntryTreeWidget
from artiq.gui.fuzzy_select import FuzzySelectWidget
from artiq.gui.tools import (LayoutWidget, WheelFilter,
log_level_to_name, get_open_file_name)
from artiq.gui.tools import (LayoutWidget, log_level_to_name, get_open_file_name)
from artiq.tools import parse_devarg_override, unparse_devarg_override
@ -25,99 +24,21 @@ logger = logging.getLogger(__name__)
# 2. file:<class name>@<file name>
class _ArgumentEditor(QtWidgets.QTreeWidget):
class _ArgumentEditor(EntryTreeWidget):
def __init__(self, manager, dock, expurl):
self.manager = manager
self.expurl = expurl
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)
set_resize_mode(2, QtWidgets.QHeaderView.ResizeToContents)
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()
EntryTreeWidget.__init__(self)
arguments = self.manager.get_submission_arguments(self.expurl)
if not arguments:
self.addTopLevelItem(QtWidgets.QTreeWidgetItem(["No arguments"]))
gradient = QtGui.QLinearGradient(
0, 0, 0, QtGui.QFontMetrics(self.font()).lineSpacing()*2.5)
gradient.setColorAt(0, self.palette().base().color())
gradient.setColorAt(1, self.palette().midlight().color())
for name, argument in arguments.items():
widgets = dict()
self._arg_to_widgets[name] = widgets
self.set_argument(name, argument)
entry = procdesc_to_entry(argument["desc"])(argument)
widget_item = QtWidgets.QTreeWidgetItem([name])
if argument["tooltip"]:
widget_item.setToolTip(0, argument["tooltip"])
widgets["entry"] = entry
widgets["widget_item"] = widget_item
for col in range(3):
widget_item.setBackground(col, gradient)
font = widget_item.font(0)
font.setBold(True)
widget_item.setFont(0, font)
if argument["group"] is None:
self.addTopLevelItem(widget_item)
else:
self._get_group(argument["group"]).addChild(widget_item)
fix_layout = LayoutWidget()
widgets["fix_layout"] = fix_layout
fix_layout.addWidget(entry)
self.setItemWidget(widget_item, 1, fix_layout)
recompute_argument = QtWidgets.QToolButton()
recompute_argument.setToolTip("Re-run the experiment's build "
"method and take the default value")
recompute_argument.setIcon(
QtWidgets.QApplication.style().standardIcon(
QtWidgets.QStyle.SP_BrowserReload))
recompute_argument.clicked.connect(
partial(self._recompute_argument_clicked, name))
tool_buttons = LayoutWidget()
tool_buttons.addWidget(recompute_argument, 1)
disable_other_scans = QtWidgets.QToolButton()
widgets["disable_other_scans"] = disable_other_scans
disable_other_scans.setIcon(
QtWidgets.QApplication.style().standardIcon(
QtWidgets.QStyle.SP_DialogResetButton))
disable_other_scans.setToolTip("Disable all other scans in "
"this experiment")
disable_other_scans.clicked.connect(
partial(self._disable_other_scans, name))
tool_buttons.layout.setRowStretch(0, 1)
tool_buttons.layout.setRowStretch(3, 1)
tool_buttons.addWidget(disable_other_scans, 2)
if not isinstance(entry, ScanEntry):
disable_other_scans.setVisible(False)
self.setItemWidget(widget_item, 2, tool_buttons)
widget_item = QtWidgets.QTreeWidgetItem()
self.addTopLevelItem(widget_item)
recompute_arguments = QtWidgets.QPushButton("Recompute all arguments")
recompute_arguments.setIcon(
QtWidgets.QApplication.style().standardIcon(
@ -136,41 +57,10 @@ class _ArgumentEditor(QtWidgets.QTreeWidget):
buttons.layout.setColumnStretch(1, 0)
buttons.layout.setColumnStretch(2, 0)
buttons.layout.setColumnStretch(3, 1)
self.setItemWidget(widget_item, 1, buttons)
self.setItemWidget(self.bottom_item, 1, 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.addTopLevelItem(group)
self._groups[name] = group
return group
def update_argument(self, name, argument):
widgets = self._arg_to_widgets[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["disable_other_scans"].setVisible(
isinstance(widgets["entry"], ScanEntry))
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 _recompute_argument_clicked(self, name):
asyncio.ensure_future(self._recompute_argument(name))
def reset_entry(self, key):
asyncio.ensure_future(self._recompute_argument(key))
async def _recompute_argument(self, name):
try:
@ -187,30 +77,6 @@ class _ArgumentEditor(QtWidgets.QTreeWidget):
argument["state"] = state
self.update_argument(name, argument)
def _disable_other_scans(self, current_name):
for name, widgets in self._arg_to_widgets.items():
if (name != current_name
and isinstance(widgets["entry"], ScanEntry)):
widgets["entry"].disable()
def save_state(self):
expanded = []
for k, v in self._groups.items():
if v.isExpanded():
expanded.append(k)
return {
"expanded": expanded,
"scroll": self.verticalScrollBar().value()
}
def restore_state(self, state):
for e in state["expanded"]:
try:
self._groups[e].setExpanded(True)
except KeyError:
pass
self.verticalScrollBar().setValue(state["scroll"])
# Hooks that allow user-supplied argument editors to react to imminent user
# actions. Here, we always keep the manager-stored submission arguments
# up-to-date, so no further action is required.
@ -433,8 +299,8 @@ class _ExperimentDock(QtWidgets.QMdiSubWindow):
editor_class = self.manager.get_argument_editor_class(self.expurl)
self.argeditor = editor_class(self.manager, self, self.expurl)
self.argeditor.restore_state(argeditor_state)
self.layout.addWidget(self.argeditor, 0, 0, 1, 5)
self.argeditor.restore_state(argeditor_state)
def contextMenuEvent(self, event):
menu = QtWidgets.QMenu(self)

View File

@ -14,43 +14,16 @@ from sipyco.pipe_ipc import AsyncioParentComm
from sipyco.logging_tools import LogParser
from sipyco import pyon
from artiq.gui.entries import procdesc_to_entry
from artiq.gui.tools import (QDockWidgetCloseDetect, LayoutWidget,
WheelFilter)
from artiq.gui.entries import procdesc_to_entry, EntryTreeWidget
from artiq.gui.tools import QDockWidgetCloseDetect, LayoutWidget
logger = logging.getLogger(__name__)
class EntryArea(QtWidgets.QTreeWidget):
class EntryArea(EntryTreeWidget):
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())
EntryTreeWidget.__init__(self)
reset_all_button = QtWidgets.QPushButton("Restore defaults")
reset_all_button.setToolTip("Reset all to default values")
reset_all_button.setIcon(
@ -62,73 +35,16 @@ class EntryArea(QtWidgets.QTreeWidget):
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, key, processor, group=None, tooltip=None):
argument = dict()
desc = processor.describe()
argument["desc"] = desc
argument["group"] = group
argument["tooltip"] = tooltip
self._arguments[key] = argument
widgets = dict()
self._arg_to_widgets[key] = widgets
entry_class = procdesc_to_entry(argument["desc"])
argument["state"] = entry_class.default_state(argument["desc"])
entry = entry_class(argument)
widget_item = QtWidgets.QTreeWidgetItem([key])
if argument["tooltip"]:
widget_item.setToolTip(0, argument["tooltip"])
widgets["entry"] = entry
widgets["widget_item"] = widget_item
self.set_argument(key, argument)
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, key))
tool_buttons = LayoutWidget()
tool_buttons.addWidget(reset_value, 0)
self.setItemWidget(widget_item, 2, tool_buttons)
def _get_group(self, key):
if key in self._groups:
return self._groups[key]
group = QtWidgets.QTreeWidgetItem([key])
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[key] = group
return group
def __getattr__(self, key):
return self.get_value(key)
@ -158,29 +74,15 @@ class EntryArea(QtWidgets.QTreeWidget):
self.set_value(key, value)
def update_value(self, key):
widgets = self._arg_to_widgets[key]
argument = self._arguments[key]
# 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()
self.update_argument(key, argument)
def reset_value(self, key):
procdesc = self._arguments[key]["desc"]
self._arguments[key]["state"] = procdesc_to_entry(procdesc).default_state(procdesc)
self.update_value(key)
self.reset_entry(key)
def reset_all(self):
for key in self._arguments.keys():
self.reset_value(key)
self.reset_entry(key)
class AppletIPCServer(AsyncioParentComm):

View File

@ -1,9 +1,10 @@
import logging
from collections import OrderedDict
from functools import partial
from PyQt5 import QtCore, QtGui, QtWidgets
from artiq.gui.tools import LayoutWidget, disable_scroll_wheel
from artiq.gui.tools import LayoutWidget, disable_scroll_wheel, WheelFilter
from artiq.gui.scanwidget import ScanWidget
from artiq.gui.scientific_spinbox import ScientificSpinBox
@ -11,6 +12,158 @@ from artiq.gui.scientific_spinbox import ScientificSpinBox
logger = logging.getLogger(__name__)
class EntryTreeWidget(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)
set_resize_mode(2, QtWidgets.QHeaderView.ResizeToContents)
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())
self.bottom_item = QtWidgets.QTreeWidgetItem()
self.addTopLevelItem(self.bottom_item)
self.bottom_item.setHidden(True)
def set_argument(self, key, argument):
self._arguments[key] = argument
widgets = dict()
self._arg_to_widgets[key] = widgets
entry_class = procdesc_to_entry(argument["desc"])
argument["state"] = entry_class.default_state(argument["desc"])
entry = entry_class(argument)
widget_item = QtWidgets.QTreeWidgetItem([key])
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_entry = QtWidgets.QToolButton()
reset_entry.setToolTip("Reset to default value")
reset_entry.setIcon(
QtWidgets.QApplication.style().standardIcon(
QtWidgets.QStyle.SP_BrowserReload))
reset_entry.clicked.connect(partial(self.reset_entry, key))
disable_other_scans = QtWidgets.QToolButton()
widgets["disable_other_scans"] = disable_other_scans
disable_other_scans.setIcon(
QtWidgets.QApplication.style().standardIcon(
QtWidgets.QStyle.SP_DialogResetButton))
disable_other_scans.setToolTip("Disable other scans")
disable_other_scans.clicked.connect(
partial(self._disable_other_scans, key))
if not isinstance(entry, ScanEntry):
disable_other_scans.setVisible(False)
tool_buttons = LayoutWidget()
tool_buttons.layout.setRowStretch(0, 1)
tool_buttons.layout.setRowStretch(3, 1)
tool_buttons.addWidget(reset_entry, 1)
tool_buttons.addWidget(disable_other_scans, 2)
self.setItemWidget(widget_item, 2, tool_buttons)
def _get_group(self, key):
if key in self._groups:
return self._groups[key]
group = QtWidgets.QTreeWidgetItem([key])
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[key] = group
return group
def _disable_other_scans(self, current_key):
for key, widgets in self._arg_to_widgets.items():
if (key != current_key and isinstance(widgets["entry"], ScanEntry)):
widgets["entry"].disable()
def update_argument(self, key, argument):
widgets = self._arg_to_widgets[key]
# 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["disable_other_scans"].setVisible(
isinstance(widgets["entry"], ScanEntry))
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_entry(self, key):
procdesc = self._arguments[key]["desc"]
self._arguments[key]["state"] = procdesc_to_entry(procdesc).default_state(procdesc)
self.update_argument(key, self._arguments[key])
def save_state(self):
expanded = []
for k, v in self._groups.items():
if v.isExpanded():
expanded.append(k)
return {
"expanded": expanded,
"scroll": self.verticalScrollBar().value()
}
def restore_state(self, state):
for e in state["expanded"]:
try:
self._groups[e].setExpanded(True)
except KeyError:
pass
self.verticalScrollBar().setValue(state["scroll"])
class StringEntry(QtWidgets.QLineEdit):
def __init__(self, argument):
QtWidgets.QLineEdit.__init__(self)

View File

@ -121,15 +121,19 @@ class DictSyncModel(QtCore.QAbstractTableModel):
old_row = self.row_to_key.index(k)
new_row = self._find_row(k, v)
if old_row == new_row:
self.backing_store[k] = v
self.dataChanged.emit(self.index(old_row, 0),
self.index(old_row, len(self.headers)-1))
else:
self.beginMoveRows(QtCore.QModelIndex(), old_row, old_row,
QtCore.QModelIndex(), new_row)
self.backing_store[k] = v
self.row_to_key[old_row], self.row_to_key[new_row] = \
self.row_to_key[new_row], self.row_to_key[old_row]
if old_row != new_row:
begin = min(old_row, new_row)
end = max(old_row, new_row)
self.beginMoveRows(QtCore.QModelIndex(), begin + 1, end - 1,
QtCore.QModelIndex(), begin)
self.backing_store[k] = v
self.row_to_key.pop(old_row)
if old_row < new_row:
new_row -= 1
self.row_to_key.insert(new_row, k)
self.endMoveRows()
else:
row = self._find_row(k, v)