diff --git a/artiq/dashboard/experiments.py b/artiq/dashboard/experiments.py index ff8264fbf..f156f4c6d 100644 --- a/artiq/dashboard/experiments.py +++ b/artiq/dashboard/experiments.py @@ -585,120 +585,3 @@ class ExperimentManager: for expurl, dock_state in state["docks"].items(): dock = self.open_experiment(expurl) dock.restore_state(dock_state) - - -class SimpleExperimentManager: - def __init__(self, main_window): - self.main_window = main_window - - self.submission_options = dict() - self.submission_arguments = dict() - - self.open_experiments = dict() - - def get_submission_options(self, expurl): - if expurl in self.submission_options: - return self.submission_options[expurl] - else: - # mutated by _ExperimentDock - options = { - "log_level": logging.WARNING - } - if expurl[:5] == "repo:": - options["repo_rev"] = None - self.submission_options[expurl] = options - return options - - def initialize_submission_arguments(self, expurl, arginfo): - arguments = OrderedDict() - for name, (procdesc, group) in arginfo.items(): - state = argty_to_entry[procdesc["ty"]].default_state(procdesc) - arguments[name] = { - "desc": procdesc, - "group": group, - "state": state # mutated by entries - } - self.submission_arguments[expurl] = arguments - return arguments - - def get_submission_arguments(self, expurl): - if expurl in self.submission_arguments: - return self.submission_arguments[expurl] - else: - if expurl[:5] != "repo:": - raise ValueError("Submission arguments must be preinitialized " - "when not using repository") - arginfo = self.explist[expurl[5:]]["arginfo"] - arguments = self.initialize_submission_arguments(expurl, arginfo) - return arguments - - def open_experiment(self, expurl): - if expurl in self.open_experiments: - dock = self.open_experiments[expurl] - self.main_window.centralWidget().setActiveSubWindow(dock) - return dock - try: - dock = _ExperimentDock(self, expurl) - except: - logger.warning("Failed to create experiment dock for %s, " - "attempting to reset arguments", expurl, - exc_info=True) - del self.submission_arguments[expurl] - dock = _ExperimentDock(self, expurl) - self.open_experiments[expurl] = dock - self.main_window.centralWidget().addSubWindow(dock) - dock.show() - dock.sigClosed.connect(partial(self.on_dock_closed, expurl)) - return dock - - def on_dock_closed(self, expurl): - del self.open_experiments[expurl] - - async def _submit_task(self, *args): - rid = await self.schedule_ctl.submit(*args) - self.main_window.statusBar().showMessage( - "Submitted RID {}".format(rid)) - - def submit(self, expurl): - file, class_name, _ = self.resolve_expurl(expurl) - options = self.get_submission_options(expurl) - arguments = self.get_submission_arguments(expurl) - - argument_values = dict() - for name, argument in arguments.items(): - entry_cls = argty_to_entry[argument["desc"]["ty"]] - argument_values[name] = entry_cls.state_to_value(argument["state"]) - - expid = { - "log_level": options["log_level"], - "file": file, - "class_name": class_name, - "arguments": argument_values, - } - if "repo_rev" in options: - expid["repo_rev"] = options["repo_rev"] - asyncio.ensure_future(self._submit_task(expid)) - - async def compute_arginfo(self, expurl): - file, class_name, use_repository = self.resolve_expurl(expurl) - description = await self.experiment_db_ctl.examine(file, - use_repository) - return description[class_name]["arginfo"] - - def save_state(self): - docks = {expurl: dock.save_state() - for expurl, dock in self.open_experiments.items()} - return { - "options": self.submission_options, - "arguments": self.submission_arguments, - "docks": docks - } - - def restore_state(self, state): - if self.open_experiments: - raise NotImplementedError - self.submission_options = state["options"] - self.submission_arguments = state["arguments"] - for expurl, dock_state in state["docks"].items(): - dock = self.open_experiment(expurl) - dock.restore_state(dock_state) diff --git a/artiq/frontend/artiq_browser.py b/artiq/frontend/artiq_browser.py index 5866475d1..d8b85151a 100755 --- a/artiq/frontend/artiq_browser.py +++ b/artiq/frontend/artiq_browser.py @@ -5,6 +5,7 @@ import asyncio import atexit import os import logging +from functools import partial from PyQt5 import QtCore, QtGui, QtWidgets from quamash import QEventLoop @@ -65,19 +66,23 @@ class MainWindow(QtWidgets.QMainWindow): self.restoreState(QtCore.QByteArray(state["state"])) -class MdiArea(QtWidgets.QMdiArea): +class ExperimentsArea(QtWidgets.QMdiArea): def __init__(self, root): QtWidgets.QMdiArea.__init__(self) self.pixmap = QtGui.QPixmap(os.path.join( artiq_dir, "gui", "logo20.svg")) self.current_dir = root self.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) + self.setFocusPolicy(QtCore.Qt.StrongFocus) + action = QtWidgets.QAction("&Open experiment", self) - # action.setShortcut(QtGui.QKeySequence("CTRL+o")) + action.setShortcut(QtGui.QKeySequence("CTRL+o")) action.setShortcutContext(QtCore.Qt.WidgetShortcut) action.triggered.connect(self.open_experiment) self.addAction(action) + self.open_experiments = [] + def paintEvent(self, event): QtWidgets.QMdiArea.paintEvent(self, event) painter = QtGui.QPainter(self.viewport()) @@ -86,12 +91,42 @@ class MdiArea(QtWidgets.QMdiArea): painter.setOpacity(0.5) painter.drawPixmap(x, y, self.pixmap) + def save_state(self): + return {"experiments": [experiment.save_state() + for experiment in self.open_experiments]} + + def restore_state(self, state): + if self.open_experiments: + raise NotImplementedError + for ex_state in state["experiments"]: + ex = self.load_experiment(ex_state["file"]) + ex.restore_state(ex_state) + def open_experiment(self): file, filter = QtWidgets.QFileDialog.getOpenFileName( self, "Open experiment", self.current_dir, "Experiments (*.py)") if not file: return - print(file) + logger.info("opening experiment %s", file) + self.load_experiment(file) + + def load_experiment(self, expurl): + try: + dock = _ExperimentDock(self, expurl) + except: + logger.warning("Failed to create experiment dock for %s, " + "attempting to reset arguments", expurl, + exc_info=True) + del self.submission_arguments[expurl] + dock = _ExperimentDock(self, expurl) + self.open_experiments.append(dock) + self.addSubWindow(dock) + dock.show() + dock.sigClosed.connect(partial(self.on_dock_closed, expurl)) + return dock + + def on_dock_closed(self, expurl): + del self.open_experiments[expurl] def main(): @@ -114,7 +149,11 @@ def main(): status_bar = QtWidgets.QStatusBar() main_window.setStatusBar(status_bar) - exp_manager = experiments.SimpleExperimentManager(main_window) + mdi_area = ExperimentsArea(args.browse_root) + mdi_area.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) + mdi_area.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) + main_window.setCentralWidget(mdi_area) + smgr.register(mdi_area) d_files = files.FilesDock(datasets_sub, args.browse_root, select=args.select) @@ -127,11 +166,6 @@ def main(): d_datasets = datasets.DatasetsDock(datasets_sub) smgr.register(d_datasets) - mdi_area = MdiArea(args.browse_root) - mdi_area.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) - mdi_area.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) - main_window.setCentralWidget(mdi_area) - main_window.addDockWidget(QtCore.Qt.LeftDockWidgetArea, d_files) main_window.addDockWidget(QtCore.Qt.BottomDockWidgetArea, d_applets) main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, d_datasets)