Exemplo n.º 1
0
    def adjustGeometry(self):
        # type: () -> None
        """
        Adjust the widget geometry to exactly fit the arrow inside
        while preserving the arrow path scene geometry.

        """
        # local system coordinate
        geom = self.geometry().translated(-self.pos())
        line = self.__line

        arrow_rect = self.__arrowItem.shape().boundingRect()

        if geom.isNull() and not line.isNull():
            geom = QRectF(0, 0, 1, 1)

        if not (geom.contains(arrow_rect)):
            geom = geom.united(arrow_rect)

        geom = geom.intersected(arrow_rect)
        diff = geom.topLeft()
        line = QLineF(line.p1() - diff, line.p2() - diff)
        geom.translate(self.pos())
        self.setGeometry(geom)
        self.setLine(line)
Exemplo n.º 2
0
    def setLine(self, line):
        """
        Set the arrow base line (a `QLineF` in object coordinates).
        """
        if self.__line != line:
            self.__line = QLineF(line)

            # local item coordinate system
            geom = self.geometry().translated(-self.pos())

            if geom.isNull() and not line.isNull():
                geom = QRectF(0, 0, 1, 1)

            arrow_shape = arrow_path_concave(line, self.lineWidth())
            arrow_rect = arrow_shape.boundingRect()

            if not (geom.contains(arrow_rect)):
                geom = geom.united(arrow_rect)

            if self.__autoAdjustGeometry:
                # Shrink the geometry if required.
                geom = geom.intersected(arrow_rect)

            # topLeft can move changing the local coordinates.
            diff = geom.topLeft()
            line = QLineF(line.p1() - diff, line.p2() - diff)
            self.__arrowItem.setLine(line)
            self.__arrowShadowBase.setLine(line)
            self.__line = line

            # parent item coordinate system
            geom.translate(self.pos())
            self.setGeometry(geom)
Exemplo n.º 3
0
    def setLine(self, line):
        # type: (QLineF) -> None
        """
        Set the arrow base line (a `QLineF` in object coordinates).
        """
        if self.__line != line:
            self.__line = QLineF(line)

            # local item coordinate system
            geom = self.geometry().translated(-self.pos())

            if geom.isNull() and not line.isNull():
                geom = QRectF(0, 0, 1, 1)

            arrow_shape = arrow_path_concave(line, self.lineWidth())
            arrow_rect = arrow_shape.boundingRect()

            if not (geom.contains(arrow_rect)):
                geom = geom.united(arrow_rect)

            if self.__autoAdjustGeometry:
                # Shrink the geometry if required.
                geom = geom.intersected(arrow_rect)

            # topLeft can move changing the local coordinates.
            diff = geom.topLeft()
            line = QLineF(line.p1() - diff, line.p2() - diff)
            self.__arrowItem.setLine(line)
            self.__arrowShadowBase.setLine(line)
            self.__line = line

            # parent item coordinate system
            geom.translate(self.pos())
            self.setGeometry(geom)
    def __select_range(self, p1: QPointF, p2: QPointF):
        rect = QRectF(p1, p2).normalized()
        self.__selection.append((rect.topLeft().x(), rect.topRight().x()))

        sel_rect_item = SelectionRect(rect)
        self.addItem(sel_rect_item)
        self.__selection_rect_items.append(sel_rect_item)
Exemplo n.º 5
0
def qgraphicsview_map_rect_from_scene(view: QGraphicsView,
                                      rect: QRectF) -> QPolygonF:
    """Like QGraphicsView.mapFromScene(QRectF) but returning a QPolygonF
    (without rounding).
    """
    tr = view.viewportTransform()
    p1 = tr.map(rect.topLeft())
    p2 = tr.map(rect.topRight())
    p3 = tr.map(rect.bottomRight())
    p4 = tr.map(rect.bottomLeft())
    return QPolygonF([p1, p2, p3, p4])
Exemplo n.º 6
0
    def select_by_rectangle(self, rect: QRectF):
        if self.bar_item is None:
            return

        x0, x1 = sorted((rect.topLeft().x(), rect.bottomRight().x()))
        y0, y1 = sorted((rect.topLeft().y(), rect.bottomRight().y()))
        x = self.bar_item.opts["x"]
        height = self.bar_item.opts["height"]
        d = self.bar_width / 2
        # positive bars
        mask = (x0 <= x + d) & (x1 >= x - d) & (y0 <= height) & (y1 > 0)
        # negative bars
        mask |= (x0 <= x + d) & (x1 >= x - d) & (y0 <= 0) & (y1 > height)
        self.select_by_indices(list(np.flatnonzero(mask)))
