gui/shortcuts: integrate with experiment manager

This commit is contained in:
Sebastien Bourdeauducq 2015-12-01 17:10:44 +08:00
parent 741dfce38c
commit ff4c03014c
3 changed files with 89 additions and 94 deletions

View File

@ -13,7 +13,7 @@ from pyqtgraph import dockarea
from artiq.tools import * from artiq.tools import *
from artiq.protocols.pc_rpc import AsyncioClient from artiq.protocols.pc_rpc import AsyncioClient
from artiq.gui.models import ModelSubscriber 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) moninj, datasets, schedule, log, console)
@ -100,11 +100,12 @@ def main():
sub_clients["schedule"], sub_clients["schedule"],
rpc_clients["schedule"]) rpc_clients["schedule"])
smgr.register(expmgr) 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"], sub_clients["explist"],
rpc_clients["schedule"], rpc_clients["schedule"],
rpc_clients["repository"]) rpc_clients["repository"])
smgr.register(d_explorer)
d_datasets = datasets.DatasetsDock(win, dock_area, sub_clients["datasets"]) d_datasets = datasets.DatasetsDock(win, dock_area, sub_clients["datasets"])
smgr.register(d_datasets) smgr.register(d_datasets)
@ -130,7 +131,8 @@ def main():
dock_area.addDock(d_datasets, "above", d_ttl_dds.ttl_dock) dock_area.addDock(d_datasets, "above", d_ttl_dds.ttl_dock)
else: else:
dock_area.addDock(d_datasets, "top") 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_console, "bottom")
dock_area.addDock(d_schedule, "above", d_console) dock_area.addDock(d_schedule, "above", d_console)

View File

@ -1,12 +1,12 @@
import asyncio import asyncio
import logging import logging
from functools import partial
from quamash import QtGui, QtCore from quamash import QtGui, QtCore
from pyqtgraph import dockarea from pyqtgraph import dockarea
from pyqtgraph import LayoutWidget from pyqtgraph import LayoutWidget
from artiq.gui.models import DictSyncTreeSepModel from artiq.gui.models import DictSyncTreeSepModel
from artiq.gui.shortcuts import ShortcutManager
class Model(DictSyncTreeSepModel): class Model(DictSyncTreeSepModel):
@ -22,13 +22,15 @@ class Model(DictSyncTreeSepModel):
class ExplorerDock(dockarea.Dock): 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): explist_sub, schedule_ctl, repository_ctl):
dockarea.Dock.__init__(self, "Explorer", size=(1500, 500)) 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.status_bar = status_bar
self.exp_manager = exp_manager self.exp_manager = exp_manager
self.d_shortcuts = d_shortcuts
self.schedule_ctl = schedule_ctl self.schedule_ctl = schedule_ctl
self.el = QtGui.QTreeView() self.el = QtGui.QTreeView()
@ -38,18 +40,21 @@ class ExplorerDock(dockarea.Dock):
self.el.doubleClicked.connect(self.open_clicked) self.el.doubleClicked.connect(self.open_clicked)
open = QtGui.QPushButton("Open") open = QtGui.QPushButton("Open")
open.setIcon(QtGui.QApplication.style().standardIcon(
QtGui.QStyle.SP_DialogOpenButton))
open.setToolTip("Open the selected experiment (Return)") open.setToolTip("Open the selected experiment (Return)")
self.addWidget(open, 1, 0) self.addWidget(open, 1, 0)
open.clicked.connect(self.open_clicked) open.clicked.connect(self.open_clicked)
submit = QtGui.QPushButton("Submit") submit = QtGui.QPushButton("Submit")
submit.setIcon(QtGui.QApplication.style().standardIcon(
QtGui.QStyle.SP_DialogOkButton))
submit.setToolTip("Schedule the selected experiment (Ctrl+Return)") submit.setToolTip("Schedule the selected experiment (Ctrl+Return)")
self.addWidget(submit, 1, 1) self.addWidget(submit, 1, 1)
submit.clicked.connect(self.submit_clicked) submit.clicked.connect(self.submit_clicked)
self.explist_model = Model(dict()) self.explist_model = Model(dict())
explist_sub.add_setmodel_callback(self.set_model) explist_sub.add_setmodel_callback(self.set_model)
self.shortcuts = ShortcutManager(self.main_window, self)
self.el.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) self.el.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
open_action = QtGui.QAction("Open", self.el) open_action = QtGui.QAction("Open", self.el)
@ -69,9 +74,15 @@ class ExplorerDock(dockarea.Dock):
sep.setSeparator(True) sep.setSeparator(True)
self.el.addAction(sep) self.el.addAction(sep)
edit_shortcuts_action = QtGui.QAction("Edit shortcuts", self.el) set_shortcut_menu = QtGui.QMenu()
edit_shortcuts_action.triggered.connect(self.edit_shortcuts) for i in range(12):
self.el.addAction(edit_shortcuts_action) 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", scan_repository_action = QtGui.QAction("(Re)scan repository HEAD",
self.el) self.el)
def scan_repository(): def scan_repository():
@ -107,18 +118,7 @@ class ExplorerDock(dockarea.Dock):
if expname is not None: if expname is not None:
self.exp_manager.request_inst_term(expname) self.exp_manager.request_inst_term(expname)
def save_state(self): def set_shortcut(self, nr):
return { expname = self._get_selected_expname()
"shortcuts": self.shortcuts.save_state() if expname is not None:
} self.d_shortcuts.set_shortcut(nr, expname)
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)

