diff --git a/artiq/frontend/artiq_gui.py b/artiq/frontend/artiq_gui.py index fd18f715c..d3f5f7d11 100755 --- a/artiq/frontend/artiq_gui.py +++ b/artiq/frontend/artiq_gui.py @@ -116,6 +116,7 @@ def main(): loop.run_until_complete(d_schedule.sub_connect( args.server, args.port_notify)) atexit.register(lambda: loop.run_until_complete(d_schedule.sub_close())) + d_explorer.get_current_schedule = d_schedule.get_current_schedule d_log = LogDock() smgr.register(d_log) diff --git a/artiq/gui/explorer.py b/artiq/gui/explorer.py index 90b9ac4ce..a885a15df 100644 --- a/artiq/gui/explorer.py +++ b/artiq/gui/explorer.py @@ -263,8 +263,7 @@ class ExplorerDock(dockarea.Dock): grid.addWidget(self.log_level, 3, 3) submit = QtGui.QPushButton("Submit") - submit.setShortcut("CTRL+RETURN") - submit.setToolTip("Schedule the selected experiment (CTRL+ENTER)") + submit.setToolTip("Schedule the selected experiment (Ctrl+Return)") grid.addWidget(submit, 4, 0, colspan=4) submit.clicked.connect(self.submit_clicked) @@ -276,6 +275,19 @@ class ExplorerDock(dockarea.Dock): self.shortcuts = ShortcutManager(self.main_window, self) self.el.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) + submit_action = QtGui.QAction("Submit", self.el) + submit_action.triggered.connect(self.submit_clicked) + submit_action.setShortcut("CTRL+RETURN") + self.el.addAction(submit_action) + reqterm_action = QtGui.QAction("Request termination of instances", self.el) + reqterm_action.triggered.connect(self.request_inst_term) + reqterm_action.setShortcut("CTRL+BACKSPACE") + self.el.addAction(reqterm_action) + + sep = QtGui.QAction(self.el) + 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) @@ -392,6 +404,28 @@ class ExplorerDock(dockarea.Dock): due_date, self.flush.isChecked()) + async def request_term_multiple(self, rids): + for rid in rids: + try: + await self.schedule_ctl.request_termination(rid) + except: + pass + + def request_inst_term(self): + if self.selected_key is not None: + expinfo = self.explist_model.backing_store[self.selected_key] + # attribute get_current_schedule must be set externally after + # instance creation + current_schedule = self.get_current_schedule() + rids = [] + for rid, desc in current_schedule.items(): + expid = desc["expid"] + if ("repo_rev" in expid # only consider runs from repository + and expid["file"] == expinfo["file"] + and expid["class_name"] == expinfo["class_name"]): + rids.append(rid) + asyncio.ensure_future(self.request_term_multiple(rids)) + def edit_shortcuts(self): experiments = sorted(self.explist_model.backing_store.keys()) self.shortcuts.edit(experiments) diff --git a/artiq/gui/schedule.py b/artiq/gui/schedule.py index 42ae01a1d..9971cd703 100644 --- a/artiq/gui/schedule.py +++ b/artiq/gui/schedule.py @@ -82,7 +82,6 @@ class ScheduleDock(dockarea.Dock): delete_action.setShortcut("SHIFT+DELETE") self.table.addAction(delete_action) - async def sub_connect(self, host, port): self.subscriber = Subscriber("schedule", self.init_schedule_model) await self.subscriber.connect(host, port) @@ -90,6 +89,13 @@ class ScheduleDock(dockarea.Dock): async def sub_close(self): await self.subscriber.close() + def get_current_schedule(self): + try: + table_model = self.table_model + except AttributeError: + return dict() + return table_model.backing_store + def init_schedule_model(self, init): self.table_model = _ScheduleModel(self.table, init) self.table.setModel(self.table_model)