Exemplo n.º 7
0
    def updateScaleBox(self, p1, p2):
        """
        Overload to use ViewBox.mapToView instead of mapRectFromParent
        mapRectFromParent (from Qt) uses QTransform.invert() which has
        floating-point issues and can't invert the matrix with large
        coefficients. ViewBox.mapToView uses invertQTransform from pyqtgraph.

        This code, except for first three lines, are copied from the overloaded
        method.
        """
        p1 = self.mapToView(p1)
        p2 = self.mapToView(p2)
        r = QRectF(p1, p2)
        self.rbScaleBox.setPos(r.topLeft())
        tr = QTransform.fromScale(r.width(), r.height())
        self.rbScaleBox.setTransform(tr)
        self.rbScaleBox.show()
Exemplo n.º 8
0
    def updateScaleBox(self, p1, p2):
        """
        Overload to use ViewBox.mapToView instead of mapRectFromParent
        mapRectFromParent (from Qt) uses QTransform.invert() which has
        floating-point issues and can't invert the matrix with large
        coefficients. ViewBox.mapToView uses invertQTransform from pyqtgraph.

        This code, except for first three lines, are copied from the overloaded
        method.
        """
        p1 = self.mapToView(p1)
        p2 = self.mapToView(p2)
        r = QRectF(p1, p2)
        self.rbScaleBox.setPos(r.topLeft())
        self.rbScaleBox.resetTransform()
        self.rbScaleBox.scale(r.width(), r.height())
        self.rbScaleBox.show()
Exemplo n.º 9
0
    def adjustGeometry(self):
        """
        Adjust the widget geometry to exactly fit the arrow inside
        while preserving the arrow path scene geometry.

        """
        # local system coordinate
        geom = self.geometry().translated(-self.pos())
        line = self.__line

        arrow_rect = self.__arrowItem.shape().boundingRect()

        if geom.isNull() and not line.isNull():
            geom = QRectF(0, 0, 1, 1)

        if not (geom.contains(arrow_rect)):
            geom = geom.united(arrow_rect)

        geom = geom.intersected(arrow_rect)
        diff = geom.topLeft()
        line = QLineF(line.p1() - diff, line.p2() - diff)
        geom.translate(self.pos())
        self.setGeometry(geom)
        self.setLine(line)
Exemplo n.º 10
0
class SelectTool(DataTool):
    cursor = Qt.ArrowCursor

    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 setSelectionRect(self, rect):
        if self._selection_rect != rect:
            self._selection_rect = QRectF(rect)
            self._item.setRect(self._selection_rect)

    def selectionRect(self):
        return self._item.rect()

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            pos = self.mapToPlot(event.pos())
            if self._item.isVisible():
                if self.selectionRect().contains(pos):
                    # Allow the event to propagate to the item.
                    event.setAccepted(False)
                    self._item.setCursor(Qt.ClosedHandCursor)
                    return False

            self._mouse_dragging = True

            self._start_pos = pos
            self._item.setVisible(True)
            self._plot.addItem(self._item)

            self.setSelectionRect(QRectF(pos, pos))
            event.accept()
            return True
        return super().mousePressEvent(event)

    def mouseMoveEvent(self, event):
        if event.buttons() & Qt.LeftButton:
            pos = self.mapToPlot(event.pos())
            self.setSelectionRect(QRectF(self._start_pos, pos).normalized())
            event.accept()
            return True
        return super().mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
            pos = self.mapToPlot(event.pos())
            self.setSelectionRect(QRectF(self._start_pos, pos).normalized())
            event.accept()
            self.issueCommand.emit(SelectRegion(self.selectionRect()))
            self._item.setCursor(Qt.OpenHandCursor)
            self._mouse_dragging = False
            return True
        return super().mouseReleaseEvent(event)

    def activate(self):
        if self._item is None:
            self._item = _RectROI((0, 0), (0, 0), pen=(25, 25, 25))
            self._item.setAcceptedMouseButtons(Qt.LeftButton)
            self._item.setVisible(False)
            self._item.setCursor(Qt.OpenHandCursor)
            self._item.sigRegionChanged.connect(self._on_region_changed)
            self._item.sigRegionChangeStarted.connect(
                self._on_region_change_started)
            self._item.sigRegionChangeFinished.connect(
                self._on_region_change_finished)
            self._plot.addItem(self._item)
            self._mouse_dragging = False

        self._plot.addAction(self._delete_action)

    def deactivate(self):
        self.reset()
        self._plot.removeAction(self._delete_action)

    def reset(self):
        self.setSelectionRect(QRectF())
        self._item.setVisible(False)
        self._mouse_dragging = False

    def delete(self):
        if not self._mouse_dragging and self._item.isVisible():
            self.issueCommand.emit(DeleteSelection())
            self.reset()

    def _on_region_changed(self):
        if not self._mouse_dragging:
            newrect = self._item.rect()
            delta = newrect.topLeft() - self._selection_rect.topLeft()
            self._selection_rect = newrect
            self.issueCommand.emit(MoveSelection(delta))

    def _on_region_change_started(self):
        if not self._mouse_dragging:
            self.editingStarted.emit()

    def _on_region_change_finished(self):
        if not self._mouse_dragging:
            self.editingFinished.emit()
