Exemplo n.º 1
0
    def paintEvent(self, QPaintEvent):
        import math


        if self.direction == 'x':
            _angle = self.parent.rotationX
            _x1 = self.width() / 2
            _y1 = self.height() / 2
            _x2 = math.cos(math.radians(_angle)) * (self.width() / 2)
            _y2 = math.sin(math.radians(_angle)) * (self.width() / 2)
        elif self.direction == 'y':
            _angle = self.parent.rotationY
            _x1 = self.width() / 2
            _y1 = self.height() / 2
            _x2 = math.cos(math.radians(_angle + 90)) * (self.height() / 2)
            _y2 = math.sin(math.radians(_angle + 90)) * (self.height() / 2)
        else:
            _angle = 0
            _x1 = 0
            _y1 = 0
            _x2 = 0
            _y2 = 0
        _painter = QPainter(self)
        _pm = QPixmap(self.width(), self.height())
        _pm_compass = QPixmap(self.compassImage).transformed(QTransform().rotate(self.compassRotation))
        _pm_image = QPixmap(self.image).transformed(QTransform().rotate(_angle))
        _painter.drawPixmap(0, 0, _pm_compass)
        _painter.setPen(QColor(255, 160, 47))
        _painter.drawLine(_x1, _y1, _x2, _y2)
        _x = (self.width() - _pm_image.width()) / 2
        _y = (self.height() - _pm_image.height()) / 2
        _painter.drawPixmap(_x, _y, _pm_image)

        _painter.end()
Exemplo n.º 2
0
    def __updateText(self):
        self.prepareGeometryChange()
        self.__boundingRect = None

        if self.__sourceName or self.__sinkName:
            if self.__sourceName != self.__sinkName:
                text = "{0} \u2192 {1}".format(self.__sourceName,
                                               self.__sinkName)
            else:
                # If the names are the same show only one.
                # Is this right? If the sink has two input channels of the
                # same type having the name on the link help elucidate
                # the scheme.
                text = self.__sourceName
        else:
            text = ""

        self.linkTextItem.setPlainText(text)

        path = self.curveItem.curvePath()
        if not path.isEmpty():
            center = path.pointAtPercent(0.5)
            angle = path.angleAtPercent(0.5)

            brect = self.linkTextItem.boundingRect()

            transform = QTransform()
            transform.translate(center.x(), center.y())
            transform.rotate(-angle)

            # Center and move above the curve path.
            transform.translate(-brect.width() / 2, -brect.height())

            self.linkTextItem.setTransform(transform)
Exemplo n.º 3
0
 def __init__(self,
              parent=None,
              root=None,
              orientation=Left,
              hoverHighlightEnabled=True,
              selectionMode=ExtendedSelection,
              **kwargs):
     super().__init__(None, **kwargs)
     # Filter all events from children (`ClusterGraphicsItem`s)
     self.setFiltersChildEvents(True)
     self.orientation = orientation
     self._root = None
     #: A tree with dendrogram geometry
     self._layout = None
     self._highlighted_item = None
     #: a list of selected items
     self._selection = OrderedDict()
     #: a {node: item} mapping
     self._items = {
     }  # type: Dict[Tree, DendrogramWidget.ClusterGraphicsItem]
     #: container for all cluster items.
     self._itemgroup = QGraphicsWidget(self)
     self._itemgroup.setGeometry(self.contentsRect())
     #: Transform mapping from 'dendrogram' to widget local coordinate
     #: system
     self._transform = QTransform()
     self._cluster_parent = {}
     self.__hoverHighlightEnabled = hoverHighlightEnabled
     self.__selectionMode = selectionMode
     self.setContentsMargins(0, 0, 0, 0)
     self.setRoot(root)
     if parent is not None:
         self.setParentItem(parent)