View File

@ -1,6 +1,8 @@
import logging
from functools import partial from functools import partial
from quamash import QtGui from quamash import QtGui
from pyqtgraph import dockarea
try: try:
from quamash import QtWidgets from quamash import QtWidgets
QShortcut = QtWidgets.QShortcut QShortcut = QtWidgets.QShortcut
@ -8,91 +10,82 @@ except:
QShortcut = QtGui.QShortcut QShortcut = QtGui.QShortcut
class _ShortcutEditor(QtGui.QDialog): logger = logging.getLogger(__name__)
def __init__(self, parent, experiments, shortcuts):
QtGui.QDialog.__init__(self, parent=parent)
self.setWindowTitle("Shortcuts")
self.shortcuts = shortcuts
self.edit_widgets = dict()
grid = QtGui.QGridLayout() class ShortcutsDock(dockarea.Dock):
self.setLayout(grid) 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"]): self.status_bar = status_bar
label = QtGui.QLabel("<b>" + title + "</b") self.exp_manager = exp_manager
grid.addWidget(label, 0, n) self.shortcut_widgets = dict()
for n, title in enumerate(["Key", "Experiment"]):
label = QtGui.QLabel("<b>" + title + "</b>")
self.addWidget(label, 0, n)
label.setMaximumHeight(label.sizeHint().height()) label.setMaximumHeight(label.sizeHint().height())
grid.setColumnStretch(1, 1) self.layout.setColumnStretch(1, 1)
grid.setColumnStretch(3, 1)
for i in range(12): for i in range(12):
row = i + 1 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() label = QtGui.QLabel()
grid.addWidget(experiment, row, 1) self.addWidget(label, row, 1)
experiment.addItem("<None>")
experiment.addItems(experiments)
experiment.setEditable(True)
experiment.setEditText(
existing_shortcut.get("experiment", "<None>"))
priority = QtGui.QSpinBox()
grid.addWidget(priority, row, 2)
priority.setRange(-99, 99)
priority.setValue(existing_shortcut.get("priority", 0))
pipeline = QtGui.QLineEdit() clear = QtGui.QToolButton()
grid.addWidget(pipeline, row, 3) clear.setIcon(QtGui.QApplication.style().standardIcon(
pipeline.setText(existing_shortcut.get("pipeline", "main")) QtGui.QStyle.SP_DialogResetButton))
self.addWidget(clear, row, 2)
clear.clicked.connect(partial(self.set_shortcut, i, ""))
self.edit_widgets[i] = { submit = QtGui.QPushButton("Submit")
"experiment": experiment, submit.setIcon(QtGui.QApplication.style().standardIcon(
"priority": priority, QtGui.QStyle.SP_DialogOkButton))
"pipeline": pipeline 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 = QShortcut("F" + str(i+1), main_window)
shortcut.activated.connect(partial(self._activated, i)) 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): def _activated(self, nr):
info = self.shortcuts.get(nr, dict()) expname = self.shortcut_widgets[nr]["label"].text()
experiment = info.get("experiment", "") if expname:
if experiment and experiment != "<None>": try:
self.explorer.submit(info["pipeline"], experiment, rid = self.exp_manager.submit(expname)
info["priority"], None, False) 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): 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): def restore_state(self, state):
self.shortcuts = state for nr, expname in state.items():
self.set_shortcut(nr, expname)