diff --git a/artiq/frontend/artiq_gui.py b/artiq/frontend/artiq_gui.py index 2db26042b..645643fb5 100755 --- a/artiq/frontend/artiq_gui.py +++ b/artiq/frontend/artiq_gui.py @@ -66,7 +66,7 @@ def main(): win.resize(1400, 800) win.setWindowTitle("ARTIQ") - d_explorer = ExplorerDock(status_bar, schedule_ctl) + d_explorer = ExplorerDock(win, status_bar, schedule_ctl) loop.run_until_complete(d_explorer.sub_connect( args.server, args.port_notify)) atexit.register(lambda: loop.run_until_complete(d_explorer.sub_close())) diff --git a/artiq/gui/explorer.py b/artiq/gui/explorer.py index 4b4529cfd..e4d594969 100644 --- a/artiq/gui/explorer.py +++ b/artiq/gui/explorer.py @@ -1,10 +1,12 @@ import asyncio +import traceback from quamash import QtGui, QtCore from pyqtgraph import dockarea from pyqtgraph import LayoutWidget from artiq.protocols.sync_struct import Subscriber +from artiq.protocols import pyon from artiq.gui.tools import DictSyncModel @@ -21,20 +23,68 @@ class _ExplistModel(DictSyncModel): return k +class _FreeValueEntry(QtGui.QLineEdit): + def __init__(self, procdesc): + QtGui.QLineEdit.__init__(self) + if "default" in procdesc: + self.insert(pyon.encode(procdesc["default"])) + + def get_argument_value(self): + return pyon.decode(self.text()) + + +_procty_to_entry = { + "FreeValue": _FreeValueEntry +} + + +class _ArgumentSetter(LayoutWidget): + def __init__(self, dialog_parent, arguments): + LayoutWidget.__init__(self) + self.dialog_parent = dialog_parent + + if not arguments: + self.addWidget(QtGui.QLabel("No arguments"), 0, 0) + + self._args_to_entries = dict() + for n, (name, procdesc) in enumerate(arguments): + self.addWidget(QtGui.QLabel(name), n, 0) + entry = _procty_to_entry[procdesc["ty"]](procdesc) + self.addWidget(entry, n, 1) + self._args_to_entries[name] = entry + + def get_argument_values(self): + r = dict() + for arg, entry in self._args_to_entries.items(): + try: + r[arg] = entry.get_argument_value() + except: + msgbox = QtGui.QMessageBox(self.dialog_parent) + msgbox.setWindowTitle("Error") + msgbox.setText("Failed to obtain value for argument '{}'.\n{}" + .format(arg, traceback.format_exc())) + msgbox.setStandardButtons(QtGui.QMessageBox.Ok) + msgbox.show() + return None + return r + + class ExplorerDock(dockarea.Dock): - def __init__(self, status_bar, schedule_ctl): + def __init__(self, dialog_parent, status_bar, schedule_ctl): dockarea.Dock.__init__(self, "Explorer", size=(1500, 500)) + self.dialog_parent = dialog_parent self.status_bar = status_bar self.schedule_ctl = schedule_ctl - splitter = QtGui.QSplitter(QtCore.Qt.Horizontal) - self.addWidget(splitter) + self.splitter = QtGui.QSplitter(QtCore.Qt.Horizontal) + self.addWidget(self.splitter) grid = LayoutWidget() - splitter.addWidget(grid) + self.splitter.addWidget(grid) self.el = QtGui.QListView() + self.el.selectionChanged = self.update_argsetter grid.addWidget(self.el, 0, 0, colspan=4) self.datetime = QtGui.QDateTimeEdit() @@ -63,8 +113,22 @@ class ExplorerDock(dockarea.Dock): grid.addWidget(submit, 3, 0, colspan=4) submit.clicked.connect(self.submit_clicked) - placeholder = QtGui.QWidget() - splitter.addWidget(placeholder) + self.argsetter = _ArgumentSetter(self.dialog_parent, []) + self.splitter.addWidget(self.argsetter) + self.splitter.setSizes([grid.minimumSizeHint().width(), 1000]) + + def update_argsetter(self, selected, deselected): + selected = selected.indexes() + if selected: + row = selected[0].row() + key = self.explist_model.row_to_key[row] + expinfo = self.explist_model.backing_store[key] + arguments = expinfo["arguments"] + sizes = self.splitter.sizes() + self.argsetter.deleteLater() + self.argsetter = _ArgumentSetter(self.dialog_parent, arguments) + self.splitter.insertWidget(1, self.argsetter) + self.splitter.setSizes(sizes) def enable_duedate(self): self.datetime_en.setChecked(True) @@ -106,7 +170,10 @@ class ExplorerDock(dockarea.Dock): due_date = self.datetime.dateTime().toMSecsSinceEpoch()/1000 else: due_date = None + arguments = self.argsetter.get_argument_values() + if arguments is None: + return asyncio.async(self.submit(self.pipeline.text(), expinfo["file"], expinfo["class_name"], - dict(), self.priority.value(), due_date, - self.flush.isChecked())) + arguments, self.priority.value(), + due_date, self.flush.isChecked()))