Exemplo n.º 4
0
    def __updateLayout(self):
        T = self.sceneTransform()
        if T is None:
            T = QTransform()

        # map the axis spine to scene coord. system.
        viewbox_line = T.map(self._spine.line())
        angle = viewbox_line.angle()
        assert not np.isnan(angle)
        # note in Qt the y axis is inverted (90 degree angle 'points' down)
        left_quad = 270 < angle <= 360 or -0.0 <= angle < 90

        # position the text label along the viewbox_line
        label_pos = self._spine.line().pointAt(0.90)

        if left_quad:
            # Anchor the text under the axis spine
            anchor = (0.5, -0.1)
        else:
            # Anchor the text over the axis spine
            anchor = (0.5, 1.1)

        self._label.setPos(label_pos)
        self._label.setAnchor(pg.Point(*anchor))
        self._label.setRotation(-angle if left_quad else 180 - angle)

        self._arrow.setPos(self._spine.line().p2())
        self._arrow.setRotation(180 - angle)
Exemplo n.º 5
0
def graphicsscene_help_event(scene: QGraphicsScene,
                             event: QGraphicsSceneHelpEvent) -> None:
    """
    Send the help event to every graphics item that is under the `event`
    scene position.
    """
    widget = event.widget()
    if widget is not None and isinstance(widget.parentWidget(), QGraphicsView):
        view = widget.parentWidget()
        deviceTransform = view.viewportTransform()
    else:
        deviceTransform = QTransform()
    items = scene.items(
        event.scenePos(),
        Qt.IntersectsItemShape,
        Qt.DescendingOrder,
        deviceTransform,
    )
    text = ""
    event.setAccepted(False)
    for item in items:
        scene.sendEvent(item, event)
        if event.isAccepted():
            return
        elif item.toolTip():
            text = item.toolTip()
            break

    QToolTip.showText(event.screenPos(), text, event.widget())
    event.setAccepted(bool(text))
Exemplo n.º 6
0
    def __updateText(self):
        # type: () -> None
        self.prepareGeometryChange()
        self.__boundingRect = None

        if self.__sourceName or self.__sinkName:
            if self.__sourceName != self.__sinkName:
                text = ("<nobr>{0}</nobr> \u2192 <nobr>{1}</nobr>"
                        .format(escape(self.__sourceName),
                                escape(self.__sinkName)))
            else:
                # If the names are the same show only one.
                # Is this right? If the sink has two input channels of the
                # same type having the name on the link help elucidate
                # the scheme.
                text = escape(self.__sourceName)
        else:
            text = ""

        self.linkTextItem.setHtml('<div align="center">{0}</div>'
                                  .format(text))
        path = self.curveItem.curvePath()

        # Constrain the text width if it is too long to fit on a single line
        # between the two ends
        if not path.isEmpty():
            # Use the distance between the start/end points as a measure of
            # available space
            diff = path.pointAtPercent(0.0) - path.pointAtPercent(1.0)
            available_width = math.sqrt(diff.x() ** 2 + diff.y() ** 2)
            # Get the ideal text width if it was unconstrained
            doc = self.linkTextItem.document().clone(self)
            doc.setTextWidth(-1)
            idealwidth = doc.idealWidth()
            doc.deleteLater()

            # Constrain the text width but not below a certain min width
            minwidth = 100
            textwidth = max(minwidth, min(available_width, idealwidth))
            self.linkTextItem.setTextWidth(textwidth)
        else:
            # Reset the fixed width
            self.linkTextItem.setTextWidth(-1)

        if not path.isEmpty():
            center = path.pointAtPercent(0.5)
            angle = path.angleAtPercent(0.5)

            brect = self.linkTextItem.boundingRect()

            transform = QTransform()
            transform.translate(center.x(), center.y())
            transform.rotate(-angle)

            # Center and move above the curve path.
            transform.translate(-brect.width() / 2, -brect.height())

            self.linkTextItem.setTransform(transform)
Exemplo n.º 7
0
    def pixmapTransform(self) -> QTransform:
        if self.__pixmap.isNull():
            return QTransform()

        pxsize = QSizeF(self.__pixmap.size())
        crect = self.contentsRect()
        transform = QTransform()
        transform = transform.translate(crect.left(), crect.top())

        if self.__scaleContents:
            csize = scaled(pxsize, crect.size(), self.__aspectMode)
        else:
            csize = pxsize

        xscale = csize.width() / pxsize.width()
        yscale = csize.height() / pxsize.height()

        return transform.scale(xscale, yscale)
