mirror of https://github.com/m-labs/artiq.git
gui: save explorer state
This commit is contained in:
parent
c8db83b11f
commit
cddb5b9ae4
|
@ -81,6 +81,7 @@ def main():
|
||||||
win.setStatusBar(status_bar)
|
win.setStatusBar(status_bar)
|
||||||
|
|
||||||
d_explorer = ExplorerDock(win, status_bar, schedule_ctl)
|
d_explorer = ExplorerDock(win, status_bar, schedule_ctl)
|
||||||
|
smgr.register(d_explorer)
|
||||||
loop.run_until_complete(d_explorer.sub_connect(
|
loop.run_until_complete(d_explorer.sub_connect(
|
||||||
args.server, args.port_notify))
|
args.server, args.port_notify))
|
||||||
atexit.register(lambda: loop.run_until_complete(d_explorer.sub_close()))
|
atexit.register(lambda: loop.run_until_complete(d_explorer.sub_close()))
|
||||||
|
|
|
@ -28,21 +28,27 @@ class _FreeValueEntry(QtGui.QLineEdit):
|
||||||
def __init__(self, procdesc):
|
def __init__(self, procdesc):
|
||||||
QtGui.QLineEdit.__init__(self)
|
QtGui.QLineEdit.__init__(self)
|
||||||
if "default" in procdesc:
|
if "default" in procdesc:
|
||||||
self.insert(pyon.encode(procdesc["default"]))
|
self.set_argument_value(procdesc["default"])
|
||||||
|
|
||||||
def get_argument_value(self):
|
def get_argument_value(self):
|
||||||
return pyon.decode(self.text())
|
return pyon.decode(self.text())
|
||||||
|
|
||||||
|
def set_argument_value(self, value):
|
||||||
|
self.setText(pyon.encode(value))
|
||||||
|
|
||||||
|
|
||||||
class _BooleanEntry(QtGui.QCheckBox):
|
class _BooleanEntry(QtGui.QCheckBox):
|
||||||
def __init__(self, procdesc):
|
def __init__(self, procdesc):
|
||||||
QtGui.QCheckBox.__init__(self)
|
QtGui.QCheckBox.__init__(self)
|
||||||
if "default" in procdesc:
|
if "default" in procdesc:
|
||||||
self.setChecked(procdesc["default"])
|
self.set_argument_value(procdesc["default"])
|
||||||
|
|
||||||
def get_argument_value(self):
|
def get_argument_value(self):
|
||||||
return self.isChecked()
|
return self.isChecked()
|
||||||
|
|
||||||
|
def set_argument_value(self, value):
|
||||||
|
self.setChecked(value)
|
||||||
|
|
||||||
|
|
||||||
class _EnumerationEntry(QtGui.QComboBox):
|
class _EnumerationEntry(QtGui.QComboBox):
|
||||||
def __init__(self, procdesc):
|
def __init__(self, procdesc):
|
||||||
|
@ -50,16 +56,15 @@ class _EnumerationEntry(QtGui.QComboBox):
|
||||||
self.choices = procdesc["choices"]
|
self.choices = procdesc["choices"]
|
||||||
self.addItems(self.choices)
|
self.addItems(self.choices)
|
||||||
if "default" in procdesc:
|
if "default" in procdesc:
|
||||||
try:
|
self.set_argument_value(procdesc["default"])
|
||||||
idx = self.choices.index(procdesc["default"])
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
self.setCurrentIndex(idx)
|
|
||||||
|
|
||||||
def get_argument_value(self):
|
def get_argument_value(self):
|
||||||
return self.choices[self.currentIndex()]
|
return self.choices[self.currentIndex()]
|
||||||
|
|
||||||
|
def set_argument_value(self, value):
|
||||||
|
idx = self.choices.index(value)
|
||||||
|
self.setCurrentIndex(idx)
|
||||||
|
|
||||||
|
|
||||||
class _NumberEntry(QtGui.QDoubleSpinBox):
|
class _NumberEntry(QtGui.QDoubleSpinBox):
|
||||||
def __init__(self, procdesc):
|
def __init__(self, procdesc):
|
||||||
|
@ -73,21 +78,27 @@ class _NumberEntry(QtGui.QDoubleSpinBox):
|
||||||
if procdesc["unit"]:
|
if procdesc["unit"]:
|
||||||
self.setSuffix(" " + procdesc["unit"])
|
self.setSuffix(" " + procdesc["unit"])
|
||||||
if "default" in procdesc:
|
if "default" in procdesc:
|
||||||
force_spinbox_value(self, procdesc["default"])
|
self.set_argument_value(procdesc["default"])
|
||||||
|
|
||||||
def get_argument_value(self):
|
def get_argument_value(self):
|
||||||
return self.value()
|
return self.value()
|
||||||
|
|
||||||
|
def set_argument_value(self, value):
|
||||||
|
force_spinbox_value(self, value)
|
||||||
|
|
||||||
|
|
||||||
class _StringEntry(QtGui.QLineEdit):
|
class _StringEntry(QtGui.QLineEdit):
|
||||||
def __init__(self, procdesc):
|
def __init__(self, procdesc):
|
||||||
QtGui.QLineEdit.__init__(self)
|
QtGui.QLineEdit.__init__(self)
|
||||||
if "default" in procdesc:
|
if "default" in procdesc:
|
||||||
self.insert(procdesc["default"])
|
self.set_argument_value(procdesc["default"])
|
||||||
|
|
||||||
def get_argument_value(self):
|
def get_argument_value(self):
|
||||||
return self.text()
|
return self.text()
|
||||||
|
|
||||||
|
def set_argument_value(self, value):
|
||||||
|
self.setText(value)
|
||||||
|
|
||||||
|
|
||||||
_procty_to_entry = {
|
_procty_to_entry = {
|
||||||
"FreeValue": _FreeValueEntry,
|
"FreeValue": _FreeValueEntry,
|
||||||
|
@ -114,21 +125,31 @@ class _ArgumentSetter(LayoutWidget):
|
||||||
self.addWidget(entry, n, 1)
|
self.addWidget(entry, n, 1)
|
||||||
self._args_to_entries[name] = entry
|
self._args_to_entries[name] = entry
|
||||||
|
|
||||||
def get_argument_values(self):
|
def get_argument_values(self, show_error_message):
|
||||||
r = dict()
|
r = dict()
|
||||||
for arg, entry in self._args_to_entries.items():
|
for arg, entry in self._args_to_entries.items():
|
||||||
try:
|
try:
|
||||||
r[arg] = entry.get_argument_value()
|
r[arg] = entry.get_argument_value()
|
||||||
except:
|
except:
|
||||||
msgbox = QtGui.QMessageBox(self.dialog_parent)
|
if show_error_message:
|
||||||
msgbox.setWindowTitle("Error")
|
msgbox = QtGui.QMessageBox(self.dialog_parent)
|
||||||
msgbox.setText("Failed to obtain value for argument '{}'.\n{}"
|
msgbox.setWindowTitle("Error")
|
||||||
.format(arg, traceback.format_exc()))
|
msgbox.setText("Failed to obtain value for argument '{}'.\n{}"
|
||||||
msgbox.setStandardButtons(QtGui.QMessageBox.Ok)
|
.format(arg, traceback.format_exc()))
|
||||||
msgbox.show()
|
msgbox.setStandardButtons(QtGui.QMessageBox.Ok)
|
||||||
|
msgbox.show()
|
||||||
return None
|
return None
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
def set_argument_values(self, arguments, ignore_errors):
|
||||||
|
for arg, value in arguments.items():
|
||||||
|
try:
|
||||||
|
entry = self._args_to_entries[arg]
|
||||||
|
entry.set_argument_value(value)
|
||||||
|
except:
|
||||||
|
if not ignore_errors:
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
class ExplorerDock(dockarea.Dock):
|
class ExplorerDock(dockarea.Dock):
|
||||||
def __init__(self, dialog_parent, status_bar, schedule_ctl):
|
def __init__(self, dialog_parent, status_bar, schedule_ctl):
|
||||||
|
@ -163,7 +184,7 @@ class ExplorerDock(dockarea.Dock):
|
||||||
grid.addWidget(self.priority, 1, 3)
|
grid.addWidget(self.priority, 1, 3)
|
||||||
|
|
||||||
self.pipeline = QtGui.QLineEdit()
|
self.pipeline = QtGui.QLineEdit()
|
||||||
self.pipeline.insert("main")
|
self.pipeline.setText("main")
|
||||||
grid.addWidget(QtGui.QLabel("Pipeline:"), 2, 0)
|
grid.addWidget(QtGui.QLabel("Pipeline:"), 2, 0)
|
||||||
grid.addWidget(self.pipeline, 2, 1)
|
grid.addWidget(self.pipeline, 2, 1)
|
||||||
|
|
||||||
|
@ -177,8 +198,15 @@ class ExplorerDock(dockarea.Dock):
|
||||||
self.argsetter = _ArgumentSetter(self.dialog_parent, [])
|
self.argsetter = _ArgumentSetter(self.dialog_parent, [])
|
||||||
self.splitter.addWidget(self.argsetter)
|
self.splitter.addWidget(self.argsetter)
|
||||||
self.splitter.setSizes([grid.minimumSizeHint().width(), 1000])
|
self.splitter.setSizes([grid.minimumSizeHint().width(), 1000])
|
||||||
|
self.state = dict()
|
||||||
|
|
||||||
def update_argsetter(self, selected, deselected):
|
def update_argsetter(self, selected, deselected):
|
||||||
|
deselected = deselected.indexes()
|
||||||
|
if deselected:
|
||||||
|
row = deselected[0].row()
|
||||||
|
key = self.explist_model.row_to_key[row]
|
||||||
|
self.state[key] = self.argsetter.get_argument_values(False)
|
||||||
|
|
||||||
selected = selected.indexes()
|
selected = selected.indexes()
|
||||||
if selected:
|
if selected:
|
||||||
row = selected[0].row()
|
row = selected[0].row()
|
||||||
|
@ -188,9 +216,24 @@ class ExplorerDock(dockarea.Dock):
|
||||||
sizes = self.splitter.sizes()
|
sizes = self.splitter.sizes()
|
||||||
self.argsetter.deleteLater()
|
self.argsetter.deleteLater()
|
||||||
self.argsetter = _ArgumentSetter(self.dialog_parent, arguments)
|
self.argsetter = _ArgumentSetter(self.dialog_parent, arguments)
|
||||||
|
if key in self.state:
|
||||||
|
arguments = self.state[key]
|
||||||
|
if arguments is not None:
|
||||||
|
self.argsetter.set_argument_values(arguments, True)
|
||||||
self.splitter.insertWidget(1, self.argsetter)
|
self.splitter.insertWidget(1, self.argsetter)
|
||||||
self.splitter.setSizes(sizes)
|
self.splitter.setSizes(sizes)
|
||||||
|
|
||||||
|
def save_state(self):
|
||||||
|
idx = self.el.selectedIndexes()
|
||||||
|
if idx:
|
||||||
|
row = idx[0].row()
|
||||||
|
key = self.explist_model.row_to_key[row]
|
||||||
|
self.state[key] = self.argsetter.get_argument_values(False)
|
||||||
|
return self.state
|
||||||
|
|
||||||
|
def restore_state(self, state):
|
||||||
|
self.state = state
|
||||||
|
|
||||||
def enable_duedate(self):
|
def enable_duedate(self):
|
||||||
self.datetime_en.setChecked(True)
|
self.datetime_en.setChecked(True)
|
||||||
|
|
||||||
|
@ -231,7 +274,7 @@ class ExplorerDock(dockarea.Dock):
|
||||||
due_date = self.datetime.dateTime().toMSecsSinceEpoch()/1000
|
due_date = self.datetime.dateTime().toMSecsSinceEpoch()/1000
|
||||||
else:
|
else:
|
||||||
due_date = None
|
due_date = None
|
||||||
arguments = self.argsetter.get_argument_values()
|
arguments = self.argsetter.get_argument_values(True)
|
||||||
if arguments is None:
|
if arguments is None:
|
||||||
return
|
return
|
||||||
asyncio.async(self.submit(self.pipeline.text(),
|
asyncio.async(self.submit(self.pipeline.text(),
|
||||||
|
|
|
@ -96,20 +96,7 @@ class ScanController(LayoutWidget):
|
||||||
b.toggled.connect(self.select_page)
|
b.toggled.connect(self.select_page)
|
||||||
|
|
||||||
if "default" in procdesc:
|
if "default" in procdesc:
|
||||||
d = procdesc["default"]
|
self.set_argument_value(procdesc["default"])
|
||||||
if d["ty"] == "NoScan":
|
|
||||||
self.noscan.setChecked(True)
|
|
||||||
force_spinbox_value(self.v_noscan, d["value"])
|
|
||||||
elif d["ty"] == "LinearScan":
|
|
||||||
self.linear.setChecked(True)
|
|
||||||
self.v_linear.set_values(d["min"], d["max"], d["npoints"])
|
|
||||||
elif d["ty"] == "RandomScan":
|
|
||||||
self.random.setChecked(True)
|
|
||||||
self.v_random.set_values(d["min"], d["max"], d["npoints"])
|
|
||||||
elif d["ty"] == "ExplicitScan":
|
|
||||||
self.explicit.setChecked(True)
|
|
||||||
self.v_explicit.insert(" ".join(
|
|
||||||
[str(x) for x in d["sequence"]]))
|
|
||||||
else:
|
else:
|
||||||
self.noscan.setChecked(True)
|
self.noscan.setChecked(True)
|
||||||
|
|
||||||
|
@ -137,3 +124,20 @@ class ScanController(LayoutWidget):
|
||||||
elif self.explicit.isChecked():
|
elif self.explicit.isChecked():
|
||||||
sequence = [float(x) for x in self.v_explicit.text().split()]
|
sequence = [float(x) for x in self.v_explicit.text().split()]
|
||||||
return {"ty": "ExplicitScan", "sequence": sequence}
|
return {"ty": "ExplicitScan", "sequence": sequence}
|
||||||
|
|
||||||
|
def set_argument_value(self, d):
|
||||||
|
if d["ty"] == "NoScan":
|
||||||
|
self.noscan.setChecked(True)
|
||||||
|
force_spinbox_value(self.v_noscan, d["value"])
|
||||||
|
elif d["ty"] == "LinearScan":
|
||||||
|
self.linear.setChecked(True)
|
||||||
|
self.v_linear.set_values(d["min"], d["max"], d["npoints"])
|
||||||
|
elif d["ty"] == "RandomScan":
|
||||||
|
self.random.setChecked(True)
|
||||||
|
self.v_random.set_values(d["min"], d["max"], d["npoints"])
|
||||||
|
elif d["ty"] == "ExplicitScan":
|
||||||
|
self.explicit.setChecked(True)
|
||||||
|
self.v_explicit.insert(" ".join(
|
||||||
|
[str(x) for x in d["sequence"]]))
|
||||||
|
else:
|
||||||
|
raise ValueError("Unknown scan type '{}'".format(d["ty"]))
|
||||||
|
|
Loading…
Reference in New Issue