Exemplo n.º 11
0
class RectangleSelectionAction(UserInteraction):
    """
    Select items in the scene using a Rectangle selection
    """
    def __init__(self, document, *args, **kwargs):
        UserInteraction.__init__(self, document, *args, **kwargs)
        # The initial selection at drag start
        self.initial_selection = None
        # Selection when last updated in a mouseMoveEvent
        self.last_selection = None
        # A selection rect (`QRectF`)
        self.selection_rect = None
        # Keyboard modifiers
        self.modifiers = 0

    def mousePressEvent(self, event):
        pos = event.scenePos()
        any_item = self.scene.item_at(pos)
        if not any_item and event.button() & Qt.LeftButton:
            self.modifiers = event.modifiers()
            self.selection_rect = QRectF(pos, QSizeF(0, 0))
            self.rect_item = QGraphicsRectItem(
                self.selection_rect.normalized())

            self.rect_item.setPen(
                QPen(QBrush(QColor(51, 153, 255, 192)), 0.4, Qt.SolidLine,
                     Qt.RoundCap))

            self.rect_item.setBrush(QBrush(QColor(168, 202, 236, 192)))

            self.rect_item.setZValue(-100)

            # Clear the focus if necessary.
            if not self.scene.stickyFocus():
                self.scene.clearFocus()

            if not self.modifiers & Qt.ControlModifier:
                self.scene.clearSelection()

            event.accept()
            return True
        else:
            self.cancel(self.ErrorReason)
            return False

    def mouseMoveEvent(self, event):
        if not self.rect_item.scene():
            # Add the rect item to the scene when the mouse moves.
            self.scene.addItem(self.rect_item)
        self.update_selection(event)
        return True

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
            if self.initial_selection is None:
                # A single click.
                self.scene.clearSelection()
            else:
                self.update_selection(event)
        self.end()
        return True

    def update_selection(self, event):
        """
        Update the selection rectangle from a QGraphicsSceneMouseEvent
        `event` instance.

        """
        if self.initial_selection is None:
            self.initial_selection = set(self.scene.selectedItems())
            self.last_selection = self.initial_selection

        pos = event.scenePos()
        self.selection_rect = QRectF(self.selection_rect.topLeft(), pos)

        # Make sure the rect_item does not cause the scene rect to grow.
        rect = self._bound_selection_rect(self.selection_rect.normalized())

        # Need that 0.5 constant otherwise the sceneRect will still
        # grow (anti-aliasing correction by QGraphicsScene?)
        pw = self.rect_item.pen().width() + 0.5

        self.rect_item.setRect(rect.adjusted(pw, pw, -pw, -pw))

        selected = self.scene.items(self.selection_rect.normalized(),
                                    Qt.IntersectsItemShape, Qt.AscendingOrder)

        selected = set([item for item in selected if \
                        item.flags() & Qt.ItemIsSelectable])

        if self.modifiers & Qt.ControlModifier:
            for item in selected | self.last_selection | \
                    self.initial_selection:
                item.setSelected((item in selected)
                                 ^ (item in self.initial_selection))
        else:
            for item in selected.union(self.last_selection):
                item.setSelected(item in selected)

        self.last_selection = set(self.scene.selectedItems())

    def end(self):
        self.initial_selection = None
        self.last_selection = None
        self.modifiers = 0

        self.rect_item.hide()
        if self.rect_item.scene() is not None:
            self.scene.removeItem(self.rect_item)
        UserInteraction.end(self)

    def viewport_rect(self):
        """
        Return the bounding rect of the document's viewport on the scene.
        """
        view = self.document.view()
        vsize = view.viewport().size()
        viewportrect = QRect(0, 0, vsize.width(), vsize.height())
        return view.mapToScene(viewportrect).boundingRect()

    def _bound_selection_rect(self, rect):
        """
        Bound the selection `rect` to a sensible size.
        """
        srect = self.scene.sceneRect()
        vrect = self.viewport_rect()
        maxrect = srect.united(vrect)
        return rect.intersected(maxrect)