Exemplo n.º 8
0
    def _updateLayout(self):
        rect = self.geometry()
        n = len(self._items)
        if not n:
            return

        regions = venn_diagram(n)

        # The y axis in Qt points downward
        transform = QTransform().scale(1, -1)
        regions = list(map(transform.map, regions))

        union_brect = reduce(QRectF.united,
                             (path.boundingRect() for path in regions))

        scalex = rect.width() / union_brect.width()
        scaley = rect.height() / union_brect.height()
        scale = min(scalex, scaley)

        transform = QTransform().scale(scale, scale)

        regions = [transform.map(path) for path in regions]

        center = rect.width() / 2, rect.height() / 2
        for item, path in zip(self.items(), regions):
            item.setPath(path)
            item.setPos(*center)

        intersections = venn_intersections(regions)
        assert len(intersections) == 2 ** n
        assert len(self.vennareas()) == 2 ** n

        anchors = [(0, 0)] + subset_anchors(self._items)

        anchor_transform = QTransform().scale(rect.width(), -rect.height())
        for i, area in enumerate(self.vennareas()):
            area.setPath(intersections[setkey(i, n)])
            area.setPos(*center)
            x, y = anchors[i]
            anchor = anchor_transform.map(QPointF(x, y))
            area.setTextAnchor(anchor)
            area.setZValue(30)

        self._updateTextAnchors()
Exemplo n.º 9
0
        def paint(self, painter, option, widget=None):
            t = painter.transform()

            rect = t.mapRect(self.rect())

            painter.save()
            painter.setTransform(QTransform())
            pwidth = self.pen().widthF()
            painter.setPen(self.pen())
            painter.drawRect(rect.adjusted(pwidth, -pwidth, -pwidth, pwidth))
            painter.restore()
Exemplo n.º 10
0
 def _scaleToFit(self):
     widget = self.__centralWidget
     if widget is None or not self.__fitInView:
         return
     vpsize = self.__viewportContentSize()
     size = widget.size()
     if not size.isEmpty():
         sc = scaled(size, vpsize, self.__aspectMode)
         sx = sc.width() / size.width()
         sy = sc.height() / size.height()
         self.setTransform(QTransform().scale(sx, sy))
Exemplo n.º 11
0
 def __setZoomLevel(self, scale):
     # type: (float) -> None
     self.__zoomLevel = max(30, min(scale, 300))
     scale = round(self.__zoomLevel)
     self.__zoomOutAction.setEnabled(scale != 30)
     self.__zoomInAction.setEnabled(scale != 300)
     if self.__effectiveZoomLevel != scale:
         self.__effectiveZoomLevel = scale
         transform = QTransform()
         transform.scale(scale / 100, scale / 100)
         self.setTransform(transform)
         self.zoomLevelChanged.emit(scale)
Exemplo n.º 12
0
    def __init__(self,
                 id,
                 title='',
                 title_above=False,
                 title_location=AxisMiddle,
                 line=None,
                 arrows=0,
                 plot=None,
                 bounds=None):
        QGraphicsItem.__init__(self)
        self.setFlag(QGraphicsItem.ItemHasNoContents)
        self.setZValue(AxisZValue)
        self.id = id
        self.title = title
        self.title_location = title_location
        self.data_line = line
        self.plot = plot
        self.graph_line = None
        self.size = None
        self.scale = None
        self.tick_length = (10, 5, 0)
        self.arrows = arrows
        self.title_above = title_above
        self.line_item = QGraphicsLineItem(self)
        self.title_item = QGraphicsTextItem(self)
        self.end_arrow_item = None
        self.start_arrow_item = None
        self.show_title = False
        self.scale = None
        path = QPainterPath()
        path.setFillRule(Qt.WindingFill)
        path.moveTo(0, 3.09)
        path.lineTo(0, -3.09)
        path.lineTo(9.51, 0)
        path.closeSubpath()
        self.arrow_path = path
        self.label_items = []
        self.label_bg_items = []
        self.tick_items = []
        self._ticks = []
        self.zoom_transform = QTransform()
        self.labels = None
        self.values = None
        self._bounds = bounds
        self.auto_range = None
        self.auto_scale = True

        self.zoomable = False
        self.update_callback = None
        self.max_text_width = 50
        self.text_margin = 5
        self.always_horizontal_text = False
