Example #1
0
    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])
Example #2
0
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 "&nbsp;&nbsp;".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)
Example #4
0
    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)
Example #5
0
    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)
Example #7
0
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)
Example #8
0
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()
Example #9
0
    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))
Example #10
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)
Example #11
0
	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
Example #12
0
    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
Example #13
0
 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
Example #15
0
    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
Example #16
0
 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)
Example #17
0
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()
Example #18
0
    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
Example #19
0
    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)
Example #20
0
    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()
Example #23
0
    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
Example #24
0
    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])
Example #25
0
    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 = {}
Example #26
0
    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)
Example #27
0
    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)
Example #28
0
    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 = {}
Example #30
0
    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()