Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/artiq
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 741dfce38c3a
Choose a base ref
...
head repository: m-labs/artiq
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 08abc2e00acc
Choose a head ref
  • 8 commits
  • 5 files changed
  • 1 contributor

Commits on Dec 1, 2015

  1. Copy the full SHA
    ff4c030 View commit details
  2. Copy the full SHA
    bbabc7b View commit details
  3. Copy the full SHA
    f73c967 View commit details
  4. Copy the full SHA
    d39126d View commit details
  5. Copy the full SHA
    03f92f2 View commit details
  6. Copy the full SHA
    9baf54d View commit details
  7. Copy the full SHA
    de54f57 View commit details
  8. Copy the full SHA
    08abc2e View commit details
Showing with 154 additions and 110 deletions.
  1. +6 −4 artiq/frontend/artiq_gui.py
  2. +40 −9 artiq/gui/experiments.py
  3. +22 −22 artiq/gui/explorer.py
  4. +3 −3 artiq/gui/scan.py
  5. +83 −72 artiq/gui/shortcuts.py
10 changes: 6 additions & 4 deletions artiq/frontend/artiq_gui.py
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@
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, 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)

49 changes: 40 additions & 9 deletions artiq/gui/experiments.py
Original file line number Diff line number Diff line change
@@ -18,9 +18,9 @@ class _StringEntry(QtGui.QLineEdit):
def __init__(self, argument):
QtGui.QLineEdit.__init__(self)
self.setText(argument["state"])
def update():
argument["state"] = self.text()
self.editingFinished.connect(update)
def update(text):
argument["state"] = text()
self.textEdited.connect(update)

@staticmethod
def state_to_value(state):
@@ -187,6 +187,7 @@ def __init__(self, manager, expname):
self.argeditor = _ArgumentEditor(
manager.get_submission_arguments(expname))
self.addWidget(self.argeditor, 0, 0, colspan=5)
self.layout.setRowStretch(0, 1)

scheduling = manager.get_submission_scheduling(expname)
options = manager.get_submission_options(expname)
@@ -220,9 +221,9 @@ def update_datetime_en(checked):
self.addWidget(pipeline_name, 1, 3)

pipeline_name.setText(scheduling["pipeline_name"])
def update_pipeline_name():
scheduling["pipeline_name"] = pipeline_name.text()
pipeline_name.editingFinished.connect(update_pipeline_name)
def update_pipeline_name(text):
scheduling["pipeline_name"] = text
pipeline_name.textEdited.connect(update_pipeline_name)

priority = QtGui.QSpinBox()
priority.setRange(-99, 99)
@@ -278,14 +279,42 @@ def update_repo_rev():
repo_rev.editingFinished.connect(update_repo_rev)

submit = QtGui.QPushButton("Submit")
submit.setToolTip("Schedule the selected experiment (Ctrl+Return)")
submit.setIcon(QtGui.QApplication.style().standardIcon(
QtGui.QStyle.SP_DialogOkButton))
submit.setToolTip("Schedule the experiment (Ctrl+Return)")
submit.setShortcut("CTRL+RETURN")
submit.setSizePolicy(QtGui.QSizePolicy.Expanding,
QtGui.QSizePolicy.Expanding)
self.addWidget(submit, 1, 4, rowspan=3)
self.addWidget(submit, 1, 4, rowspan=2)
submit.clicked.connect(self.submit_clicked)

reqterm = QtGui.QPushButton("Terminate instances")
reqterm.setIcon(QtGui.QApplication.style().standardIcon(
QtGui.QStyle.SP_DialogCancelButton))
reqterm.setToolTip("Request termination of instances (Ctrl+Backspace)")
reqterm.setShortcut("CTRL+BACKSPACE")
reqterm.setSizePolicy(QtGui.QSizePolicy.Expanding,
QtGui.QSizePolicy.Expanding)
self.addWidget(reqterm, 3, 4)
reqterm.clicked.connect(self.reqterm_clicked)

def submit_clicked(self):
self.manager.submit(self.expname)
try:
self.manager.submit(self.expname)
except:
# May happen when experiment has been removed
# from repository/explist
logger.warning("failed to request termination of instances of %s",
self.expname, exc_info=True)