Exemplo n.º 13
0
 def __init__(self, stamp, position, scene, adjust_position=True,
              matrix=QTransform()):
     super(StampItem, self).__init__()
     self.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsMovable)
     self.setStamp(stamp)
     self.setPos(position)
     self.setTransform(matrix)
     scene.clearSelection()
     scene.addItem(self)
     self.setSelected(True)
     if adjust_position:
         bb = self.boundingRect()
         self.moveBy(-(bb.width()//2 + 3), -(bb.height()//2 + 3))
Exemplo n.º 14
0
def ellipse_path(center, a, b, rotation=0):
    if not isinstance(center, QPointF):
        center = QPointF(*center)

    brect = QRectF(-a, -b, 2 * a, 2 * b)

    path = QPainterPath()
    path.addEllipse(brect)

    if rotation != 0:
        transform = QTransform().rotate(rotation)
        path = transform.map(path)

    path.translate(center)
    return path
Exemplo n.º 15
0
    def __init__(self, *args, **kwargs):
        QDockWidget.__init__(self, *args, **kwargs)

        self.__expandedWidget = None
        self.__collapsedWidget = None
        self.__expanded = True

        self.__trueMinimumWidth = -1

        self.setFeatures(QDockWidget.DockWidgetClosable | \
                         QDockWidget.DockWidgetMovable)
        self.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)

        self.featuresChanged.connect(self.__onFeaturesChanged)
        self.dockLocationChanged.connect(self.__onDockLocationChanged)

        # Use the toolbar horizontal extension button icon as the default
        # for the expand/collapse button
        icon = self.style().standardIcon(
            QStyle.SP_ToolBarHorizontalExtensionButton)

        # Mirror the icon
        transform = QTransform()
        transform = transform.scale(-1.0, 1.0)
        icon_rev = QIcon()
        for s in (8, 12, 14, 16, 18, 24, 32, 48, 64):
            pm = icon.pixmap(s, s)
            icon_rev.addPixmap(pm.transformed(transform))

        self.__iconRight = QIcon(icon)
        self.__iconLeft = QIcon(icon_rev)

        close = self.findChild(QAbstractButton,
                               name="qt_dockwidget_closebutton")

        close.installEventFilter(self)
        self.__closeButton = close

        self.__stack = AnimatedStackedWidget()

        self.__stack.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding)

        self.__stack.transitionStarted.connect(self.__onTransitionStarted)
        self.__stack.transitionFinished.connect(self.__onTransitionFinished)

        QDockWidget.setWidget(self, self.__stack)

        self.__closeButton.setIcon(self.__iconLeft)
Exemplo n.º 16
0
def _define_symbols():
    """
    Add symbol ? to ScatterPlotItemSymbols,
    reflect the triangle to point upwards
    """
    symbols = pyqtgraph.graphicsItems.ScatterPlotItem.Symbols
    path = QPainterPath()
    path.addEllipse(QRectF(-0.35, -0.35, 0.7, 0.7))
    path.moveTo(-0.5, 0.5)
    path.lineTo(0.5, -0.5)
    path.moveTo(-0.5, -0.5)
    path.lineTo(0.5, 0.5)
    symbols["?"] = path

    tr = QTransform()
    tr.rotate(180)
    symbols['t'] = tr.map(symbols['t'])
Exemplo n.º 17
0
 def __static_text_elided_cache(
         self, text: str, font: QFont, fontMetrics: QFontMetrics,
         elideMode: Qt.TextElideMode, width: int
 ) -> QStaticText:
     """
     Return a `QStaticText` instance for depicting the text with the `font`
     """
     try:
         return self.__static_text_lru_cache[text, font, elideMode, width]
     except KeyError:
         text = fontMetrics.elidedText(text, elideMode, width)
         st = QStaticText(text)
         st.prepare(QTransform(), font)
         # take a copy of the font for cache key
         key = text, QFont(font), elideMode, width
         self.__static_text_lru_cache[key] = st
         return st
