File: graphicspixmapwidget.py

package info (click to toggle)
orange3 3.40.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 15,908 kB
  • sloc: python: 162,745; ansic: 622; makefile: 322; sh: 93; cpp: 77
file content (125 lines) | stat: -rw-r--r-- 4,345 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
from typing import Optional

from AnyQt.QtCore import Qt, QSizeF, QRectF, QPointF
from AnyQt.QtGui import QPixmap, QTransform, QPainter
from AnyQt.QtWidgets import (
    QGraphicsWidget, QGraphicsItem, QStyleOptionGraphicsItem, QWidget,
)
from Orange.widgets.utils.graphicslayoutitem import scaled


class GraphicsPixmapWidget(QGraphicsWidget):
    def __init__(
            self,
            parent: Optional[QGraphicsItem] = None,
            pixmap: Optional[QPixmap] = None,
            scaleContents=False,
            aspectMode=Qt.KeepAspectRatio,
            **kwargs
    ) -> None:
        self.__scaleContents = scaleContents
        self.__aspectMode = aspectMode
        self.__pixmap = QPixmap(pixmap) if pixmap is not None else QPixmap()
        super().__init__(None, **kwargs)
        self.setFlag(QGraphicsWidget.ItemUsesExtendedStyleOption, True)
        self.setContentsMargins(0, 0, 0, 0)
        if parent is not None:
            self.setParentItem(parent)

    def setPixmap(self, pixmap: QPixmap) -> None:
        self.prepareGeometryChange()
        self.__pixmap = QPixmap(pixmap)
        self.updateGeometry()

    def pixmap(self) -> QPixmap:
        return QPixmap(self.__pixmap)

    def setAspectRatioMode(self, mode: Qt.AspectRatioMode) -> None:
        if self.__aspectMode != mode:
            self.__aspectMode = mode
            sp = self.sizePolicy()
            sp.setHeightForWidth(
                self.__aspectMode != Qt.IgnoreAspectRatio and self.__scaleContents
            )
            self.setSizePolicy(sp)
            self.updateGeometry()

    def aspectRatioMode(self) -> Qt.AspectRatioMode:
        return self.__aspectMode

    def setScaleContents(self, scale: bool) -> None:
        if self.__scaleContents != scale:
            self.__scaleContents = bool(scale)
            sp = self.sizePolicy()
            sp.setHeightForWidth(
                self.__aspectMode != Qt.IgnoreAspectRatio and self.__scaleContents
            )
            self.setSizePolicy(sp)
            self.updateGeometry()

    def scaleContents(self) -> bool:
        return self.__scaleContents

    def sizeHint(self, which, constraint=QSizeF(-1, -1)) -> QSizeF:
        if which == Qt.PreferredSize:
            sh = QSizeF(self.__pixmap.size())
            if self.__scaleContents:
                sh = scaled(sh, constraint, self.__aspectMode)
            return sh
        elif which == Qt.MinimumSize:
            if self.__scaleContents:
                return QSizeF(0, 0)
            else:
                return QSizeF(self.__pixmap.size())
        elif which == Qt.MaximumSize:
            if self.__scaleContents:
                return QSizeF()
            else:
                return QSizeF(self.__pixmap.size())
        else:
            # Qt.MinimumDescent
            return QSizeF()

    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)

    def paint(
            self, painter: QPainter, option: QStyleOptionGraphicsItem,
            widget: Optional[QWidget] = None
    ) -> None:
        if self.__pixmap.isNull():
            return
        pixmap = self.__pixmap
        crect = self.contentsRect()

        exposed = option.exposedRect
        exposedcrect = crect.intersected(exposed)
        pixmaptransform = self.pixmapTransform()
        # map exposed rect to exposed pixmap coords
        assert pixmaptransform.type() in (
            QTransform.TxNone, QTransform.TxTranslate, QTransform.TxScale
        )
        pixmaptransform, ok = pixmaptransform.inverted()
        if not ok:
            painter.drawPixmap(
                crect, pixmap, QRectF(QPointF(0, 0), QSizeF(pixmap.size()))
            )
        else:
            exposedpixmap = pixmaptransform.mapRect(exposed)
            painter.drawPixmap(exposedcrect, pixmap, exposedpixmap)