예제 #1
0
파일: explorer.py 프로젝트: cr1901/artiq
    def __init__(self, main_window, status_bar,
                 explist_sub, schedule_sub,
                 schedule_ctl, repository_ctl):
        dockarea.Dock.__init__(self, "Explorer", size=(1500, 500))

        self.main_window = main_window
        self.status_bar = status_bar
        self.schedule_sub = schedule_sub
        self.schedule_ctl = schedule_ctl

        self.splitter = QtGui.QSplitter(QtCore.Qt.Horizontal)
        self.addWidget(self.splitter)

        grid = LayoutWidget()
        self.splitter.addWidget(grid)

        self.el = QtGui.QTreeView()
        self.el.setHeaderHidden(True)
        self.el.setSelectionBehavior(QtGui.QAbstractItemView.SelectItems)
        self.el.selectionChanged = self._selection_changed
        self.selected_key = None
        grid.addWidget(self.el, 0, 0, colspan=4)

        self.datetime = QtGui.QDateTimeEdit()
        self.datetime.setDisplayFormat("MMM d yyyy hh:mm:ss")
        self.datetime.setDate(QtCore.QDate.currentDate())
        self.datetime.dateTimeChanged.connect(self.enable_duedate)
        self.datetime_en = QtGui.QCheckBox("Due date:")
        grid.addWidget(self.datetime_en, 1, 0, colspan=2)
        grid.addWidget(self.datetime, 1, 2, colspan=2)

        self.pipeline = QtGui.QLineEdit()
        self.pipeline.setText("main")
        grid.addWidget(QtGui.QLabel("Pipeline:"), 2, 0, colspan=2)
        grid.addWidget(self.pipeline, 2, 2, colspan=2)

        self.priority = QtGui.QSpinBox()
        self.priority.setRange(-99, 99)
        grid.addWidget(QtGui.QLabel("Priority:"), 3, 0)
        grid.addWidget(self.priority, 3, 1)

        self.flush = QtGui.QCheckBox("Flush")
        self.flush.setToolTip("Flush the pipeline before starting the experiment")
        grid.addWidget(self.flush, 3, 2)

        self.log_level = QtGui.QComboBox()
        self.log_level.addItems(["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"])
        self.log_level.setCurrentIndex(1)
        self.log_level.setToolTip("Minimum level for log entry production")
        grid.addWidget(self.log_level, 3, 3)

        submit = QtGui.QPushButton("Submit")
        submit.setToolTip("Schedule the selected experiment (Ctrl+Return)")
        grid.addWidget(submit, 4, 0, colspan=4)
        submit.clicked.connect(self.submit_clicked)

        self.argeditor = _ArgumentEditor(self.main_window)
        self.splitter.addWidget(self.argeditor)
        self.splitter.setSizes([grid.minimumSizeHint().width(), 1000])
        self.argeditor_states = dict()
        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)
        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)
        scan_repository_action = QtGui.QAction("(Re)scan repository HEAD",
                                               self.el)
        def scan_repository():
            asyncio.ensure_future(repository_ctl.scan_async())
            self.status_bar.showMessage("Requested repository scan")
        scan_repository_action.triggered.connect(scan_repository)
        self.el.addAction(scan_repository_action)
