diff --git a/artiq/frontend/artiq_gui.py b/artiq/frontend/artiq_gui.py
index 43bfb276c..bc72b380b 100755
--- a/artiq/frontend/artiq_gui.py
+++ b/artiq/frontend/artiq_gui.py
@@ -13,7 +13,7 @@ from pyqtgraph import dockarea
from artiq.tools import *
from artiq.protocols.pc_rpc import AsyncioClient
from artiq.gui.models import ModelSubscriber
-from artiq.gui import (state, experiments, explorer,
+from artiq.gui import (state, experiments, shortcuts, explorer,
moninj, datasets, schedule, log, console)
@@ -100,11 +100,12 @@ def main():
sub_clients["schedule"],
rpc_clients["schedule"])
smgr.register(expmgr)
- d_explorer = explorer.ExplorerDock(win, status_bar, expmgr,
+ d_shortcuts = shortcuts.ShortcutsDock(win, status_bar, expmgr)
+ smgr.register(d_shortcuts)
+ d_explorer = explorer.ExplorerDock(status_bar, expmgr, d_shortcuts,
sub_clients["explist"],
rpc_clients["schedule"],
rpc_clients["repository"])
- smgr.register(d_explorer)
d_datasets = datasets.DatasetsDock(win, dock_area, sub_clients["datasets"])
smgr.register(d_datasets)
@@ -130,7 +131,8 @@ def main():
dock_area.addDock(d_datasets, "above", d_ttl_dds.ttl_dock)
else:
dock_area.addDock(d_datasets, "top")
- dock_area.addDock(d_explorer, "above", d_datasets)
+ dock_area.addDock(d_shortcuts, "above", d_datasets)
+ dock_area.addDock(d_explorer, "above", d_shortcuts)
dock_area.addDock(d_console, "bottom")
dock_area.addDock(d_schedule, "above", d_console)
diff --git a/artiq/gui/explorer.py b/artiq/gui/explorer.py
index 9d5ae8a4e..3c6e07891 100644
--- a/artiq/gui/explorer.py
+++ b/artiq/gui/explorer.py
@@ -1,12 +1,12 @@
import asyncio
import logging
+from functools import partial
from quamash import QtGui, QtCore
from pyqtgraph import dockarea
from pyqtgraph import LayoutWidget
from artiq.gui.models import DictSyncTreeSepModel
-from artiq.gui.shortcuts import ShortcutManager
class Model(DictSyncTreeSepModel):
@@ -22,13 +22,15 @@ class Model(DictSyncTreeSepModel):
class ExplorerDock(dockarea.Dock):
- def __init__(self, main_window, status_bar, exp_manager,
+ def __init__(self, status_bar, exp_manager, d_shortcuts,
explist_sub, schedule_ctl, repository_ctl):
dockarea.Dock.__init__(self, "Explorer", size=(1500, 500))
+ self.layout.setSpacing(5)
+ self.layout.setContentsMargins(5, 5, 5, 5)
- self.main_window = main_window
self.status_bar = status_bar
self.exp_manager = exp_manager
+ self.d_shortcuts = d_shortcuts
self.schedule_ctl = schedule_ctl
self.el = QtGui.QTreeView()
@@ -38,18 +40,21 @@ class ExplorerDock(dockarea.Dock):
self.el.doubleClicked.connect(self.open_clicked)
open = QtGui.QPushButton("Open")
+ open.setIcon(QtGui.QApplication.style().standardIcon(
+ QtGui.QStyle.SP_DialogOpenButton))
open.setToolTip("Open the selected experiment (Return)")
self.addWidget(open, 1, 0)
open.clicked.connect(self.open_clicked)
submit = QtGui.QPushButton("Submit")
+ submit.setIcon(QtGui.QApplication.style().standardIcon(
+ QtGui.QStyle.SP_DialogOkButton))
submit.setToolTip("Schedule the selected experiment (Ctrl+Return)")
self.addWidget(submit, 1, 1)
submit.clicked.connect(self.submit_clicked)
self.explist_model = Model(dict())
explist_sub.add_setmodel_callback(self.set_model)
- self.shortcuts = ShortcutManager(self.main_window, self)
self.el.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
open_action = QtGui.QAction("Open", self.el)
@@ -69,9 +74,15 @@ class ExplorerDock(dockarea.Dock):
sep.setSeparator(True)
self.el.addAction(sep)
- edit_shortcuts_action = QtGui.QAction("Edit shortcuts", self.el)
- edit_shortcuts_action.triggered.connect(self.edit_shortcuts)
- self.el.addAction(edit_shortcuts_action)
+ set_shortcut_menu = QtGui.QMenu()
+ for i in range(12):
+ action = QtGui.QAction("F" + str(i+1), self.el)
+ action.triggered.connect(partial(self.set_shortcut, i))
+ set_shortcut_menu.addAction(action)
+
+ set_shortcut_action = QtGui.QAction("Set shortcut", self.el)
+ set_shortcut_action.setMenu(set_shortcut_menu)
+ self.el.addAction(set_shortcut_action)
scan_repository_action = QtGui.QAction("(Re)scan repository HEAD",
self.el)
def scan_repository():
@@ -107,18 +118,7 @@ class ExplorerDock(dockarea.Dock):
if expname is not None:
self.exp_manager.request_inst_term(expname)
- def save_state(self):
- return {
- "shortcuts": self.shortcuts.save_state()
- }
-
- def restore_state(self, state):
- try:
- shortcuts_state = state["shortcuts"]
- except KeyError:
- return
- self.shortcuts.restore_state(shortcuts_state)
-
- def edit_shortcuts(self):
- experiments = sorted(self.explist_model.backing_store.keys())
- self.shortcuts.edit(experiments)
+ def set_shortcut(self, nr):
+ expname = self._get_selected_expname()
+ if expname is not None:
+ self.d_shortcuts.set_shortcut(nr, expname)
diff --git a/artiq/gui/shortcuts.py b/artiq/gui/shortcuts.py
index 82308f0be..e6059a392 100644
--- a/artiq/gui/shortcuts.py
+++ b/artiq/gui/shortcuts.py
@@ -1,6 +1,8 @@
+import logging
from functools import partial
from quamash import QtGui
+from pyqtgraph import dockarea
try:
from quamash import QtWidgets
QShortcut = QtWidgets.QShortcut
@@ -8,91 +10,82 @@ except:
QShortcut = QtGui.QShortcut
-class _ShortcutEditor(QtGui.QDialog):
- def __init__(self, parent, experiments, shortcuts):
- QtGui.QDialog.__init__(self, parent=parent)
- self.setWindowTitle("Shortcuts")
+logger = logging.getLogger(__name__)
- self.shortcuts = shortcuts
- self.edit_widgets = dict()
- grid = QtGui.QGridLayout()
- self.setLayout(grid)
+class ShortcutsDock(dockarea.Dock):
+ def __init__(self, main_window, status_bar, exp_manager):
+ dockarea.Dock.__init__(self, "Shortcuts", size=(1000, 300))
+ self.layout.setSpacing(5)
+ self.layout.setContentsMargins(5, 5, 5, 5)
- for n, title in enumerate(["Key", "Experiment", "Priority", "Pipeline"]):
- label = QtGui.QLabel("" + title + "" + title + "")
+ self.addWidget(label, 0, n)
label.setMaximumHeight(label.sizeHint().height())
- grid.setColumnStretch(1, 1)
- grid.setColumnStretch(3, 1)
+ self.layout.setColumnStretch(1, 1)
for i in range(12):
row = i + 1
- existing_shortcut = self.shortcuts.get(i, dict())
- grid.addWidget(QtGui.QLabel("F" + str(i+1)), row, 0)
+ self.addWidget(QtGui.QLabel("F" + str(i+1)), row, 0)
- experiment = QtGui.QComboBox()
- grid.addWidget(experiment, row, 1)
- experiment.addItem("")
- experiment.addItems(experiments)
- experiment.setEditable(True)
- experiment.setEditText(
- existing_shortcut.get("experiment", ""))
-
- priority = QtGui.QSpinBox()
- grid.addWidget(priority, row, 2)
- priority.setRange(-99, 99)
- priority.setValue(existing_shortcut.get("priority", 0))
+ label = QtGui.QLabel()
+ self.addWidget(label, row, 1)
- pipeline = QtGui.QLineEdit()
- grid.addWidget(pipeline, row, 3)
- pipeline.setText(existing_shortcut.get("pipeline", "main"))
+ clear = QtGui.QToolButton()
+ clear.setIcon(QtGui.QApplication.style().standardIcon(
+ QtGui.QStyle.SP_DialogResetButton))
+ self.addWidget(clear, row, 2)
+ clear.clicked.connect(partial(self.set_shortcut, i, ""))
- self.edit_widgets[i] = {
- "experiment": experiment,
- "priority": priority,
- "pipeline": pipeline
+ submit = QtGui.QPushButton("Submit")
+ submit.setIcon(QtGui.QApplication.style().standardIcon(
+ QtGui.QStyle.SP_DialogOkButton))
+ self.addWidget(submit, row, 3)
+ submit.clicked.connect(partial(self._activated, i))
+
+ self.shortcut_widgets[i] = {
+ "label": label,
+ "clear": clear,
+ "submit": submit
}
-
- buttons = QtGui.QDialogButtonBox(
- QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel)
- grid.addWidget(buttons, 14, 0, 1, 4)
- buttons.accepted.connect(self.accept)
- buttons.rejected.connect(self.reject)
- self.accepted.connect(self.on_accept)
-
- def on_accept(self):
- for n, widgets in self.edit_widgets.items():
- self.shortcuts[n] = {
- "experiment": widgets["experiment"].currentText(),
- "priority": widgets["priority"].value(),
- "pipeline": widgets["pipeline"].text()
- }
-
-
-class ShortcutManager:
- def __init__(self, main_window, explorer):
- for i in range(12):
shortcut = QShortcut("F" + str(i+1), main_window)
shortcut.activated.connect(partial(self._activated, i))
- self.main_window = main_window
- self.explorer = explorer
- self.shortcuts = dict()
-
- def edit(self, experiments):
- dlg = _ShortcutEditor(self.main_window, experiments, self.shortcuts)
- dlg.open()
def _activated(self, nr):
- info = self.shortcuts.get(nr, dict())
- experiment = info.get("experiment", "")
- if experiment and experiment != "":
- self.explorer.submit(info["pipeline"], experiment,
- info["priority"], None, False)
+ expname = self.shortcut_widgets[nr]["label"].text()
+ if expname:
+ try:
+ rid = self.exp_manager.submit(expname)
+ except:
+ self.status_bar.showMessage("Could not submit experiment '{}'"
+ .format(expname))
+ logger.warning("failed to submit experiment %s",
+ expname, exc_info=True)
+ else:
+ self.status_bar.showMessage("Submitted RID {} "
+ "(from global shortcut)"
+ .format(rid))
+
+ def set_shortcut(self, nr, expname):
+ widgets = self.shortcut_widgets[nr]
+ widgets["label"].setText(expname)
+ if expname:
+ widgets["clear"].show()
+ widgets["submit"].show()
+ else:
+ widgets["clear"].hide()
+ widgets["submit"].hide()
def save_state(self):
- return self.shortcuts
+ return {nr: widgets["label"].text()
+ for nr, widgets in self.shortcut_widgets.items()}
def restore_state(self, state):
- self.shortcuts = state
+ for nr, expname in state.items():
+ self.set_shortcut(nr, expname)