def reqterm_clicked(self):
try:
self.manager.request_inst_term(self.expname)
except:
# May happen when experiment has been removed
# from repository/explist
logger.warning("failed to request termination of instances of %s",
self.expname, exc_info=True)

def save_state(self):
return self.argeditor.save_state()
@@ -413,6 +442,8 @@ async def _request_term_multiple(self, rids):
rid, exc_info=True)

def request_inst_term(self, expname):
self.status_bar.showMessage("Requesting termination of all instances "
"of '{}'".format(expname))
expinfo = self.explist[expname]
rids = []
for rid, desc in self.schedule.items():
44 changes: 22 additions & 22 deletions artiq/gui/explorer.py
Original file line number Diff line number Diff line change
@@ -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 @@ def __setitem__(self, k, v):


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 @@ def __init__(self, main_window, status_bar, exp_manager,
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 @@ def __init__(self, main_window, status_bar, exp_manager,
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 @@ def reqterm_clicked(self):
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)
6 changes: 3 additions & 3 deletions artiq/gui/scan.py
Original file line number Diff line number Diff line change
@@ -104,9 +104,9 @@ def __init__(self, state):
self.value))

self.value.setText(" ".join([str(x) for x in state["sequence"]]))
def update():
state["sequence"] = [float(x) for x in self.value.text().split()]
self.value.editingFinished.connect(update)
def update(text):
state["sequence"] = [float(x) for x in text.split()]
self.value.textEdited.connect(update)


class ScanController(LayoutWidget):
155 changes: 83 additions & 72 deletions artiq/gui/shortcuts.py
Original file line number Diff line number Diff line change
@@ -1,98 +1,109 @@
import logging
from functools import partial

from quamash import QtGui
from quamash import QtGui, QtCore
from pyqtgraph import dockarea
try:
from quamash import QtWidgets
QShortcut = QtWidgets.QShortcut
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, 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("<b>" + title + "</b")
grid.addWidget(label, 0, n)
self.exp_manager = exp_manager
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())
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)

experiment = QtGui.QComboBox()
grid.addWidget(experiment, 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()
grid.addWidget(pipeline, row, 3)
pipeline.setText(existing_shortcut.get("pipeline", "main"))

self.edit_widgets[i] = {
"experiment": experiment,
"priority": priority,
"pipeline": pipeline
}

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()
self.addWidget(QtGui.QLabel("F" + str(i+1)), row, 0)

label = QtGui.QLabel()
label.setSizePolicy(QtGui.QSizePolicy.Ignored,
QtGui.QSizePolicy.Ignored)
self.addWidget(label, row, 1)

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, ""))

open = QtGui.QToolButton()
open.setIcon(QtGui.QApplication.style().standardIcon(
QtGui.QStyle.SP_DialogOpenButton))
self.addWidget(open, row, 3)
open.clicked.connect(partial(self._open_experiment, i))

submit = QtGui.QPushButton("Submit")
submit.setIcon(QtGui.QApplication.style().standardIcon(
QtGui.QStyle.SP_DialogOkButton))
self.addWidget(submit, row, 4)
submit.clicked.connect(partial(self._activated, i))

self.shortcut_widgets[i] = {
"label": label,
"clear": clear,
"open": open,
"submit": submit
}


class ShortcutManager:
def __init__(self, main_window, explorer):
for i in range(12):
shortcut = QShortcut("F" + str(i+1), main_window)
shortcut.setContext(QtCore.Qt.ApplicationShortcut)
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 != "<None>":
self.explorer.submit(info["pipeline"], experiment,
info["priority"], None, False)
expname = self.shortcut_widgets[nr]["label"].text()
if expname:
try:
self.exp_manager.submit(expname)
except:
# May happen when experiment has been removed
# from repository/explist
logger.warning("failed to submit experiment %s",
expname, exc_info=True)

def _open_experiment(self, nr):
expname = self.shortcut_widgets[nr]["label"].text()
if expname:
try:
self.exp_manager.open_experiment(expname)
except:
# May happen when experiment has been removed
# from repository/explist
logger.warning("failed to open experiment %s",
expname, exc_info=True)

def set_shortcut(self, nr, expname):
widgets = self.shortcut_widgets[nr]
widgets["label"].setText(expname)
if expname:
widgets["clear"].show()
widgets["open"].show()
widgets["submit"].show()
else:
widgets["clear"].hide()
widgets["open"].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)