def zoom_actions(self, parent): def zoom(s): """ Zoom in/out by factor `s`. scaleBy scales the view's bounds (the axis range) """ self.view_box.scaleBy((1 / s, 1 / s)) def fit_to_view(): self.viewbox.autoRange() zoom_in = QAction("Zoom in", parent, triggered=lambda: zoom(1.25)) zoom_in.setShortcuts([ QKeySequence(QKeySequence.ZoomIn), QKeySequence(parent.tr("Ctrl+=")) ]) zoom_out = QAction("Zoom out", parent, shortcut=QKeySequence.ZoomOut, triggered=lambda: zoom(1 / 1.25)) zoom_fit = QAction("Fit in view", parent, shortcut=QKeySequence(Qt.ControlModifier | Qt.Key_0), triggered=fit_to_view) parent.addActions([zoom_in, zoom_out, zoom_fit])
def tooltip_with_shortcut(tool_tip, shortcut: QKeySequence) -> str: text = [] if tool_tip: text.append("<span>{}</span>".format(tool_tip)) if not shortcut.isEmpty(): text.append("<kbd>{}</kbd>".format( shortcut.toString(QKeySequence.NativeText))) return " ".join(text)
def _setup_gui_labels(self): vlayout = QVBoxLayout() vlayout.setContentsMargins(0, 0, 0, 0) vlayout.setSpacing(1) self.labels_edit = QTreeView() self.labels_edit.setEditTriggers(QTreeView.CurrentChanged) self.labels_edit.setRootIsDecorated(False) self.labels_model = DictItemsModel() self.labels_edit.setModel(self.labels_model) self.labels_edit.selectionModel().selectionChanged.connect( self.on_label_selection_changed) # Necessary signals to know when the labels change self.labels_model.dataChanged.connect(self.on_labels_changed) self.labels_model.rowsInserted.connect(self.on_labels_changed) self.labels_model.rowsRemoved.connect(self.on_labels_changed) vlayout.addWidget(self.labels_edit) hlayout = QHBoxLayout() hlayout.setContentsMargins(0, 0, 0, 0) hlayout.setSpacing(1) self.add_label_action = QAction( "+", self, toolTip="Add a new label.", triggered=self.on_add_label, enabled=False, shortcut=QKeySequence(QKeySequence.New), ) self.remove_label_action = QAction( unicodedata.lookup("MINUS SIGN"), self, toolTip="Remove selected label.", triggered=self.on_remove_label, enabled=False, shortcut=QKeySequence(QKeySequence.Delete), ) button_size = gui.toolButtonSizeHint() button_size = QSize(button_size, button_size) button = QToolButton(self) button.setFixedSize(button_size) button.setDefaultAction(self.add_label_action) hlayout.addWidget(button) button = QToolButton(self) button.setFixedSize(button_size) button.setDefaultAction(self.remove_label_action) hlayout.addWidget(button) hlayout.addStretch(10) vlayout.addLayout(hlayout) self.main_form.addRow("Labels:", vlayout)
def __init__(self, *args, widgetResizable=False, **kwargs): super().__init__(*args, **kwargs) self.__widgetResizable = widgetResizable self.__zoomFactor = 100 zoomin = QAction( "Zoom in", self, objectName="zoom-in-action", shortcut=QKeySequence.ZoomIn, ) zoomout = QAction( "Zoom out", self, objectName="zoom-out-action", shortcut=QKeySequence.ZoomOut, ) zoomreset = QAction( "Actual Size", self, objectName="zoom-reset-action", shortcut=QKeySequence(Qt.ControlModifier | Qt.Key_0), ) fit = QAction( "Zoom to fit", self, objectName="zoom-to-fit-action", shortcut=QKeySequence(Qt.ControlModifier | Qt.Key_9), checkable=True, ) if hasattr(QAction, "setShortcutVisibleInContextMenu"): # Qt 5.10 for a in [zoomin, zoomout, zoomreset, fit]: a.setShortcutVisibleInContextMenu(True) @zoomin.triggered.connect def _(): self.setZoomFactor(self.__zoomFactor + 10) @zoomout.triggered.connect def _(): self.setZoomFactor(self.__zoomFactor - 10) @zoomreset.triggered.connect def _(): self.__zoomFactor = -1 self.setZoomFactor(100.) @fit.toggled.connect def _(state): self.setFitInView(state) self.addActions([zoomin, zoomout, zoomreset, fit]) self._actions = SimpleNamespace(zoomin=zoomin, zoomout=zoomout, zoomreset=zoomreset, fit=fit)
def _setup_library_box(self): self.library_view = QListView( editTriggers=QListView.DoubleClicked | QListView.EditKeyPressed, minimumWidth=200, sizePolicy=QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Expanding), ) self.library_view.setItemDelegate(WordListItemDelegate(self)) self.library_view.setModel(self.library_model) self.library_view.selectionModel().selectionChanged.connect( self.__on_library_selection_changed) self.__library_box.layout().setSpacing(1) self.__library_box.layout().addWidget(self.library_view) actions_widget = ModelActionsWidget() actions_widget.layout().setSpacing(1) action = QAction("+", self) action.setToolTip("Add a new word list to the library") action.triggered.connect(self.__on_add_word_list) actions_widget.addAction(action) action = QAction("\N{MINUS SIGN}", self) action.setToolTip("Remove word list from library") action.triggered.connect(self.__on_remove_word_list) actions_widget.addAction(action) action = QAction("Update", self) action.setToolTip("Save changes in the editor to library") action.setShortcut(QKeySequence(QKeySequence.Save)) action.triggered.connect(self.__on_update_word_list) actions_widget.addAction(action) gui.rubber(actions_widget.layout()) action = QAction("More", self, toolTip="More actions") new_from_file = QAction("Import Words from File", self) new_from_file.triggered.connect(self.__on_import_word_list) save_to_file = QAction("Save Words to File", self) save_to_file.setShortcut(QKeySequence(QKeySequence.SaveAs)) save_to_file.triggered.connect(self.__on_save_word_list) menu = QMenu(actions_widget) menu.addAction(new_from_file) menu.addAction(save_to_file) action.setMenu(menu) button = actions_widget.addAction(action) button.setPopupMode(QToolButton.InstantPopup) self.__library_box.layout().addWidget(actions_widget)
def _setup_gui_values(self): vlayout = QVBoxLayout() vlayout.setContentsMargins(0, 0, 0, 0) vlayout.setSpacing(1) self.values_edit = QListView() self.values_edit.setEditTriggers(QTreeView.CurrentChanged) self.values_model = itemmodels.PyListModel(flags=Qt.ItemIsSelectable | \ Qt.ItemIsEnabled | Qt.ItemIsEditable) self.values_edit.setModel(self.values_model) self.values_edit.selectionModel().selectionChanged.connect( self.on_value_selection_changed) self.values_model.dataChanged.connect(self.on_values_changed) vlayout.addWidget(self.values_edit) hlayout = QHBoxLayout() hlayout.setContentsMargins(0, 0, 0, 0) hlayout.setSpacing(1) self.move_value_up = QAction(unicodedata.lookup("UPWARDS ARROW"), self, toolTip="Move up.", triggered=self.move_up, enabled=False, shortcut=QKeySequence(QKeySequence.New)) self.move_value_down = QAction(unicodedata.lookup("DOWNWARDS ARROW"), self, toolTip="Move down.", triggered=self.move_down, enabled=False, shortcut=QKeySequence( QKeySequence.Delete)) button_size = gui.toolButtonSizeHint() button_size = QSize(button_size, button_size) button = QToolButton(self) button.setFixedSize(button_size) button.setDefaultAction(self.move_value_up) hlayout.addWidget(button) button = QToolButton(self) button.setFixedSize(button_size) button.setDefaultAction(self.move_value_down) hlayout.addWidget(button) hlayout.addStretch(10) vlayout.addLayout(hlayout) self.main_form.addRow("Values:", vlayout)
def keySequenceClicks(widget_, keySequence, extraModifiers=Qt.NoModifier): """Use QTest.keyClick to send a QKeySequence to a widget.""" # pylint: disable=line-too-long # This is based on a simplified version of http://stackoverflow.com/questions/14034209/convert-string-representation-of-keycode-to-qtkey-or-any-int-and-back. I added code to handle the case in which the resulting key contains a modifier (for example, Shift+Home). When I execute QTest.keyClick(widget, keyWithModifier), I get the error "ASSERT: "false" in file .\qasciikey.cpp, line 495". To fix this, the following code splits the key into a key and its modifier. # Bitmask for all modifier keys. modifierMask = int(Qt.ShiftModifier | Qt.ControlModifier | Qt.AltModifier | Qt.MetaModifier | Qt.KeypadModifier) ks = QKeySequence(keySequence) # For now, we don't handle a QKeySequence("Ctrl") or any other modified by itself. assert ks.count() > 0 for _, key in enumerate(ks): modifiers = Qt.KeyboardModifiers((key & modifierMask) | extraModifiers) key = key & ~modifierMask QTest.keyClick(widget_, key, modifiers, 10)
def main(argv): app = QApplication(argv) mw = QMainWindow() dock = CollapsibleDockWidget() w1 = QTreeView() w1.header().hide() w2 = QToolButton() w2.setFixedSize(38, 200) dock.setExpandedWidget(w1) dock.setCollapsedWidget(w2) mw.addDockWidget(Qt.LeftDockWidgetArea, dock) mw.setCentralWidget(QTextEdit()) mw.show() a = QAction("Expand", mw, checkable=True, shortcut=QKeySequence(Qt.ControlModifier | Qt.Key_D)) a.triggered[bool].connect(dock.setExpanded) mw.addAction(a) return app.exec()
def __init__(self, *args): super().__init__(*args) self.setAlignment(Qt.AlignTop | Qt.AlignLeft) self.__backgroundIcon = QIcon() self.__autoScroll = False self.__autoScrollMargin = 16 self.__autoScrollTimer = QTimer(self) self.__autoScrollTimer.timeout.connect(self.__autoScrollAdvance) # scale factor accumulating partial increments from wheel events self.__zoomLevel = 100 # effective scale level(rounded to whole integers) self.__effectiveZoomLevel = 100 self.__zoomInAction = QAction( self.tr("Zoom in"), self, objectName="action-zoom-in", shortcut=QKeySequence.ZoomIn, triggered=self.zoomIn, ) self.__zoomOutAction = QAction(self.tr("Zoom out"), self, objectName="action-zoom-out", shortcut=QKeySequence.ZoomOut, triggered=self.zoomOut) self.__zoomResetAction = QAction( self.tr("Reset Zoom"), self, objectName="action-zoom-reset", triggered=self.zoomReset, shortcut=QKeySequence(Qt.ControlModifier | Qt.Key_0))
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.show_report_action = QAction( "Show report", self, objectName="action-show-report", toolTip="Show a report window", shortcut=QKeySequence(Qt.ShiftModifier | Qt.Key_R), enabled=HAVE_REPORT, ) self.show_report_action.triggered.connect(self.show_report_view) self.open_report_action = QAction( "Open Report...", self, objectName="action-open-report", toolTip="Open a saved report", enabled=HAVE_REPORT, ) self.open_report_action.triggered.connect(self.open_report) self.reset_widget_settings_action = QAction( self.tr("Reset Widget Settings..."), self, triggered=self.reset_widget_settings) menubar = self.menuBar() # Insert the 'Load report' in the File menu ... _insert_action(menubar, "file-menu", "open-actions-separator", self.open_report_action) # ... and 'Show report' in the View menu. _insert_action(menubar, "view-menu", "view-visible-actions-separator", self.show_report_action) _insert_action(menubar, "options-menu", "canvas-addons-action", self.reset_widget_settings_action)
def add_popup_menu_option(self, label, function_action=None, key=None, icon=None, submenu=None): """ Add an option to the Control popup menu @param label: label of the option. @param function_action: function called when the option is selected. @param key: shortcut key @param icon: icon """ self.__create_popup_menu() menu = submenu if submenu else self._popup_menu if label == "-": return menu.addSeparator() else: action = QAction(label, self.form) if icon is not None: action.setIconVisibleInMenu(True) action.setIcon(icon if isinstance(icon, QIcon) else QIcon(icon) ) if key != None: action.setShortcut(QKeySequence(key)) if function_action: action.triggered.connect(function_action) menu.addAction(action) return action
def add_popup_menu_option(self, label, function_action=None, key=None, icon=None, menu=None): """ Add an option to the Control popup menu. :param str label: Label of the option :param function function_action: The function that should be executed when the menu is selected. :param str key: Short key. :param QIcon or str icon: Icon. :param QMenu submenu: Parent submenu to which the option should be added. If no value is set, then the option will be added to the main popup menu. .. code:: python control.add_popup_menu_option('option 0', function_action=self._do_something) submenu1 = control.add_popup_submenu('menu 1') submenu2 = control.add_popup_submenu('menu 2', submenu=submenu1) control.add_popup_menu_option('option 1', function_action=self._do_something, key='Control+Q', submenu=submenu2) """ self.__create_popup_menu() menu = menu if menu else self._popup_menu if label == "-": return menu.addSeparator() else: action = QAction(label, self.form) if icon is not None: action.setIconVisibleInMenu(True) action.setIcon(icon if isinstance(icon, QIcon) else QIcon(icon) ) if key != None: action.setShortcut(QKeySequence(key)) if function_action: action.triggered.connect(function_action) menu.addAction(action) return action
def add_zoom_actions(self, menu): zoom_in = QAction( "Zoom in", self, triggered=self.plot.vb.set_mode_zooming ) zoom_in.setShortcuts([Qt.Key_Z, QKeySequence(QKeySequence.ZoomIn)]) zoom_in.setShortcutContext(Qt.WidgetWithChildrenShortcut) self.addAction(zoom_in) if menu: menu.addAction(zoom_in) zoom_fit = QAction( "Zoom to fit", self, triggered=lambda x: (self.plot.vb.autoRange(), self.plot.vb.set_mode_panning()) ) zoom_fit.setShortcuts([Qt.Key_Backspace, QKeySequence(Qt.ControlModifier | Qt.Key_0)]) zoom_fit.setShortcutContext(Qt.WidgetWithChildrenShortcut) self.addAction(zoom_fit) if menu: menu.addAction(zoom_fit)
def __call__(self, master, model_selected, model_other): self.master = master params_view = { "sizePolicy": QSizePolicy(*SIZE_POLICY_ADAPTING), "selectionMode": QListView.ExtendedSelection, "dragEnabled": True, "defaultDropAction": Qt.MoveAction, "dragDropOverwriteMode": False, "dragDropMode": QListView.DragDrop, } self.view_selected = view = gui.listView(widget=master.controlArea, master=master, box="Displayed Axes", **params_view) view.box.setMinimumHeight(120) view.viewport().setAcceptDrops(True) delete = QAction( "Delete", view, shortcut=QKeySequence(Qt.Key_Delete), triggered=self.__deactivate_selection, ) view.addAction(delete) self.model_selected = model = model_selected model.rowsInserted.connect(master.invalidate_plot) model.rowsRemoved.connect(master.invalidate_plot) model.rowsMoved.connect(master.invalidate_plot) view.setModel(model) addClassLabel = QAction("+", master, toolTip="Add new class label", triggered=self._action_add) removeClassLabel = QAction( unicodedata.lookup("MINUS SIGN"), master, toolTip="Remove selected class label", triggered=self.__deactivate_selection, ) add_remove = itemmodels.ModelActionsWidget( [addClassLabel, removeClassLabel], master) add_remove.layout().addStretch(10) add_remove.layout().setSpacing(1) add_remove.setSizePolicy(*SIZE_POLICY_FIXED) view.box.layout().addWidget(add_remove) self.add_remove = add_remove self.box = add_remove.buttons[1] self.model_other = model_other
def __new__(cls, *args, captionTitle=None, **kwargs): self = super().__new__(cls, None, cls.get_flags()) QDialog.__init__(self, None, self.get_flags()) OWComponent.__init__(self) WidgetMessagesMixin.__init__(self) WidgetSignalsMixin.__init__(self) stored_settings = kwargs.get('stored_settings', None) if self.settingsHandler: self.settingsHandler.initialize(self, stored_settings) self.signalManager = kwargs.get('signal_manager', None) self.__env = _asmappingproxy(kwargs.get("env", {})) self.graphButton = None self.report_button = None OWWidget.widget_id += 1 self.widget_id = OWWidget.widget_id captionTitle = self.name if captionTitle is None else captionTitle # must be set without invoking setCaption self.captionTitle = captionTitle self.setWindowTitle(captionTitle) self.setFocusPolicy(Qt.StrongFocus) self.__blocking = False # flag indicating if the widget's position was already restored self.__was_restored = False self.__statusMessage = "" self.__msgwidget = None self.__msgchoice = 0 self.left_side = None self.controlArea = self.mainArea = self.buttonsArea = None self.splitter = None if self.want_basic_layout: self.set_basic_layout() sc = QShortcut(QKeySequence(Qt.ShiftModifier | Qt.Key_F1), self) sc.activated.connect(self.__quicktip) sc = QShortcut(QKeySequence.Copy, self) sc.activated.connect(self.copy_to_clipboard) if self.controlArea is not None: # Otherwise, the first control has focus self.controlArea.setFocus(Qt.ActiveWindowFocusReason) return self
def __init__(self, parent, plot): super().__init__(parent, plot) self._item = None self._start_pos = None self._selection_rect = None self._mouse_dragging = False self._delete_action = QAction( "Delete", self, shortcutContext=Qt.WindowShortcut ) self._delete_action.setShortcuts([QKeySequence.Delete, QKeySequence("Backspace")]) self._delete_action.triggered.connect(self.delete)
def main(args): # pragma: no cover # pylint: disable=import-outside-toplevel,protected-access from AnyQt.QtWidgets import QApplication, QAction from AnyQt.QtGui import QKeySequence app = QApplication(args) view = StickyGraphicsView() scene = QGraphicsScene(view) scene.setBackgroundBrush(QBrush(Qt.lightGray, Qt.CrossPattern)) view.setScene(scene) scene.addRect(QRectF(0, 0, 300, 20), Qt.red, QBrush(Qt.red, Qt.BDiagPattern)) scene.addRect(QRectF(0, 25, 300, 100)) scene.addRect(QRectF(0, 130, 300, 20), Qt.darkGray, QBrush(Qt.darkGray, Qt.BDiagPattern)) view.setHeaderSceneRect(QRectF(0, 0, 300, 20)) view.setFooterSceneRect(QRectF(0, 130, 300, 20)) view.show() zoomin = QAction("Zoom in", view, shortcut=QKeySequence.ZoomIn) zoomout = QAction("Zoom out", view, shortcut=QKeySequence.ZoomOut) zoomreset = QAction("Reset", view, shortcut=QKeySequence(Qt.ControlModifier | Qt.Key_0)) view._zoom = 100 def set_zoom(zoom): if view._zoom != zoom: view._zoom = zoom view.setTransform(QTransform.fromScale(*(view._zoom / 100, ) * 2)) zoomout.setEnabled(zoom >= 20) zoomin.setEnabled(zoom <= 300) @zoomin.triggered.connect def _(): set_zoom(view._zoom + 10) @zoomout.triggered.connect def _(): set_zoom(view._zoom - 10) @zoomreset.triggered.connect def _(): set_zoom(100) view.addActions([zoomin, zoomout, zoomreset]) return app.exec()
def add_popup_menu_option(self, label='', function_action=None, key=None, item=None, icon=None, submenu=None): """ Add an option to the Control popup menu @param label: label of the option. @param function_action: function called when the option is selected. @param key: shortcut key @param key: shortcut key """ action = super(ControlTree, self).add_popup_menu_option(label, function_action, key, submenu) if item is not None: if label == "-": self._items[id(item)].append(label) else: action = QAction(label, self.form) if icon is not None: action.setIconVisibleInMenu(True) action.setIcon(QIcon(icon)) if key is not None: action.setShortcut(QKeySequence(key)) if function_action: action.triggered.connect(function_action) # Associate action to the item. if id(item) not in self._items.keys(): self._items.update({id(item): []}) self._items[id(item)].append(action) ########################## return action return action
def __init__(self): super().__init__() self.libraryListSource = [] for name in self.signal_names: setattr(self, name, {}) self._cachedDocuments = {} self.infoBox = gui.vBox(self.controlArea, 'Info') gui.label( self.infoBox, self, "<p>Execute python script.</p><p>Input variables:<ul><li> " + "<li>".join(map("in_{0}, in_{0}s".format, self.signal_names)) + "</ul></p><p>Output variables:<ul><li>" + "<li>".join(map("out_{0}".format, self.signal_names)) + "</ul></p>") self.libraryList = itemmodels.PyListModel( [], self, flags=Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable) self.libraryList.wrap(self.libraryListSource) self.controlBox = gui.vBox(self.controlArea, 'Library') self.controlBox.layout().setSpacing(1) self.libraryView = QListView( editTriggers=QListView.DoubleClicked | QListView.EditKeyPressed, sizePolicy=QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Preferred)) self.libraryView.setItemDelegate(ScriptItemDelegate(self)) self.libraryView.setModel(self.libraryList) self.libraryView.selectionModel().selectionChanged.connect( self.onSelectedScriptChanged) self.controlBox.layout().addWidget(self.libraryView) w = itemmodels.ModelActionsWidget() self.addNewScriptAction = action = QAction("+", self) action.setToolTip("Add a new script to the library") action.triggered.connect(self.onAddScript) w.addAction(action) action = QAction(unicodedata.lookup("MINUS SIGN"), self) action.setToolTip("Remove script from library") action.triggered.connect(self.onRemoveScript) w.addAction(action) action = QAction("Update", self) action.setToolTip("Save changes in the editor to library") action.setShortcut(QKeySequence(QKeySequence.Save)) action.triggered.connect(self.commitChangesToLibrary) w.addAction(action) action = QAction("More", self, toolTip="More actions") new_from_file = QAction("Import Script from File", self) save_to_file = QAction("Save Selected Script to File", self) restore_saved = QAction("Undo Changes to Selected Script", self) save_to_file.setShortcut(QKeySequence(QKeySequence.SaveAs)) new_from_file.triggered.connect(self.onAddScriptFromFile) save_to_file.triggered.connect(self.saveScript) restore_saved.triggered.connect(self.restoreSaved) menu = QMenu(w) menu.addAction(new_from_file) menu.addAction(save_to_file) menu.addAction(restore_saved) action.setMenu(menu) button = w.addAction(action) button.setPopupMode(QToolButton.InstantPopup) w.layout().setSpacing(1) self.controlBox.layout().addWidget(w) self.execute_button = gui.button(self.controlArea, self, 'Run', callback=self.commit) run = QAction("Run script", self, triggered=self.commit, shortcut=QKeySequence(Qt.ControlModifier | Qt.Key_R)) self.addAction(run) self.splitCanvas = QSplitter(Qt.Vertical, self.mainArea) self.mainArea.layout().addWidget(self.splitCanvas) self.defaultFont = defaultFont = \ "Monaco" if sys.platform == "darwin" else "Courier" self.textBox = gui.vBox(self, 'Python Script') self.splitCanvas.addWidget(self.textBox) self.text = PythonScriptEditor(self) self.textBox.layout().addWidget(self.text) self.textBox.setAlignment(Qt.AlignVCenter) self.text.setTabStopWidth(4) self.text.modificationChanged[bool].connect(self.onModificationChanged) self.saveAction = action = QAction("&Save", self.text) action.setToolTip("Save script to file") action.setShortcut(QKeySequence(QKeySequence.Save)) action.setShortcutContext(Qt.WidgetWithChildrenShortcut) action.triggered.connect(self.saveScript) self.consoleBox = gui.vBox(self, 'Console') self.splitCanvas.addWidget(self.consoleBox) self.console = PythonConsole({}, self) self.consoleBox.layout().addWidget(self.console) self.console.document().setDefaultFont(QFont(defaultFont)) self.consoleBox.setAlignment(Qt.AlignBottom) self.console.setTabStopWidth(4) self.splitCanvas.setSizes([2, 1]) self.setAcceptDrops(True) self.controlArea.layout().addStretch(10) self._restoreState() self.settingsAboutToBePacked.connect(self._saveState)
def __init__(self): super().__init__() for name in self.signal_names: setattr(self, name, []) self.splitCanvas = QSplitter(Qt.Vertical, self.mainArea) self.mainArea.layout().addWidget(self.splitCanvas) # Styling self.defaultFont = defaultFont = ( 'Menlo' if sys.platform == 'darwin' else 'Courier' if sys.platform in ['win32', 'cygwin'] else 'DejaVu Sans Mono') self.defaultFontSize = defaultFontSize = 13 self.editorBox = gui.vBox(self, box="Editor", spacing=4) self.splitCanvas.addWidget(self.editorBox) darkMode = QApplication.instance().property('darkMode') scheme_name = 'Dark' if darkMode else 'Light' syntax_highlighting_scheme = SYNTAX_HIGHLIGHTING_STYLES[scheme_name] self.pygments_style_class = make_pygments_style(scheme_name) eFont = QFont(defaultFont) eFont.setPointSize(defaultFontSize) # Fake Signature self.func_sig = func_sig = FunctionSignature( self.editorBox, syntax_highlighting_scheme, eFont) # Editor editor = PythonEditor(self) editor.setFont(eFont) editor.setup_completer_appearance((300, 180), eFont) # Fake return return_stmt = ReturnStatement(self.editorBox, syntax_highlighting_scheme, eFont) self.return_stmt = return_stmt # Match indentation textEditBox = QWidget(self.editorBox) textEditBox.setLayout(QHBoxLayout()) char_4_width = QFontMetrics(eFont).horizontalAdvance('0000') @editor.viewport_margins_updated.connect def _(width): func_sig.setIndent(width) textEditMargin = max(0, round(char_4_width - width)) return_stmt.setIndent(textEditMargin + width) textEditBox.layout().setContentsMargins(textEditMargin, 0, 0, 0) self.text = editor textEditBox.layout().addWidget(editor) self.editorBox.layout().addWidget(func_sig) self.editorBox.layout().addWidget(textEditBox) self.editorBox.layout().addWidget(return_stmt) self.editorBox.setAlignment(Qt.AlignVCenter) self.text.setTabStopWidth(4) self.text.modificationChanged[bool].connect(self.onModificationChanged) # Controls self.editor_controls = gui.vBox(self.controlArea, box='Preferences') self.vim_box = gui.hBox(self.editor_controls, spacing=20) self.vim_indicator = VimIndicator(self.vim_box) vim_sp = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) vim_sp.setRetainSizeWhenHidden(True) self.vim_indicator.setSizePolicy(vim_sp) def enable_vim_mode(): editor.vimModeEnabled = self.vimModeEnabled self.vim_indicator.setVisible(self.vimModeEnabled) enable_vim_mode() gui.checkBox(self.vim_box, self, 'vimModeEnabled', 'Vim mode', tooltip="Only for the coolest.", callback=enable_vim_mode) self.vim_box.layout().addWidget(self.vim_indicator) @editor.vimModeIndicationChanged.connect def _(color, text): self.vim_indicator.indicator_color = color self.vim_indicator.indicator_text = text self.vim_indicator.update() # Library self.libraryListSource = [] self._cachedDocuments = {} self.libraryList = itemmodels.PyListModel( [], self, flags=Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable) self.libraryList.wrap(self.libraryListSource) self.controlBox = gui.vBox(self.controlArea, 'Library') self.controlBox.layout().setSpacing(1) self.libraryView = QListView( editTriggers=QListView.DoubleClicked | QListView.EditKeyPressed, sizePolicy=QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Preferred)) self.libraryView.setItemDelegate(ScriptItemDelegate(self)) self.libraryView.setModel(self.libraryList) self.libraryView.selectionModel().selectionChanged.connect( self.onSelectedScriptChanged) self.controlBox.layout().addWidget(self.libraryView) w = itemmodels.ModelActionsWidget() self.addNewScriptAction = action = QAction("+", self) action.setToolTip("Add a new script to the library") action.triggered.connect(self.onAddScript) w.addAction(action) action = QAction(unicodedata.lookup("MINUS SIGN"), self) action.setToolTip("Remove script from library") action.triggered.connect(self.onRemoveScript) w.addAction(action) action = QAction("Update", self) action.setToolTip("Save changes in the editor to library") action.setShortcut(QKeySequence(QKeySequence.Save)) action.triggered.connect(self.commitChangesToLibrary) w.addAction(action) action = QAction("More", self, toolTip="More actions") new_from_file = QAction("Import Script from File", self) save_to_file = QAction("Save Selected Script to File", self) restore_saved = QAction("Undo Changes to Selected Script", self) save_to_file.setShortcut(QKeySequence(QKeySequence.SaveAs)) new_from_file.triggered.connect(self.onAddScriptFromFile) save_to_file.triggered.connect(self.saveScript) restore_saved.triggered.connect(self.restoreSaved) menu = QMenu(w) menu.addAction(new_from_file) menu.addAction(save_to_file) menu.addAction(restore_saved) action.setMenu(menu) button = w.addAction(action) button.setPopupMode(QToolButton.InstantPopup) w.layout().setSpacing(1) self.controlBox.layout().addWidget(w) self.execute_button = gui.button(self.buttonsArea, self, 'Run', callback=self.commit) self.run_action = QAction("Run script", self, triggered=self.commit, shortcut=QKeySequence(Qt.ControlModifier | Qt.Key_R)) self.addAction(self.run_action) self.saveAction = action = QAction("&Save", self.text) action.setToolTip("Save script to file") action.setShortcut(QKeySequence(QKeySequence.Save)) action.setShortcutContext(Qt.WidgetWithChildrenShortcut) action.triggered.connect(self.saveScript) self.consoleBox = gui.vBox(self.splitCanvas, 'Console') self.console = PythonConsole({}, self) self.consoleBox.layout().addWidget(self.console) self.console.document().setDefaultFont(QFont(defaultFont)) self.consoleBox.setAlignment(Qt.AlignBottom) self.splitCanvas.setSizes([2, 1]) self.controlArea.layout().addStretch(10) self._restoreState() self.settingsAboutToBePacked.connect(self._saveState)
def __add_widget_for_node(self, node): # type: (SchemeNode) -> None item = self.__item_for_node.get(node) if item is not None: return if self.__workflow is None: return if node not in self.__workflow.nodes: return if node in self.__init_queue: self.__init_queue.remove(node) item = Item(node, None, -1) # Insert on the node -> item mapping. self.__item_for_node[node] = item log.debug("Creating widget for node %s", node) try: w = self.create_widget_for_node(node) except Exception: # pylint: disable=broad-except log.critical("", exc_info=True) lines = traceback.format_exception(*sys.exc_info()) text = "".join(lines) errorwidget = QLabel(textInteractionFlags=Qt.TextSelectableByMouse, wordWrap=True, objectName="widgetmanager-error-placeholder", text="<pre>" + escape(text) + "</pre>") item.errorwidget = errorwidget node.set_state_message(UserMessage(text, UserMessage.Error, "")) raise else: item.widget = w self.__item_for_widget[w] = item self.__set_float_on_top_flag(w) if w.windowIcon().isNull(): desc = node.description w.setWindowIcon(icon_loader.from_description(desc).get(desc.icon)) if not w.windowTitle(): w.setWindowTitle(node.title) w.installEventFilter(self.__activation_monitor) raise_canvas = QAction( self.tr("Raise Canvas to Front"), w, objectName="action-canvas-raise-canvas", toolTip=self.tr("Raise containing canvas workflow window"), shortcut=QKeySequence(Qt.ControlModifier | Qt.Key_Up)) raise_canvas.triggered.connect(self.__on_activate_parent) raise_descendants = QAction( self.tr("Raise Descendants"), w, objectName="action-canvas-raise-descendants", toolTip=self.tr("Raise all immediate descendants of this node"), shortcut=QKeySequence(Qt.ControlModifier | Qt.ShiftModifier | Qt.Key_Right)) raise_descendants.triggered.connect( partial(self.__on_raise_descendants, node)) raise_ancestors = QAction( self.tr("Raise Ancestors"), w, objectName="action-canvas-raise-ancestors", toolTip=self.tr("Raise all immediate ancestors of this node"), shortcut=QKeySequence(Qt.ControlModifier | Qt.ShiftModifier | Qt.Key_Left)) raise_ancestors.triggered.connect( partial(self.__on_raise_ancestors, node)) w.addActions([raise_canvas, raise_descendants, raise_ancestors]) # send all the post creation notification events workflow = self.__workflow assert workflow is not None inputs = workflow.find_links(sink_node=node) for link in inputs: ev = LinkEvent(LinkEvent.InputLinkAdded, link) QCoreApplication.sendEvent(w, ev) outputs = workflow.find_links(source_node=node) for link in outputs: ev = LinkEvent(LinkEvent.OutputLinkAdded, link) QCoreApplication.sendEvent(w, ev) self.widget_for_node_added.emit(node, w)
def __init__(self): super().__init__() self.matrix = None self.items = None self.linkmatrix = None self.root = None self._displayed_root = None self.cutoff_height = 0.0 gui.comboBox(self.controlArea, self, "linkage", items=LINKAGE, box="Linkage", callback=self._invalidate_clustering) model = itemmodels.VariableListModel() model[:] = self.basic_annotations box = gui.widgetBox(self.controlArea, "Annotations") self.label_cb = cb = combobox.ComboBoxSearch( minimumContentsLength=14, sizeAdjustPolicy=QComboBox.AdjustToMinimumContentsLengthWithIcon) cb.setModel(model) cb.setCurrentIndex(cb.findData(self.annotation, Qt.EditRole)) def on_annotation_activated(): self.annotation = cb.currentData(Qt.EditRole) self._update_labels() cb.activated.connect(on_annotation_activated) def on_annotation_changed(value): cb.setCurrentIndex(cb.findData(value, Qt.EditRole)) self.connect_control("annotation", on_annotation_changed) box.layout().addWidget(self.label_cb) box = gui.radioButtons(self.controlArea, self, "pruning", box="Pruning", callback=self._invalidate_pruning) grid = QGridLayout() box.layout().addLayout(grid) grid.addWidget(gui.appendRadioButton(box, "None", addToLayout=False), 0, 0) self.max_depth_spin = gui.spin(box, self, "max_depth", minv=1, maxv=100, callback=self._invalidate_pruning, keyboardTracking=False, addToLayout=False) grid.addWidget( gui.appendRadioButton(box, "Max depth:", addToLayout=False), 1, 0) grid.addWidget(self.max_depth_spin, 1, 1) self.selection_box = gui.radioButtons( self.controlArea, self, "selection_method", box="Selection", callback=self._selection_method_changed) grid = QGridLayout() self.selection_box.layout().addLayout(grid) grid.addWidget( gui.appendRadioButton(self.selection_box, "Manual", addToLayout=False), 0, 0) grid.addWidget( gui.appendRadioButton(self.selection_box, "Height ratio:", addToLayout=False), 1, 0) self.cut_ratio_spin = gui.spin(self.selection_box, self, "cut_ratio", 0, 100, step=1e-1, spinType=float, callback=self._selection_method_changed, addToLayout=False) self.cut_ratio_spin.setSuffix("%") grid.addWidget(self.cut_ratio_spin, 1, 1) grid.addWidget( gui.appendRadioButton(self.selection_box, "Top N:", addToLayout=False), 2, 0) self.top_n_spin = gui.spin(self.selection_box, self, "top_n", 1, 20, callback=self._selection_method_changed, addToLayout=False) grid.addWidget(self.top_n_spin, 2, 1) self.zoom_slider = gui.hSlider(self.controlArea, self, "zoom_factor", box="Zoom", minValue=-6, maxValue=3, step=1, ticks=True, createLabel=False, callback=self.__update_font_scale) zoom_in = QAction("Zoom in", self, shortcut=QKeySequence.ZoomIn, triggered=self.__zoom_in) zoom_out = QAction("Zoom out", self, shortcut=QKeySequence.ZoomOut, triggered=self.__zoom_out) zoom_reset = QAction("Reset zoom", self, shortcut=QKeySequence(Qt.ControlModifier | Qt.Key_0), triggered=self.__zoom_reset) self.addActions([zoom_in, zoom_out, zoom_reset]) self.controlArea.layout().addStretch() gui.auto_send(self.buttonsArea, self, "autocommit") self.scene = QGraphicsScene(self) self.view = StickyGraphicsView( self.scene, horizontalScrollBarPolicy=Qt.ScrollBarAlwaysOff, verticalScrollBarPolicy=Qt.ScrollBarAlwaysOn, alignment=Qt.AlignLeft | Qt.AlignVCenter) self.mainArea.layout().setSpacing(1) self.mainArea.layout().addWidget(self.view) def axis_view(orientation): ax = AxisItem(orientation=orientation, maxTickLength=7) ax.mousePressed.connect(self._activate_cut_line) ax.mouseMoved.connect(self._activate_cut_line) ax.mouseReleased.connect(self._activate_cut_line) ax.setRange(1.0, 0.0) return ax self.top_axis = axis_view("top") self.bottom_axis = axis_view("bottom") self._main_graphics = QGraphicsWidget() scenelayout = QGraphicsGridLayout() scenelayout.setHorizontalSpacing(10) scenelayout.setVerticalSpacing(10) self._main_graphics.setLayout(scenelayout) self.scene.addItem(self._main_graphics) self.dendrogram = DendrogramWidget() self.dendrogram.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.dendrogram.selectionChanged.connect(self._invalidate_output) self.dendrogram.selectionEdited.connect(self._selection_edited) self.labels = TextListWidget() self.labels.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred) self.labels.setAlignment(Qt.AlignLeft) self.labels.setMaximumWidth(200) scenelayout.addItem(self.top_axis, 0, 0, alignment=Qt.AlignLeft | Qt.AlignVCenter) scenelayout.addItem(self.dendrogram, 1, 0, alignment=Qt.AlignLeft | Qt.AlignVCenter) scenelayout.addItem(self.labels, 1, 1, alignment=Qt.AlignLeft | Qt.AlignVCenter) scenelayout.addItem(self.bottom_axis, 2, 0, alignment=Qt.AlignLeft | Qt.AlignVCenter) self.view.viewport().installEventFilter(self) self._main_graphics.installEventFilter(self) self.top_axis.setZValue(self.dendrogram.zValue() + 10) self.bottom_axis.setZValue(self.dendrogram.zValue() + 10) self.cut_line = SliderLine(self.top_axis, orientation=Qt.Horizontal) self.cut_line.valueChanged.connect(self._dendrogram_slider_changed) self.dendrogram.geometryChanged.connect(self._dendrogram_geom_changed) self._set_cut_line_visible(self.selection_method == 1) self.__update_font_scale()
def create_widget_instance(self, node): """ Create a OWWidget instance for the node. """ desc = node.description klass = widget = None initialized = False error = None # First try to actually retrieve the class. try: klass = name_lookup(desc.qualified_name) except (ImportError, AttributeError): sys.excepthook(*sys.exc_info()) error = "Could not import {0!r}\n\n{1}".format( node.description.qualified_name, traceback.format_exc()) except Exception: sys.excepthook(*sys.exc_info()) error = "An unexpected error during import of {0!r}\n\n{1}".format( node.description.qualified_name, traceback.format_exc()) if klass is None: widget = mock_error_owwidget(node, error) initialized = True if widget is None: log.info("WidgetManager: Creating '%s.%s' instance '%s'.", klass.__module__, klass.__name__, node.title) widget = klass.__new__( klass, None, captionTitle=node.title, signal_manager=self.signal_manager(), stored_settings=node.properties, # NOTE: env is a view of the real env and reflects # changes to the environment. env=self.scheme().runtime_env()) initialized = False # Init the node/widget mapping and state before calling __init__ # Some OWWidgets might already send data in the constructor # (should this be forbidden? Raise a warning?) triggering the signal # manager which would request the widget => node mapping or state # Furthermore they can (though they REALLY REALLY REALLY should not) # explicitly call qApp.processEvents. assert node not in self.__widget_for_node self.__widget_for_node[node] = widget self.__node_for_widget[widget] = node self.__widget_processing_state[widget] = WidgetManager.Initializing self.__initstate_for_node[node] = \ WidgetManager.PartiallyInitialized(node, widget) if not initialized: try: widget.__init__() except Exception: sys.excepthook(*sys.exc_info()) msg = traceback.format_exc() msg = "Could not create {0!r}\n\n{1}".format( node.description.name, msg) # remove state tracking for widget ... del self.__widget_for_node[node] del self.__node_for_widget[widget] del self.__widget_processing_state[widget] # ... and substitute it with a mock error widget. widget = mock_error_owwidget(node, msg) self.__widget_for_node[node] = widget self.__node_for_widget[widget] = node self.__widget_processing_state[widget] = 0 self.__initstate_for_node[node] = \ WidgetManager.Materialized(node, widget) self.__initstate_for_node[node] = \ WidgetManager.Materialized(node, widget) # Clear Initializing flag self.__widget_processing_state[widget] &= ~WidgetManager.Initializing node.title_changed.connect(widget.setCaption) # Widget's info/warning/error messages. widget.messageActivated.connect(self.__on_widget_state_changed) widget.messageDeactivated.connect(self.__on_widget_state_changed) # Widget's statusTip node.set_status_message(widget.statusMessage()) widget.statusMessageChanged.connect(node.set_status_message) # Widget's progress bar value state. widget.progressBarValueChanged.connect(node.set_progress) # Widget processing state (progressBarInit/Finished) # and the blocking state. widget.processingStateChanged.connect( self.__on_processing_state_changed) widget.blockingStateChanged.connect(self.__on_blocking_state_changed) if widget.isBlocking(): # A widget can already enter blocking state in __init__ self.__widget_processing_state[widget] |= self.BlockingUpdate if widget.processingState != 0: # It can also start processing (initialization of resources, ...) self.__widget_processing_state[widget] |= self.ProcessingUpdate node.set_processing_state(1) node.set_progress(widget.progressBarValue) # Install a help shortcut on the widget help_action = widget.findChild(QAction, "action-help") if help_action is not None: help_action.setEnabled(True) help_action.setVisible(True) help_action.triggered.connect(self.__on_help_request) # Up shortcut (activate/open parent) up_shortcut = QShortcut(QKeySequence(Qt.ControlModifier + Qt.Key_Up), widget) up_shortcut.activated.connect(self.__on_activate_parent) # Call setters only after initialization. widget.setWindowIcon(icon_loader.from_description(desc).get(desc.icon)) widget.setCaption(node.title) # befriend class Report widget._Report__report_view = self.scheme().report_view self.__set_float_on_top_flag(widget) # Schedule an update with the signal manager, due to the cleared # implicit Initializing flag self.signal_manager()._update() return widget
def __init__(self): super().__init__() box = gui.vBox(self.mainArea, True, margin=0) self.graph = OWScatterPlotGraph(self, box, "ScatterPlot") box.layout().addWidget(self.graph.plot_widget) plot = self.graph.plot_widget axispen = QPen(self.palette().color(QPalette.Text)) axis = plot.getAxis("bottom") axis.setPen(axispen) axis = plot.getAxis("left") axis.setPen(axispen) self.data = None # Orange.data.Table self.subset_data = None # Orange.data.Table self.data_metas_X = None # self.data, where primitive metas are moved to X self.sql_data = None # Orange.data.sql.table.SqlTable self.attribute_selection_list = None # list of Orange.data.Variable self.__timer = QTimer(self, interval=1200) self.__timer.timeout.connect(self.add_data) common_options = dict( labelWidth=50, orientation=Qt.Horizontal, sendSelectedValue=True, valueType=str) box = gui.vBox(self.controlArea, "Axis Data") dmod = DomainModel self.xy_model = DomainModel(dmod.MIXED, valid_types=dmod.PRIMITIVE) self.cb_attr_x = gui.comboBox( box, self, "attr_x", label="Axis x:", callback=self.update_attr, model=self.xy_model, **common_options) self.cb_attr_y = gui.comboBox( box, self, "attr_y", label="Axis y:", callback=self.update_attr, model=self.xy_model, **common_options) vizrank_box = gui.hBox(box) gui.separator(vizrank_box, width=common_options["labelWidth"]) self.vizrank, self.vizrank_button = ScatterPlotVizRank.add_vizrank( vizrank_box, self, "Find Informative Projections", self.set_attr) gui.separator(box) gui.valueSlider( box, self, value='graph.jitter_size', label='Jittering: ', values=self.jitter_sizes, callback=self.reset_graph_data, labelFormat=lambda x: "None" if x == 0 else ("%.1f %%" if x < 1 else "%d %%") % x) gui.checkBox( gui.indentedBox(box), self, 'graph.jitter_continuous', 'Jitter numeric values', callback=self.reset_graph_data) self.sampling = gui.auto_commit( self.controlArea, self, "auto_sample", "Sample", box="Sampling", callback=self.switch_sampling, commit=lambda: self.add_data(1)) self.sampling.setVisible(False) g = self.graph.gui g.point_properties_box(self.controlArea) self.models = [self.xy_model] + g.points_models box = gui.vBox(self.controlArea, "Plot Properties") g.add_widgets([g.ShowLegend, g.ShowGridLines], box) gui.checkBox( box, self, value='graph.tooltip_shows_all', label='Show all data on mouse hover') self.cb_class_density = gui.checkBox( box, self, value='graph.class_density', label='Show class density', callback=self.update_density) self.cb_reg_line = gui.checkBox( box, self, value='graph.show_reg_line', label='Show regression line', callback=self.update_regression_line) gui.checkBox( box, self, 'graph.label_only_selected', 'Label only selected points', callback=self.graph.update_labels) self.zoom_select_toolbar = g.zoom_select_toolbar( gui.vBox(self.controlArea, "Zoom/Select"), nomargin=True, buttons=[g.StateButtonsBegin, g.SimpleSelect, g.Pan, g.Zoom, g.StateButtonsEnd, g.ZoomReset] ) buttons = self.zoom_select_toolbar.buttons buttons[g.Zoom].clicked.connect(self.graph.zoom_button_clicked) buttons[g.Pan].clicked.connect(self.graph.pan_button_clicked) buttons[g.SimpleSelect].clicked.connect(self.graph.select_button_clicked) buttons[g.ZoomReset].clicked.connect(self.graph.reset_button_clicked) self.controlArea.layout().addStretch(100) self.icons = gui.attributeIconDict p = self.graph.plot_widget.palette() self.graph.set_palette(p) gui.auto_commit(self.controlArea, self, "auto_send_selection", "Send Selection", "Send Automatically") def zoom(s): """Zoom in/out by factor `s`.""" viewbox = plot.getViewBox() # scaleBy scales the view's bounds (the axis range) viewbox.scaleBy((1 / s, 1 / s)) def fit_to_view(): viewbox = plot.getViewBox() viewbox.autoRange() zoom_in = QAction( "Zoom in", self, triggered=lambda: zoom(1.25) ) zoom_in.setShortcuts([QKeySequence(QKeySequence.ZoomIn), QKeySequence(self.tr("Ctrl+="))]) zoom_out = QAction( "Zoom out", self, shortcut=QKeySequence.ZoomOut, triggered=lambda: zoom(1 / 1.25) ) zoom_fit = QAction( "Fit in view", self, shortcut=QKeySequence(Qt.ControlModifier | Qt.Key_0), triggered=fit_to_view ) self.addActions([zoom_in, zoom_out, zoom_fit])
def __init__(self, parent, select_fn=None): QWidget.__init__(self) OWComponent.__init__(self, parent) self.parent = parent self.select_fn = select_fn self.selection_type = SELECTMANY self.saving_enabled = hasattr(self.parent, "save_graph") self.selection_enabled = True self.viewtype = INDIVIDUAL # required bt InteractiveViewBox self.highlighted = None self.data_points = None self.data_values = None self.data_imagepixels = None self.selection = None self.plotview = pg.PlotWidget(background="w", viewBox=InteractiveViewBox(self)) self.plot = self.plotview.getPlotItem() self.plot.scene().installEventFilter( HelpEventDelegate(self.help_event, self)) layout = QVBoxLayout() self.setLayout(layout) self.layout().setContentsMargins(0, 0, 0, 0) self.layout().addWidget(self.plotview) self.img = ImageItemNan() self.img.setOpts(axisOrder='row-major') self.plot.addItem(self.img) self.plot.vb.setAspectLocked() self.plot.scene().sigMouseMoved.connect(self.plot.vb.mouseMovedEvent) layout = QGridLayout() self.plotview.setLayout(layout) self.button = QPushButton("View", self.plotview) self.button.setAutoDefault(False) layout.setRowStretch(1, 1) layout.setColumnStretch(1, 1) layout.addWidget(self.button, 0, 0) view_menu = MenuFocus(self) self.button.setMenu(view_menu) actions = [] zoom_in = QAction( "Zoom in", self, triggered=self.plot.vb.set_mode_zooming ) zoom_in.setShortcuts([Qt.Key_Z, QKeySequence(QKeySequence.ZoomIn)]) zoom_in.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(zoom_in) zoom_fit = QAction( "Zoom to fit", self, triggered=lambda x: (self.plot.vb.autoRange(), self.plot.vb.set_mode_panning()) ) zoom_fit.setShortcuts([Qt.Key_Backspace, QKeySequence(Qt.ControlModifier | Qt.Key_0)]) zoom_fit.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(zoom_fit) select_square = QAction( "Select (square)", self, triggered=self.plot.vb.set_mode_select_square, ) select_square.setShortcuts([Qt.Key_S]) select_square.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(select_square) select_polygon = QAction( "Select (polygon)", self, triggered=self.plot.vb.set_mode_select_polygon, ) select_polygon.setShortcuts([Qt.Key_P]) select_polygon.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(select_polygon) if self.saving_enabled: save_graph = QAction( "Save graph", self, triggered=self.save_graph, ) save_graph.setShortcuts([QKeySequence(Qt.ControlModifier | Qt.Key_I)]) actions.append(save_graph) view_menu.addActions(actions) self.addActions(actions) common_options = dict( labelWidth=50, orientation=Qt.Horizontal, sendSelectedValue=True, valueType=str) choose_xy = QWidgetAction(self) box = gui.vBox(self) box.setFocusPolicy(Qt.TabFocus) self.xy_model = DomainModel(DomainModel.METAS | DomainModel.CLASSES, valid_types=DomainModel.PRIMITIVE) self.cb_attr_x = gui.comboBox( box, self, "attr_x", label="Axis x:", callback=self.update_attr, model=self.xy_model, **common_options) self.cb_attr_y = gui.comboBox( box, self, "attr_y", label="Axis y:", callback=self.update_attr, model=self.xy_model, **common_options) box.setFocusProxy(self.cb_attr_x) self.color_cb = gui.comboBox(box, self, "palette_index", label="Color:", labelWidth=50, orientation=Qt.Horizontal) self.color_cb.setIconSize(QSize(64, 16)) palettes = _color_palettes self.palette_index = min(self.palette_index, len(palettes) - 1) model = color_palette_model(palettes, self.color_cb.iconSize()) model.setParent(self) self.color_cb.setModel(model) self.color_cb.activated.connect(self.update_color_schema) self.color_cb.setCurrentIndex(self.palette_index) form = QFormLayout( formAlignment=Qt.AlignLeft, labelAlignment=Qt.AlignLeft, fieldGrowthPolicy=QFormLayout.AllNonFixedFieldsGrow ) lowslider = gui.hSlider( box, self, "threshold_low", minValue=0.0, maxValue=1.0, step=0.05, ticks=True, intOnly=False, createLabel=False, callback=self.update_color_schema) highslider = gui.hSlider( box, self, "threshold_high", minValue=0.0, maxValue=1.0, step=0.05, ticks=True, intOnly=False, createLabel=False, callback=self.update_color_schema) form.addRow("Low:", lowslider) form.addRow("High:", highslider) box.layout().addLayout(form) choose_xy.setDefaultWidget(box) view_menu.addAction(choose_xy) self.markings_integral = [] self.lsx = None # info about the X axis self.lsy = None # info about the Y axis self.data = None self.data_ids = {}
def __init__(self): super().__init__() for name in self.signal_names: setattr(self, name, {}) for s in self.libraryListSource: s.flags = 0 self._cachedDocuments = {} self.infoBox = gui.vBox(self.controlArea, '信息') gui.label( self.infoBox, self, "<p>执行Python脚本。</p><p>输入变量:<ul><li> " + "<li>".join(map("in_{0}, in_{0}s".format, self.signal_names)) + "</ul></p><p>输出变量:<ul><li>" + "<li>".join(map("out_{0}".format, self.signal_names)) + "</ul></p>") self.libraryList = itemmodels.PyListModel( [], self, flags=Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable) self.libraryList.wrap(self.libraryListSource) self.controlBox = gui.vBox(self.controlArea, '脚本库') self.controlBox.layout().setSpacing(1) self.libraryView = QListView( editTriggers=QListView.DoubleClicked | QListView.EditKeyPressed, sizePolicy=QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Preferred)) self.libraryView.setItemDelegate(ScriptItemDelegate(self)) self.libraryView.setModel(self.libraryList) self.libraryView.selectionModel().selectionChanged.connect( self.onSelectedScriptChanged) self.controlBox.layout().addWidget(self.libraryView) w = itemmodels.ModelActionsWidget() self.addNewScriptAction = action = QAction("+", self) action.setToolTip("向库中添加新脚本") action.triggered.connect(self.onAddScript) w.addAction(action) action = QAction(unicodedata.lookup("MINUS SIGN"), self) action.setToolTip("从库中删除脚本") action.triggered.connect(self.onRemoveScript) w.addAction(action) action = QAction("保存", self) action.setToolTip("将编辑器中的更改的脚本保存到库中") action.setShortcut(QKeySequence(QKeySequence.Save)) action.triggered.connect(self.commitChangesToLibrary) w.addAction(action) action = QAction("更多", self, toolTip="更多操作") new_from_file = QAction("从文件导入脚本", self) save_to_file = QAction("将所选脚本保存到文件", self) save_to_file.setShortcut(QKeySequence(QKeySequence.SaveAs)) new_from_file.triggered.connect(self.onAddScriptFromFile) save_to_file.triggered.connect(self.saveScript) menu = QMenu(w) menu.addAction(new_from_file) menu.addAction(save_to_file) action.setMenu(menu) button = w.addAction(action) button.setPopupMode(QToolButton.InstantPopup) w.layout().setSpacing(1) self.controlBox.layout().addWidget(w) auto = gui.auto_commit(self.controlArea, self, "auto_execute", "运行", checkbox_label="对新数据自动运行") self.execute_button, self.autobox = auto.button, auto.checkbox self.splitCanvas = QSplitter(Qt.Vertical, self.mainArea) self.mainArea.layout().addWidget(self.splitCanvas) self.defaultFont = defaultFont = \ "Monaco" if sys.platform == "darwin" else "Courier" self.textBox = gui.vBox(self, 'Python脚本') self.splitCanvas.addWidget(self.textBox) self.text = PythonScriptEditor(self) self.textBox.layout().addWidget(self.text) self.textBox.setAlignment(Qt.AlignVCenter) self.text.setTabStopWidth(4) self.text.modificationChanged[bool].connect(self.onModificationChanged) self.saveAction = action = QAction("&Save", self.text) action.setToolTip("Save script to file") action.setShortcut(QKeySequence(QKeySequence.Save)) action.setShortcutContext(Qt.WidgetWithChildrenShortcut) action.triggered.connect(self.saveScript) self.consoleBox = gui.vBox(self, '控制台') self.splitCanvas.addWidget(self.consoleBox) self.console = PythonConsole({}, self) self.consoleBox.layout().addWidget(self.console) self.console.document().setDefaultFont(QFont(defaultFont)) self.consoleBox.setAlignment(Qt.AlignBottom) self.console.setTabStopWidth(4) select_row(self.libraryView, self.currentScriptIndex) self.splitCanvas.setSizes([2, 1]) if self.splitterState is not None: self.splitCanvas.restoreState(QByteArray(self.splitterState)) self.splitCanvas.splitterMoved[int, int].connect(self.onSpliterMoved) self.controlArea.layout().addStretch(1) self.resize(800, 600)
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) form = self.layout().itemAt(0) assert isinstance(form, QFormLayout) #: A list model of discrete variable's values. self.values_model = itemmodels.PyListModel( flags=Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable) vlayout = QVBoxLayout(spacing=1, margin=0) self.values_edit = QListView(editTriggers=QListView.DoubleClicked | QListView.EditKeyPressed) self.values_edit.setItemDelegate(CategoriesEditDelegate(self)) self.values_edit.setModel(self.values_model) self.values_model.dataChanged.connect(self.on_values_changed) self.values_edit.selectionModel().selectionChanged.connect( self.on_value_selection_changed) self.values_model.layoutChanged.connect( self.on_value_selection_changed) self.values_model.rowsMoved.connect(self.on_value_selection_changed) vlayout.addWidget(self.values_edit) hlayout = QHBoxLayout(spacing=1, margin=0) self.categories_action_group = group = QActionGroup( self, objectName="action-group-categories", enabled=False) self.move_value_up = QAction( "\N{UPWARDS ARROW}", group, toolTip="Move the selected item up.", shortcut=QKeySequence(Qt.ControlModifier | Qt.AltModifier | Qt.Key_BracketLeft), shortcutContext=Qt.WidgetShortcut, ) self.move_value_up.triggered.connect(self.move_up) self.move_value_down = QAction( "\N{DOWNWARDS ARROW}", group, toolTip="Move the selected item down.", shortcut=QKeySequence(Qt.ControlModifier | Qt.AltModifier | Qt.Key_BracketRight), shortcutContext=Qt.WidgetShortcut, ) self.move_value_down.triggered.connect(self.move_down) self.add_new_item = QAction( "+", group, objectName="action-add-item", toolTip="Append a new item.", shortcut=QKeySequence(QKeySequence.New), shortcutContext=Qt.WidgetShortcut, ) self.remove_item = QAction( "\N{MINUS SIGN}", group, objectName="action-remove-item", toolTip="Delete the selected item.", shortcut=QKeySequence(QKeySequence.Delete), shortcutContext=Qt.WidgetShortcut, ) self.add_new_item.triggered.connect(self._add_category) self.remove_item.triggered.connect(self._remove_category) button1 = FixedSizeButton(self, defaultAction=self.move_value_up, accessibleName="Move up") button2 = FixedSizeButton(self, defaultAction=self.move_value_down, accessibleName="Move down") button3 = FixedSizeButton(self, defaultAction=self.add_new_item, accessibleName="Add") button4 = FixedSizeButton(self, defaultAction=self.remove_item, accessibleName="Remove") self.values_edit.addActions([ self.move_value_up, self.move_value_down, self.add_new_item, self.remove_item ]) hlayout.addWidget(button1) hlayout.addWidget(button2) hlayout.addSpacing(3) hlayout.addWidget(button3) hlayout.addWidget(button4) hlayout.addStretch(10) vlayout.addLayout(hlayout) form.insertRow(1, "Values:", vlayout) QWidget.setTabOrder(self.name_edit, self.values_edit) QWidget.setTabOrder(self.values_edit, button1) QWidget.setTabOrder(button1, button2) QWidget.setTabOrder(button2, button3) QWidget.setTabOrder(button3, button4)
def __init__(self, parent=None, **kwargs): super().__init__(parent, **kwargs) self.var = None # type: Optional[Variable] layout = QVBoxLayout() self.setLayout(layout) self.form = form = QFormLayout( fieldGrowthPolicy=QFormLayout.AllNonFixedFieldsGrow, objectName="editor-form-layout") layout.addLayout(self.form) self.name_edit = QLineEdit(objectName="name-editor") self.name_edit.editingFinished.connect( lambda: self.name_edit.isModified() and self.on_name_changed()) form.addRow("Name:", self.name_edit) vlayout = QVBoxLayout(margin=0, spacing=1) self.labels_edit = view = QTreeView( objectName="annotation-pairs-edit", rootIsDecorated=False, editTriggers=QTreeView.DoubleClicked | QTreeView.EditKeyPressed, ) self.labels_model = model = DictItemsModel() view.setModel(model) view.selectionModel().selectionChanged.connect( self.on_label_selection_changed) agrp = QActionGroup(view, objectName="annotate-action-group") action_add = QAction("+", self, objectName="action-add-label", toolTip="Add a new label.", shortcut=QKeySequence(QKeySequence.New), shortcutContext=Qt.WidgetShortcut) action_delete = QAction("\N{MINUS SIGN}", self, objectName="action-delete-label", toolTip="Remove selected label.", shortcut=QKeySequence(QKeySequence.Delete), shortcutContext=Qt.WidgetShortcut) agrp.addAction(action_add) agrp.addAction(action_delete) view.addActions([action_add, action_delete]) def add_label(): row = [QStandardItem(), QStandardItem()] model.appendRow(row) idx = model.index(model.rowCount() - 1, 0) view.setCurrentIndex(idx) view.edit(idx) def remove_label(): rows = view.selectionModel().selectedRows(0) if rows: assert len(rows) == 1 idx = rows[0].row() model.removeRow(idx) action_add.triggered.connect(add_label) action_delete.triggered.connect(remove_label) agrp.setEnabled(False) self.add_label_action = action_add self.remove_label_action = action_delete # Necessary signals to know when the labels change model.dataChanged.connect(self.on_labels_changed) model.rowsInserted.connect(self.on_labels_changed) model.rowsRemoved.connect(self.on_labels_changed) vlayout.addWidget(self.labels_edit) hlayout = QHBoxLayout() hlayout.setContentsMargins(0, 0, 0, 0) button = FixedSizeButton( self, defaultAction=self.add_label_action, accessibleName="Add", ) hlayout.addWidget(button) button = FixedSizeButton( self, defaultAction=self.remove_label_action, accessibleName="Remove", ) hlayout.addWidget(button) hlayout.addStretch(10) vlayout.addLayout(hlayout) form.addRow("Labels:", vlayout)
def __init__(self, parent): QWidget.__init__(self) OWComponent.__init__(self, parent) SelectionGroupMixin.__init__(self) ImageColorSettingMixin.__init__(self) ImageZoomMixin.__init__(self) ConcurrentMixin.__init__(self) self.parent = parent self.selection_type = SELECTMANY self.saving_enabled = True self.selection_enabled = True self.viewtype = INDIVIDUAL # required bt InteractiveViewBox self.highlighted = None self.data_points = None self.data_values = None self.data_imagepixels = None self.data_valid_positions = None self.plotview = pg.GraphicsLayoutWidget() self.plot = pg.PlotItem(background="w", viewBox=InteractiveViewBox(self)) self.plotview.addItem(self.plot) self.legend = ImageColorLegend() self.plotview.addItem(self.legend) self.plot.scene().installEventFilter( HelpEventDelegate(self.help_event, self)) layout = QVBoxLayout() self.setLayout(layout) self.layout().setContentsMargins(0, 0, 0, 0) self.layout().addWidget(self.plotview) self.img = ImageItemNan() self.img.setOpts(axisOrder='row-major') self.plot.addItem(self.img) self.vis_img = pg.ImageItem() self.vis_img.setOpts(axisOrder='row-major') self.plot.vb.setAspectLocked() self.plot.scene().sigMouseMoved.connect(self.plot.vb.mouseMovedEvent) layout = QGridLayout() self.plotview.setLayout(layout) self.button = QPushButton("Menu", self.plotview) self.button.setAutoDefault(False) layout.setRowStretch(1, 1) layout.setColumnStretch(1, 1) layout.addWidget(self.button, 0, 0) view_menu = MenuFocus(self) self.button.setMenu(view_menu) # prepare interface according to the new context self.parent.contextAboutToBeOpened.connect( lambda x: self.init_interface_data(x[0])) actions = [] self.add_zoom_actions(view_menu) select_square = QAction( "Select (square)", self, triggered=self.plot.vb.set_mode_select_square, ) select_square.setShortcuts([Qt.Key_S]) select_square.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(select_square) select_polygon = QAction( "Select (polygon)", self, triggered=self.plot.vb.set_mode_select_polygon, ) select_polygon.setShortcuts([Qt.Key_P]) select_polygon.setShortcutContext(Qt.WidgetWithChildrenShortcut) actions.append(select_polygon) if self.saving_enabled: save_graph = QAction( "Save graph", self, triggered=self.save_graph, ) save_graph.setShortcuts( [QKeySequence(Qt.ControlModifier | Qt.Key_I)]) actions.append(save_graph) view_menu.addActions(actions) self.addActions(actions) common_options = dict(labelWidth=50, orientation=Qt.Horizontal, sendSelectedValue=True) choose_xy = QWidgetAction(self) box = gui.vBox(self) box.setFocusPolicy(Qt.TabFocus) self.xy_model = DomainModel(DomainModel.METAS | DomainModel.CLASSES, valid_types=DomainModel.PRIMITIVE) self.cb_attr_x = gui.comboBox(box, self, "attr_x", label="Axis x:", callback=self.update_attr, model=self.xy_model, **common_options) self.cb_attr_y = gui.comboBox(box, self, "attr_y", label="Axis y:", callback=self.update_attr, model=self.xy_model, **common_options) box.setFocusProxy(self.cb_attr_x) box.layout().addWidget(self.color_settings_box()) choose_xy.setDefaultWidget(box) view_menu.addAction(choose_xy) self.lsx = None # info about the X axis self.lsy = None # info about the Y axis self.data = None self.data_ids = {}
def __init__(self, parent=None, select=SELECTNONE): QWidget.__init__(self) OWComponent.__init__(self, parent) self.parent = parent self.selection_type = select self.saving_enabled = hasattr(self.parent, "save_graph") self.clear_data(init=True) self.plotview = pg.PlotWidget(background="w", viewBox=InteractiveViewBox(self)) self.plot = self.plotview.getPlotItem() self.plot.setDownsampling(auto=True, mode="peak") self.markings = [] self.vLine = pg.InfiniteLine(angle=90, movable=False) self.hLine = pg.InfiniteLine(angle=0, movable=False) self.proxy = pg.SignalProxy(self.plot.scene().sigMouseMoved, rateLimit=20, slot=self.mouseMoved, delay=0.1) self.plot.scene().sigMouseMoved.connect(self.plot.vb.mouseMovedEvent) self.plot.vb.sigRangeChanged.connect(self.resized) self.pen_mouse = pg.mkPen(color=(0, 0, 255), width=2) self.pen_normal = defaultdict(lambda: pg.mkPen(color=(200, 200, 200, 127), width=1)) self.pen_subset = defaultdict(lambda: pg.mkPen(color=(0, 0, 0, 127), width=1)) self.pen_selected = defaultdict(lambda: pg.mkPen(color=(0, 0, 0, 127), width=2, style=Qt.DotLine)) self.label = pg.TextItem("", anchor=(1, 0)) self.label.setText("", color=(0, 0, 0)) self.discrete_palette = None QPixmapCache.setCacheLimit(max(QPixmapCache.cacheLimit(), 100 * 1024)) self.curves_cont = PlotCurvesItem() self.important_decimals = 4, 4 self.MOUSE_RADIUS = 20 self.clear_graph() #interface settings self.location = True #show current position self.markclosest = True #mark self.crosshair = True self.crosshair_hidden = True self.viewtype = INDIVIDUAL layout = QVBoxLayout() self.setLayout(layout) self.layout().setContentsMargins(0, 0, 0, 0) self.layout().addWidget(self.plotview) actions = [] zoom_in = QAction( "Zoom in", self, triggered=self.plot.vb.set_mode_zooming ) zoom_in.setShortcuts([Qt.Key_Z, QKeySequence(QKeySequence.ZoomIn)]) actions.append(zoom_in) zoom_fit = QAction( "Zoom to fit", self, triggered=lambda x: (self.plot.vb.autoRange(), self.plot.vb.set_mode_panning()) ) zoom_fit.setShortcuts([Qt.Key_Backspace, QKeySequence(Qt.ControlModifier | Qt.Key_0)]) actions.append(zoom_fit) rescale_y = QAction( "Rescale Y to fit", self, shortcut=Qt.Key_D, triggered=self.rescale_current_view_y ) actions.append(rescale_y) view_individual = QAction( "Show individual", self, shortcut=Qt.Key_I, triggered=lambda x: self.show_individual() ) actions.append(view_individual) view_average = QAction( "Show averages", self, shortcut=Qt.Key_A, triggered=lambda x: self.show_average() ) actions.append(view_average) self.show_grid = False self.show_grid_a = QAction( "Show grid", self, shortcut=Qt.Key_G, checkable=True, triggered=self.grid_changed ) actions.append(self.show_grid_a) self.invertX_menu = QAction( "Invert X", self, shortcut=Qt.Key_X, checkable=True, triggered=self.invertX_changed ) actions.append(self.invertX_menu) if self.selection_type == SELECTMANY: select_curves = QAction( "Select (line)", self, triggered=self.plot.vb.set_mode_select, ) select_curves.setShortcuts([Qt.Key_S]) actions.append(select_curves) if self.saving_enabled: save_graph = QAction( "Save graph", self, triggered=self.save_graph, ) save_graph.setShortcuts([QKeySequence(Qt.ControlModifier | Qt.Key_S)]) actions.append(save_graph) range_menu = MenuFocus("Define view range", self) range_action = QWidgetAction(self) layout = QGridLayout() range_box = gui.widgetBox(self, margin=5, orientation=layout) range_box.setFocusPolicy(Qt.TabFocus) self.range_e_x1 = lineEditFloatOrNone(None, self, "range_x1", label="e") range_box.setFocusProxy(self.range_e_x1) self.range_e_x2 = lineEditFloatOrNone(None, self, "range_x2", label="e") layout.addWidget(QLabel("X"), 0, 0, Qt.AlignRight) layout.addWidget(self.range_e_x1, 0, 1) layout.addWidget(QLabel("-"), 0, 2) layout.addWidget(self.range_e_x2, 0, 3) self.range_e_y1 = lineEditFloatOrNone(None, self, "range_y1", label="e") self.range_e_y2 = lineEditFloatOrNone(None, self, "range_y2", label="e") layout.addWidget(QLabel("Y"), 1, 0, Qt.AlignRight) layout.addWidget(self.range_e_y1, 1, 1) layout.addWidget(QLabel("-"), 1, 2) layout.addWidget(self.range_e_y2, 1, 3) b = gui.button(None, self, "Apply", callback=self.set_limits) layout.addWidget(b, 2, 3, Qt.AlignRight) range_action.setDefaultWidget(range_box) range_menu.addAction(range_action) layout = QGridLayout() self.plotview.setLayout(layout) self.button = QPushButton("View", self.plotview) self.button.setAutoDefault(False) layout.setRowStretch(1, 1) layout.setColumnStretch(1, 1) layout.addWidget(self.button, 0, 0) view_menu = MenuFocus(self) self.button.setMenu(view_menu) view_menu.addActions(actions) view_menu.addMenu(range_menu) self.addActions(actions) choose_color_action = QWidgetAction(self) choose_color_box = gui.hBox(self) choose_color_box.setFocusPolicy(Qt.TabFocus) model = VariableListModel() self.attrs = [] model.wrap(self.attrs) label = gui.label(choose_color_box, self, "Color by") label.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.attrCombo = gui.comboBox( choose_color_box, self, value="color_attr", contentsLength=12, callback=self.change_color_attr) self.attrCombo.setModel(model) choose_color_box.setFocusProxy(self.attrCombo) choose_color_action.setDefaultWidget(choose_color_box) view_menu.addAction(choose_color_action) labels_action = QWidgetAction(self) layout = QGridLayout() labels_box = gui.widgetBox(self, margin=0, orientation=layout) t = gui.lineEdit(None, self, "label_title", label="Title:", callback=self.labels_changed, callbackOnType=self.labels_changed) layout.addWidget(QLabel("Title:"), 0, 0, Qt.AlignRight) layout.addWidget(t, 0, 1) t = gui.lineEdit(None, self, "label_xaxis", label="X-axis:", callback=self.labels_changed, callbackOnType=self.labels_changed) layout.addWidget(QLabel("X-axis:"), 1, 0, Qt.AlignRight) layout.addWidget(t, 1, 1) t = gui.lineEdit(None, self, "label_yaxis", label="Y-axis:", callback=self.labels_changed, callbackOnType=self.labels_changed) layout.addWidget(QLabel("Y-axis:"), 2, 0, Qt.AlignRight) layout.addWidget(t, 2, 1) labels_action.setDefaultWidget(labels_box) view_menu.addAction(labels_action) self.labels_changed() # apply saved labels self.invertX_apply() self.plot.vb.set_mode_panning() self.reports = {} # current reports self.viewhelpers_show()