class PipeLine(PipeLineDock): error_detected = QtCore.pyqtSignal(object, object, object) def __init__(self, parent): super(PipeLine, self).__init__(parent) self._tree = Tree() # Root branches self._branch_map = None self._items = [] # Test data picker self._test_data_picker = TestDataPicker(self) self._test_data_picker.setModal(True) self._active_thread = None self._init_title() return def _init_title(self): self.setWindowTitle("Pipeline") self.treeWidget.setSortingEnabled(False) self.treeWidget.headerItem().setText(0, "Waiting...") return def _set_branch_map(self, branch_map): self._branch_map = branch_map return def _set_title(self, title): self.treeWidget.headerItem().setText(0, title) return def _draw(self, shell): self._clear() for branch_dict in self._branch_map: HubCls = branch_dict["hub"] args = [] if "args" in branch_dict: args.extend(branch_dict["args"]) new_item = HubCls(self.treeWidget, branch_dict["name"], *args) new_item._activate(shell) self._items.append(new_item) return def _expand(self, shell): for item in self._items: item._expand(shell) return def _refresh(self, shell, expand=True): self._draw(shell) if expand: self._expand(shell) return def _clear(self): root = self.treeWidget.invisibleRootItem() for widget in self._items: widget._clear() if not isinstance(widget, HiddenHub): root.removeChild(widget) self._items = [] return def _find_item(self, item_title, item_class=None, root_item=None): if root_item is None: root_item = self for item in root_item._items: if item._title == item_title: if item_class is None or isinstance(item, item_class): return item result = self._find_item(item_title, item_class, item) if result is not None: return result return None def _make_menus(self, shell, position): item = self.treeWidget.currentItem() if isinstance(item, InputBranchItem): # Set the widget action self._test_data_picker.buttonBox.button( QtGui.QDialogButtonBox.Ok).clicked.disconnect() self._test_data_picker.buttonBox.button( QtGui.QDialogButtonBox.Ok).clicked.connect( lambda: self._read_test_data(shell, item)) self._test_data_picker.buttonBox.button( QtGui.QDialogButtonBox.Ok).clicked.connect( self._test_data_picker.close) # Build module and theme context menu if item._hub_title in ["Modules", "Assessment"]: menu = QtGui.QMenu() if item._hub_title == "Modules": menu.addAction('Inspect', lambda: item._inspect(shell)) menu.addAction('Reset', lambda: item._reset(shell)) menu.addAction('Load test data...', self._test_data_picker.show) menu.exec_(self.treeWidget.mapToGlobal(position)) elif isinstance(item, OutputBranchItem): # Build module context menu if item._hub_title == "Modules": menu = QtGui.QMenu() menu.addAction('Inspect', lambda: item._inspect(shell)) menu.exec_(self.treeWidget.mapToGlobal(position)) return def _set_top_item(self): self.treeWidget.itemClicked.emit(self.treeWidget.topLevelItem(0), -1) return def _read_auto(self, shell): self._tree.read_auto(shell.core, shell.project) return @QtCore.pyqtSlot(object, object) def _read_test_data(self, shell, item): self._active_thread = ThreadReadTest( item, shell, str(self._test_data_picker.pathLineEdit.text()), self._test_data_picker.overwriteBox.isChecked()) self._active_thread.start() self._active_thread.error_detected.connect(self._emit_error) self._active_thread.finished.connect(self._clear_active_thread) return @QtCore.pyqtSlot() def _clear_active_thread(self): self._active_thread = None return @QtCore.pyqtSlot(object, object, object) def _emit_error(self, etype, evalue, etraceback): self.error_detected.emit(etype, evalue, etraceback) return
class PipeLine(PipeLineDock): error_detected = QtCore.pyqtSignal(object, object, object) def __init__(self, parent): super(PipeLine, self).__init__(parent) self._tree = Tree() self._model = None self._proxy = None # Root branches self._branch_map = None self._controls = [] # Test data picker self._test_data_picker = TestDataPicker(self) self._test_data_picker.setModal(True) self._init_model() self._init_title() return def _init_model(self): self._model = QtGui.QStandardItemModel() self._model.setColumnCount(1) self._proxy = PipelineFilterProxyModel() self._proxy.setSourceModel(self._model) self._proxy.setDynamicSortFilter(True) self.treeView.setModel(self._proxy) self.filterLineEdit.textChanged.connect(self._update_filter) self.clearButton.clicked.connect(self._clear_filter) return def _init_title(self): self.setWindowTitle("Pipeline") self.treeView.setSortingEnabled(False) self._model.setHeaderData(0, QtCore.Qt.Horizontal, "Waiting...") return def _set_branch_map(self, branch_map): self._branch_map = branch_map return def _set_title(self, title): self._model.setHeaderData(0, QtCore.Qt.Horizontal, title) return def _draw(self, shell): self._clear() section_address = "" for branch_dict in self._branch_map: HubCls = branch_dict["hub"] args = [] if "args" in branch_dict: args.extend(branch_dict["args"]) # Model item if HubCls == SectionControl: section_address = branch_dict["name"] address = section_address section = "section" else: address = section_address + "." + branch_dict["name"] section = "hub" user_dict = { "address": address, "visible": True, "section": section, "status": None } name_item = QtGui.QStandardItem(branch_dict["name"]) name_item.setData(address, QtCore.Qt.UserRole) name_item.setData((user_dict, ), 33) self._model.appendRow(name_item) # Controller new_control = HubCls(address, branch_dict["name"], self.treeView, self._model, self._proxy, *args) new_control._init_ui(name_item) new_control._activate(shell, name_item) self._controls.append(new_control) return def _expand(self, shell): for controller in self._controls: controller._expand(shell) return def _refresh(self, shell, expand=True): self._draw(shell) if expand: self._expand(shell) return def _clear(self): root = self._model.invisibleRootItem() root.removeRows(0, root.rowCount()) self._controls = [] return def _find_controller(self, proxy_index=None, controller_title=None, controller_class=None, root=None): if proxy_index is None and controller_title is None: err_str = ("Either argument 'proxy_index' or 'controller_title' " "must be provided and 'proxy_index' will take " "precedence") raise ValueError(err_str) if root is None: root = self if proxy_index is not None: match = self._proxy.data(proxy_index, QtCore.Qt.UserRole) search_attr = "_address" else: match = controller_title search_attr = "_title" for controller in root._controls: if getattr(controller, search_attr) == match: if (controller_class is None or isinstance(controller, controller_class)): return controller result = self._find_controller(proxy_index, controller_title, controller_class, controller) if result is not None: return result return None def _make_menus(self, shell, position): proxy_indexes = self.treeView.selectedIndexes() proxy_index = proxy_indexes[0] controller = self._find_controller(proxy_index) if isinstance(controller, InputBranchControl): # Set the widget action self._test_data_picker.buttonBox.button( QtGui.QDialogButtonBox.Ok).clicked.disconnect() self._test_data_picker.buttonBox.button( QtGui.QDialogButtonBox.Ok).clicked.connect( lambda: self._read_test_data(shell, controller)) self._test_data_picker.buttonBox.button( QtGui.QDialogButtonBox.Ok).clicked.connect( self._test_data_picker.close) # Build module and theme context menu if controller._hub_title in ["Modules", "Assessment"]: menu = QtGui.QMenu() # Enable tooltips tips = lambda action: QtGui.QToolTip.showText( QtGui.QCursor.pos(), action.toolTip(), menu, menu.actionGeometry(action)) menu.hovered.connect(tips) if controller._hub_title == "Modules": # Can't reset or insepct unless the interface has executed connector = _get_connector(shell.project, "modules") active = connector.is_interface_completed( shell.core, shell.project, controller._title) action = menu.addAction('Inspect', lambda: controller._inspect(shell)) action.setToolTip('Inspect results following ' 'execution of this module') action.setEnabled(active) action = menu.addAction('Reset', lambda: controller._reset(shell)) action.setToolTip('Reset simulation prior to ' 'execution of this module') action.setEnabled(active) menu.addAction('Load test data...', self._test_data_picker.show) menu.exec_(self.treeView.mapToGlobal(position)) elif isinstance(controller, OutputBranchControl): # Build module context menu if controller._hub_title == "Modules": menu = QtGui.QMenu() menu.addAction('Inspect', lambda: controller._inspect(shell)) menu.exec_(self.treeView.mapToGlobal(position)) return def _set_top_item(self): index = self._controls[0]._get_index_from_address() proxy_index = self._proxy.mapFromSource(index) self.treeView.clicked.emit(proxy_index) return def _read_auto(self, shell): self._tree.read_auto(shell.core, shell.project) return @QtCore.pyqtSlot(str) def _update_filter(self, text): search = QtCore.QRegExp(text, QtCore.Qt.CaseInsensitive, QtCore.QRegExp.RegExp) self._proxy.setFilterRegExp(search) return @QtCore.pyqtSlot(str) def _repeat_filter(self): text = self.filterLineEdit.text() search = QtCore.QRegExp(text, QtCore.Qt.CaseInsensitive, QtCore.QRegExp.RegExp) self._proxy.setFilterRegExp(search) return @QtCore.pyqtSlot() def _clear_filter(self): self.filterLineEdit.clear() self._update_filter("") return @QtCore.pyqtSlot(object, object) def _read_test_data(self, shell, controller): if shell._active_thread is not None: shell._active_thread.wait() shell.read_test_data(controller, str(self._test_data_picker.pathLineEdit.text()), self._test_data_picker.overwriteBox.isChecked()) shell._active_thread.error_detected.connect(self._emit_error) return @QtCore.pyqtSlot(object, object, object) def _emit_error(self, etype, evalue, etraceback): self.error_detected.emit(etype, evalue, etraceback) return