From ff4c03014c64c5c72d793e67da84646a06034c81 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Tue, 1 Dec 2015 17:10:44 +0800 Subject: [PATCH] gui/shortcuts: integrate with experiment manager --- artiq/frontend/artiq_gui.py | 10 +-- artiq/gui/explorer.py | 44 ++++++------ artiq/gui/shortcuts.py | 129 +++++++++++++++++------------------- 3 files changed, 89 insertions(+), 94 deletions(-) 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)