Exemplo n.º 12
0
class SelectTool(DataTool):
    cursor = Qt.ArrowCursor

    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 setSelectionRect(self, rect):
        if self._selection_rect != rect:
            self._selection_rect = QRectF(rect)
            self._item.setRect(self._selection_rect)

    def selectionRect(self):
        return self._item.rect()

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            pos = self.mapToPlot(event.pos())
            if self._item.isVisible():
                if self.selectionRect().contains(pos):
                    # Allow the event to propagate to the item.
                    event.setAccepted(False)
                    self._item.setCursor(Qt.ClosedHandCursor)
                    return False

            self._mouse_dragging = True

            self._start_pos = pos
            self._item.setVisible(True)
            self._plot.addItem(self._item)

            self.setSelectionRect(QRectF(pos, pos))
            event.accept()
            return True
        else:
            return super().mousePressEvent(event)

    def mouseMoveEvent(self, event):
        if event.buttons() & Qt.LeftButton:
            pos = self.mapToPlot(event.pos())
            self.setSelectionRect(QRectF(self._start_pos, pos).normalized())
            event.accept()
            return True
        else:
            return super().mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
            pos = self.mapToPlot(event.pos())
            self.setSelectionRect(QRectF(self._start_pos, pos).normalized())
            event.accept()
            self.issueCommand.emit(SelectRegion(self.selectionRect()))
            self._item.setCursor(Qt.OpenHandCursor)
            self._mouse_dragging = False
            return True
        else:
            return super().mouseReleaseEvent(event)

    def activate(self):
        if self._item is None:
            self._item = _RectROI((0, 0), (0, 0), pen=(25, 25, 25))
            self._item.setAcceptedMouseButtons(Qt.LeftButton)
            self._item.setVisible(False)
            self._item.setCursor(Qt.OpenHandCursor)
            self._item.sigRegionChanged.connect(self._on_region_changed)
            self._item.sigRegionChangeStarted.connect(
                self._on_region_change_started)
            self._item.sigRegionChangeFinished.connect(
                self._on_region_change_finished)
            self._plot.addItem(self._item)
            self._mouse_dragging = False

        self._plot.addAction(self._delete_action)

    def deactivate(self):
        self._reset()
        self._plot.removeAction(self._delete_action)

    def _reset(self):
        self.setSelectionRect(QRectF())
        self._item.setVisible(False)
        self._mouse_dragging = False

    def delete(self):
        if not self._mouse_dragging and self._item.isVisible():
            self.issueCommand.emit(DeleteSelection())
            self._reset()

    def _on_region_changed(self):
        if not self._mouse_dragging:
            newrect = self._item.rect()
            delta = newrect.topLeft() - self._selection_rect.topLeft()
            self._selection_rect = newrect
            self.issueCommand.emit(MoveSelection(delta))

    def _on_region_change_started(self):
        if not self._mouse_dragging:
            self.editingStarted.emit()

    def _on_region_change_finished(self):
        if not self._mouse_dragging:
            self.editingFinished.emit()
