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)
|