Exemplo n.º 18
0
 def __setZoomLevel(self, scale, anchor=None):
     # type: (float, Optional[QPointF]) -> None
     self.__zoomLevel = max(30, min(scale, 300))
     scale = round(self.__zoomLevel)
     self.__zoomOutAction.setEnabled(scale != 30)
     self.__zoomInAction.setEnabled(scale != 300)
     if self.__effectiveZoomLevel != scale:
         self.__effectiveZoomLevel = scale
         transform = QTransform()
         transform.scale(scale / 100, scale / 100)
         if anchor is not None:
             anchor = self.mapFromScene(anchor)
         self.setTransform(transform)
         if anchor is not None:
             center = self.viewport().rect().center()
             diff = self.mapToScene(center) - self.mapToScene(anchor)
             self.centerOn(anchor + diff)
         self.zoomLevelChanged.emit(scale)
Exemplo n.º 19
0
    def setHistogram(self,
                     values=None,
                     bins=None,
                     use_kde=False,
                     histogram=None):
        """ Set background histogram (or density estimation, violin plot)

        The histogram of bins is calculated from values, optionally as a
        Gaussian KDE. If histogram is provided, its values are used directly
        and other parameters are ignored.
        """
        if (values is None or not len(values)) and histogram is None:
            self.setPixmap(None)
            return
        if histogram is not None:
            self._histogram = hist = histogram
        else:
            if bins is None:
                bins = min(100, max(10, len(values) // 20))
            if use_kde:
                hist = gaussian_kde(
                    values, None if isinstance(use_kde, bool) else use_kde)(
                        np.linspace(np.min(values), np.max(values), bins))
            else:
                hist = np.histogram(values, bins)[0]
            self._histogram = hist = hist / hist.max()

        HEIGHT = self.rect().height() / 2
        OFFSET = HEIGHT * .3
        pixmap = QPixmap(QSize(
            len(hist), 2 *
            (HEIGHT + OFFSET)))  # +1 avoids right/bottom frame border shadow
        pixmap.fill(Qt.transparent)
        painter = QPainter(pixmap)
        painter.setPen(QPen(Qt.darkGray))
        for x, value in enumerate(hist):
            painter.drawLine(x,
                             HEIGHT * (1 - value) + OFFSET, x,
                             HEIGHT * (1 + value) + OFFSET)

        if self.orientation() != Qt.Horizontal:
            pixmap = pixmap.transformed(QTransform().rotate(-90))

        self.setPixmap(pixmap)
Exemplo n.º 20
0
    def _rescale(self):
        if self._root is None:
            return

        scale = self._height_scale_factor()
        base = scale * self._root.value.height
        crect = self.contentsRect()
        leaf_count = len(list(leaves(self._root)))
        if self.orientation in [Left, Right]:
            drect = QSizeF(base, leaf_count)
        else:
            drect = QSizeF(leaf_count, base)

        eps = np.finfo(np.float64).eps

        if abs(drect.width()) < eps:
            sx = 1.0
        else:
            sx = crect.width() / drect.width()

        if abs(drect.height()) < eps:
            sy = 1.0
        else:
            sy = crect.height() / drect.height()

        transform = QTransform().scale(sx, sy)
        self._transform = transform
        self._itemgroup.setPos(crect.topLeft())
        self._itemgroup.setGeometry(crect)
        for node_geom in postorder(self._layout):
            node, _ = node_geom.value
            item = self._items[node]
            item.setGeometryData(transform.map(item.sourcePath),
                                 transform.map(item.sourceAreaShape))
        self._selection_items = None
        self._update_selection_items()
 def updateTransform(self):
     if self.master.autoResize:
         self.fitInView(self.scene().sceneRect().adjusted(-1, -1, 1, 1),
                        Qt.KeepAspectRatio)
     else:
         self.setTransform(QTransform())
Exemplo n.º 22
0
 def toggle_zoom_slider(self):
     k = 0.0028 * (self.zoom ** 2) + 0.2583 * self.zoom + 1.1389
     self.scene_view.setTransform(QTransform().scale(k / 2, k / 2))
     self.scene.update()
Exemplo n.º 23
0
 def __set_zoom(self, scale):
     self.__scale = min(15, max(scale, 3))
     transform = QTransform()
     transform.scale(self.__scale / 10, self.__scale / 10)
     self.setTransform(transform)