예제 #2
0
파일: explorer.py 프로젝트: cr1901/artiq
class ExplorerDock(dockarea.Dock):
    def __init__(self, main_window, status_bar,
                 explist_sub, schedule_sub,
                 schedule_ctl, repository_ctl):
        dockarea.Dock.__init__(self, "Explorer", size=(1500, 500))

        self.main_window = main_window
        self.status_bar = status_bar
        self.schedule_sub = schedule_sub
        self.schedule_ctl = schedule_ctl

        self.splitter = QtGui.QSplitter(QtCore.Qt.Horizontal)
        self.addWidget(self.splitter)

        grid = LayoutWidget()
        self.splitter.addWidget(grid)

        self.el = QtGui.QTreeView()
        self.el.setHeaderHidden(True)
        self.el.setSelectionBehavior(QtGui.QAbstractItemView.SelectItems)
        self.el.selectionChanged = self._selection_changed
        self.selected_key = None
        grid.addWidget(self.el, 0, 0, colspan=4)

        self.datetime = QtGui.QDateTimeEdit()
        self.datetime.setDisplayFormat("MMM d yyyy hh:mm:ss")
        self.datetime.setDate(QtCore.QDate.currentDate())
        self.datetime.dateTimeChanged.connect(self.enable_duedate)
        self.datetime_en = QtGui.QCheckBox("Due date:")
        grid.addWidget(self.datetime_en, 1, 0, colspan=2)
        grid.addWidget(self.datetime, 1, 2, colspan=2)

        self.pipeline = QtGui.QLineEdit()
        self.pipeline.setText("main")
        grid.addWidget(QtGui.QLabel("Pipeline:"), 2, 0, colspan=2)
        grid.addWidget(self.pipeline, 2, 2, colspan=2)

        self.priority = QtGui.QSpinBox()
        self.priority.setRange(-99, 99)
        grid.addWidget(QtGui.QLabel("Priority:"), 3, 0)
        grid.addWidget(self.priority, 3, 1)

        self.flush = QtGui.QCheckBox("Flush")
        self.flush.setToolTip("Flush the pipeline before starting the experiment")
        grid.addWidget(self.flush, 3, 2)

        self.log_level = QtGui.QComboBox()
        self.log_level.addItems(["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"])
        self.log_level.setCurrentIndex(1)
        self.log_level.setToolTip("Minimum level for log entry production")
        grid.addWidget(self.log_level, 3, 3)

        submit = QtGui.QPushButton("Submit")
        submit.setToolTip("Schedule the selected experiment (Ctrl+Return)")
        grid.addWidget(submit, 4, 0, colspan=4)
        submit.clicked.connect(self.submit_clicked)

        self.argeditor = _ArgumentEditor(self.main_window)
        self.splitter.addWidget(self.argeditor)
        self.splitter.setSizes([grid.minimumSizeHint().width(), 1000])
        self.argeditor_states = dict()
        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)
        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)
        scan_repository_action = QtGui.QAction("(Re)scan repository HEAD",
                                               self.el)
        def scan_repository():
            asyncio.ensure_future(repository_ctl.scan_async())
            self.status_bar.showMessage("Requested repository scan")
        scan_repository_action.triggered.connect(scan_repository)
        self.el.addAction(scan_repository_action)

    def set_model(self, model):
        model.explorer = self
        self.explist_model = model
        self.el.setModel(model)

    def update_selection(self, selected, deselected):
        if deselected is not None:
            self.argeditor_states[deselected] = self.argeditor.save_state()

        if selected is not None:
            expinfo = self.explist_model.backing_store[selected]
            self.argeditor.set_arguments(expinfo["arguments"])
            if selected in self.argeditor_states:
                self.argeditor.restore_state(self.argeditor_states[selected])
            self.splitter.insertWidget(1, self.argeditor)
        self.selected_key = selected

    def _sel_to_key(self, selection):
        selection = selection.indexes()
        if selection:
            return self.explist_model.index_to_key(selection[0])
        else:
            return None

    def _selection_changed(self, selected, deselected):
        self.update_selection(self._sel_to_key(selected),
                              self._sel_to_key(deselected))

    def save_state(self):
        idx = self.el.selectedIndexes()
        if idx:
            key = self.explist_model.index_to_key(idx[0])
            if key is not None:
                self.argeditor_states[key] = self.argeditor.save_state()
        return {
            "argeditor": self.argeditor_states,
            "shortcuts": self.shortcuts.save_state()
        }

    def restore_state(self, state):
        try:
            argeditor_states = state["argeditor"]
            shortcuts_state = state["shortcuts"]
        except KeyError:
            return
        self.argeditor_states = argeditor_states
        self.shortcuts.restore_state(shortcuts_state)

    def enable_duedate(self):
        self.datetime_en.setChecked(True)

    async def submit_task(self, pipeline_name, file, class_name, arguments,
                          priority, due_date, flush):
        expid = {
            "log_level": getattr(logging, self.log_level.currentText()),
            "repo_rev": None,
            "file": file,
            "class_name": class_name,
            "arguments": arguments,
        }
        rid = await self.schedule_ctl.submit(pipeline_name, expid,
                                             priority, due_date, flush)
        self.status_bar.showMessage("Submitted RID {}".format(rid))

    def submit(self, pipeline, key, priority, due_date, flush):
        # TODO: refactor explorer and cleanup.
        # Argument editors should immediately modify the global state.
        expinfo = self.explist_model.backing_store[key]
        if key == self.selected_key:
            arguments = self.argeditor.get_argument_values(True)
            if arguments is None:
                # There has been an error. Displaying the error message box
                # was done by argeditor.
                return
        else:
            try:
                arguments = self.argeditor_states[key]["argument_values"]
            except KeyError:
                arguments = dict()
        asyncio.ensure_future(self.submit_task(pipeline, expinfo["file"],
                                               expinfo["class_name"],
                                               arguments, priority, due_date,
                                               flush))

    def submit_clicked(self):
        if self.selected_key is not None:
            if self.datetime_en.isChecked():
                due_date = self.datetime.dateTime().toMSecsSinceEpoch()/1000
            else:
                due_date = None
            self.submit(self.pipeline.text(),
                        self.selected_key,
                        self.priority.value(),
                        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]
            if self.schedule_sub.model is not None:
                current_schedule = self.schedule_sub.model.backing_store
                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)