Exemplo n.º 13
0
class RectangleSelectionAction(UserInteraction):
    """
    Select items in the scene using a Rectangle selection
    """
    def __init__(self, document, *args, **kwargs):
        UserInteraction.__init__(self, document, *args, **kwargs)
        # The initial selection at drag start
        self.initial_selection = None
        # Selection when last updated in a mouseMoveEvent
        self.last_selection = None
        # A selection rect (`QRectF`)
        self.selection_rect = None
        # Keyboard modifiers
        self.modifiers = 0

    def mousePressEvent(self, event):
        pos = event.scenePos()
        any_item = self.scene.item_at(pos)
        if not any_item and event.button() & Qt.LeftButton:
            self.modifiers = event.modifiers()
            self.selection_rect = QRectF(pos, QSizeF(0, 0))
            self.rect_item = QGraphicsRectItem(
                self.selection_rect.normalized()
            )

            self.rect_item.setPen(
                QPen(QBrush(QColor(51, 153, 255, 192)),
                     0.4, Qt.SolidLine, Qt.RoundCap)
            )

            self.rect_item.setBrush(
                QBrush(QColor(168, 202, 236, 192))
            )

            self.rect_item.setZValue(-100)

            # Clear the focus if necessary.
            if not self.scene.stickyFocus():
                self.scene.clearFocus()

            if not self.modifiers & Qt.ControlModifier:
                self.scene.clearSelection()

            event.accept()
            return True
        else:
            self.cancel(self.ErrorReason)
            return False

    def mouseMoveEvent(self, event):
        if not self.rect_item.scene():
            # Add the rect item to the scene when the mouse moves.
            self.scene.addItem(self.rect_item)
        self.update_selection(event)
        return True

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
            if self.initial_selection is None:
                # A single click.
                self.scene.clearSelection()
            else:
                self.update_selection(event)
        self.end()
        return True

    def update_selection(self, event):
        """
        Update the selection rectangle from a QGraphicsSceneMouseEvent
        `event` instance.

        """
        if self.initial_selection is None:
            self.initial_selection = set(self.scene.selectedItems())
            self.last_selection = self.initial_selection

        pos = event.scenePos()
        self.selection_rect = QRectF(self.selection_rect.topLeft(), pos)

        # Make sure the rect_item does not cause the scene rect to grow.
        rect = self._bound_selection_rect(self.selection_rect.normalized())

        # Need that 0.5 constant otherwise the sceneRect will still
        # grow (anti-aliasing correction by QGraphicsScene?)
        pw = self.rect_item.pen().width() + 0.5

        self.rect_item.setRect(rect.adjusted(pw, pw, -pw, -pw))

        selected = self.scene.items(self.selection_rect.normalized(),
                                    Qt.IntersectsItemShape,
                                    Qt.AscendingOrder)

        selected = set([item for item in selected if \
                        item.flags() & Qt.ItemIsSelectable])

        if self.modifiers & Qt.ControlModifier:
            for item in selected | self.last_selection | \
                    self.initial_selection:
                item.setSelected(
                    (item in selected) ^ (item in self.initial_selection)
                )
        else:
            for item in selected.union(self.last_selection):
                item.setSelected(item in selected)

        self.last_selection = set(self.scene.selectedItems())

    def end(self):
        self.initial_selection = None
        self.last_selection = None
        self.modifiers = 0

        self.rect_item.hide()
        if self.rect_item.scene() is not None:
            self.scene.removeItem(self.rect_item)
        UserInteraction.end(self)

    def viewport_rect(self):
        """
        Return the bounding rect of the document's viewport on the scene.
        """
        view = self.document.view()
        vsize = view.viewport().size()
        viewportrect = QRect(0, 0, vsize.width(), vsize.height())
        return view.mapToScene(viewportrect).boundingRect()

    def _bound_selection_rect(self, rect):
        """
        Bound the selection `rect` to a sensible size.
        """
        srect = self.scene.sceneRect()
        vrect = self.viewport_rect()
        maxrect = srect.united(vrect)
        return rect.intersected(maxrect)
Exemplo n.º 14
0
 def update_rect(self, p1: QPointF, p2: QPointF):
     rect = QRectF(p1, p2)
     self.setPos(rect.topLeft())
     trans = QTransform.fromScale(rect.width(), rect.height())
     self.setTransform(trans)