コード例 #1
0
class GraphicsPixmapWidget(QGraphicsWidget):
    """
    A QGraphicsWidget displaying a QPixmap
    """
    def __init__(self, pixmap=None, parent=None):
        super().__init__(parent)
        self.setCacheMode(QGraphicsItem.ItemCoordinateCache)
        self._pixmap = QPixmap(pixmap) if pixmap is not None else QPixmap()
        self._keepAspect = True
        self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)

    def setPixmap(self, pixmap):
        self._pixmap = QPixmap(pixmap)
        self.updateGeometry()
        self.update()

    def pixmap(self):
        return QPixmap(self._pixmap)

    def setKeepAspectRatio(self, keep):
        if self._keepAspect != keep:
            self._keepAspect = bool(keep)
            self.update()

    def keepAspectRatio(self):
        return self._keepAspect

    def setGeometry(self, rect):
        self.prepareGeometryChange()
        super().setGeometry(rect)

    def sizeHint(self, which, constraint=QSizeF()):
        if which == Qt.PreferredSize:
            return QSizeF(self._pixmap.size())
        else:
            return QGraphicsWidget.sizeHint(self, which, constraint)

    def paint(self, painter, option, widget=0):
        if self._pixmap.isNull():
            return

        rect = self.contentsRect()
        pixsize = QSizeF(self._pixmap.size())
        aspectmode = (Qt.KeepAspectRatio
                      if self._keepAspect else Qt.IgnoreAspectRatio)
        pixsize.scale(rect.size(), aspectmode)
        pixrect = QRectF(QPointF(0, 0), pixsize)
        pixrect.moveCenter(rect.center())

        painter.save()
        painter.setPen(QPen(QColor(0, 0, 0, 50), 3))
        painter.drawRoundedRect(pixrect, 2, 2)
        painter.setRenderHint(QPainter.SmoothPixmapTransform)
        source = QRectF(QPointF(0, 0), QSizeF(self._pixmap.size()))
        painter.drawPixmap(pixrect, self._pixmap, source)
        painter.restore()
コード例 #2
0
ファイル: owimageviewer.py プロジェクト: RachitKansal/orange3
class GraphicsPixmapWidget(QGraphicsWidget):
    """
    A QGraphicsWidget displaying a QPixmap
    """
    def __init__(self, pixmap=None, parent=None):
        super().__init__(parent)
        self.setCacheMode(QGraphicsItem.ItemCoordinateCache)
        self._pixmap = QPixmap(pixmap) if pixmap is not None else QPixmap()
        self._keepAspect = True
        self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)

    def setPixmap(self, pixmap):
        self._pixmap = QPixmap(pixmap)
        self.updateGeometry()
        self.update()

    def pixmap(self):
        return QPixmap(self._pixmap)

    def setKeepAspectRatio(self, keep):
        if self._keepAspect != keep:
            self._keepAspect = bool(keep)
            self.update()

    def keepAspectRatio(self):
        return self._keepAspect

    def setGeometry(self, rect):
        self.prepareGeometryChange()
        super().setGeometry(rect)

    def sizeHint(self, which, constraint=QSizeF()):
        if which == Qt.PreferredSize:
            return QSizeF(self._pixmap.size())
        else:
            return QGraphicsWidget.sizeHint(self, which, constraint)

    def paint(self, painter, option, widget=0):
        if self._pixmap.isNull():
            return

        rect = self.contentsRect()
        pixsize = QSizeF(self._pixmap.size())
        aspectmode = (Qt.KeepAspectRatio if self._keepAspect
                      else Qt.IgnoreAspectRatio)
        pixsize.scale(rect.size(), aspectmode)
        pixrect = QRectF(QPointF(0, 0), pixsize)
        pixrect.moveCenter(rect.center())

        painter.save()
        painter.setPen(QPen(QColor(0, 0, 0, 50), 3))
        painter.drawRoundedRect(pixrect, 2, 2)
        painter.setRenderHint(QPainter.SmoothPixmapTransform)
        source = QRectF(QPointF(0, 0), QSizeF(self._pixmap.size()))
        painter.drawPixmap(pixrect, self._pixmap, source)
        painter.restore()
コード例 #3
0
    def setIcon(self, icon):
        """
        Set the message icon.

        :type icon: QIcon | QPixmap | QString | QStyle.StandardPixmap
        """
        if isinstance(icon, QStyle.StandardPixmap):
            icon = self.style().standardIcon(icon)
        else:
            icon = QIcon(icon)

        if self.__icon != icon:
            self.__icon = QIcon(icon)
            if not self.__icon.isNull():
                size = self.style().pixelMetric(QStyle.PM_SmallIconSize, None, self)
                pm = self.__icon.pixmap(QSize(size, size))
            else:
                pm = QPixmap()

            self.__iconlabel.setPixmap(pm)
            self.__iconlabel.setVisible(not pm.isNull())
コード例 #4
0
ファイル: overlay.py プロジェクト: RachitKansal/orange3
    def setIcon(self, icon):
        """
        Set the message icon.

        :type icon: QIcon | QPixmap | QString | QStyle.StandardPixmap
        """
        if isinstance(icon, QStyle.StandardPixmap):
            icon = self.style().standardIcon(icon)
        else:
            icon = QIcon(icon)

        if self.__icon != icon:
            self.__icon = QIcon(icon)
            if not self.__icon.isNull():
                size = self.style().pixelMetric(
                    QStyle.PM_SmallIconSize, None, self)
                pm = self.__icon.pixmap(QSize(size, size))
            else:
                pm = QPixmap()

            self.__iconlabel.setPixmap(pm)
            self.__iconlabel.setVisible(not pm.isNull())
コード例 #5
0
ファイル: owimageviewer.py プロジェクト: RachitKansal/orange3
class Preview(QWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.__pixmap = QPixmap()
        # Flag indicating if the widget was resized as a result of user
        # initiated window resize. When false the widget will automatically
        # resize/re-position based on pixmap size.
        self.__hasExplicitSize = False
        self.__inUpdateWindowGeometry = False

    def setPixmap(self, pixmap):
        if self.__pixmap != pixmap:
            self.__pixmap = QPixmap(pixmap)
            self.__updateWindowGeometry()
            self.update()
            self.updateGeometry()

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

    def resizeEvent(self, event):
        super().resizeEvent(event)
        if self.isVisible() and self.isWindow() and \
                not self.__inUpdateWindowGeometry:
            # mark that we have an explicit user provided size
            self.__hasExplicitSize = True

    def __updateWindowGeometry(self):
        if not self.isWindow() or self.__hasExplicitSize:
            return

        def framemargins(widget):
            frame, geom = widget.frameGeometry(), widget.geometry()
            return QMargins(geom.left() - frame.left(),
                            geom.top() - frame.top(),
                            geom.right() - frame.right(),
                            geom.bottom() - frame.bottom())

        def fitRect(rect, targetrect):
            size = rect.size().boundedTo(targetgeom.size())
            newrect = QRect(rect.topLeft(), size)
            dx, dy = 0, 0
            if newrect.left() < targetrect.left():
                dx = targetrect.left() - newrect.left()
            if newrect.top() < targetrect.top():
                dy = targetrect.top() - newrect.top()
            if newrect.right() > targetrect.right():
                dx = targetrect.right() - newrect.right()
            if newrect.bottom() > targetrect.bottom():
                dy = targetrect.bottom() - newrect.bottom()
            return newrect.translated(dx, dy)

        margins = framemargins(self)
        minsize = QSize(120, 120)
        pixsize = self.__pixmap.size()
        available = QApplication.desktop().availableGeometry(self)
        available = available.adjusted(margins.left(), margins.top(),
                                       -margins.right(), -margins.bottom())
        # extra adjustment so the preview does not cover the whole desktop
        available = available.adjusted(10, 10, -10, -10)
        targetsize = pixsize.boundedTo(available.size()).expandedTo(minsize)
        pixsize.scale(targetsize, Qt.KeepAspectRatio)

        if not self.testAttribute(Qt.WA_WState_Created) or \
                self.testAttribute(Qt.WA_WState_Hidden):
            center = available.center()
        else:
            center = self.geometry().center()
        targetgeom = QRect(QPoint(0, 0), pixsize)
        targetgeom.moveCenter(center)
        if not available.contains(targetgeom):
            targetgeom = fitRect(targetgeom, available)
        self.__inUpdateWindowGeometry = True
        self.setGeometry(targetgeom)
        self.__inUpdateWindowGeometry = False

    def sizeHint(self):
        return self.__pixmap.size()

    def paintEvent(self, event):
        if self.__pixmap.isNull():
            return

        sourcerect = QRect(QPoint(0, 0), self.__pixmap.size())
        pixsize = QSizeF(self.__pixmap.size())
        rect = self.contentsRect()
        pixsize.scale(QSizeF(rect.size()), Qt.KeepAspectRatio)
        targetrect = QRectF(QPointF(0, 0), pixsize)
        targetrect.moveCenter(QPointF(rect.center()))
        painter = QPainter(self)
        painter.setRenderHint(QPainter.SmoothPixmapTransform)
        painter.drawPixmap(targetrect, self.__pixmap, QRectF(sourcerect))
        painter.end()
コード例 #6
0
class Preview(QWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.__pixmap = QPixmap()
        # Flag indicating if the widget was resized as a result of user
        # initiated window resize. When false the widget will automatically
        # resize/re-position based on pixmap size.
        self.__hasExplicitSize = False
        self.__inUpdateWindowGeometry = False

    def setPixmap(self, pixmap):
        if self.__pixmap != pixmap:
            self.__pixmap = QPixmap(pixmap)
            self.__updateWindowGeometry()
            self.update()
            self.updateGeometry()

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

    def resizeEvent(self, event):
        super().resizeEvent(event)
        if self.isVisible() and self.isWindow() and \
                not self.__inUpdateWindowGeometry:
            # mark that we have an explicit user provided size
            self.__hasExplicitSize = True

    def __updateWindowGeometry(self):
        if not self.isWindow() or self.__hasExplicitSize:
            return

        def framemargins(widget):
            frame, geom = widget.frameGeometry(), widget.geometry()
            return QMargins(geom.left() - frame.left(),
                            geom.top() - frame.top(),
                            geom.right() - frame.right(),
                            geom.bottom() - frame.bottom())

        def fitRect(rect, targetrect):
            size = rect.size().boundedTo(targetgeom.size())
            newrect = QRect(rect.topLeft(), size)
            dx, dy = 0, 0
            if newrect.left() < targetrect.left():
                dx = targetrect.left() - newrect.left()
            if newrect.top() < targetrect.top():
                dy = targetrect.top() - newrect.top()
            if newrect.right() > targetrect.right():
                dx = targetrect.right() - newrect.right()
            if newrect.bottom() > targetrect.bottom():
                dy = targetrect.bottom() - newrect.bottom()
            return newrect.translated(dx, dy)

        margins = framemargins(self)
        minsize = QSize(120, 120)
        pixsize = self.__pixmap.size()
        available = QApplication.desktop().availableGeometry(self)
        available = available.adjusted(margins.left(), margins.top(),
                                       -margins.right(), -margins.bottom())
        # extra adjustment so the preview does not cover the whole desktop
        available = available.adjusted(10, 10, -10, -10)
        targetsize = pixsize.boundedTo(available.size()).expandedTo(minsize)
        pixsize.scale(targetsize, Qt.KeepAspectRatio)

        if not self.testAttribute(Qt.WA_WState_Created) or \
                self.testAttribute(Qt.WA_WState_Hidden):
            center = available.center()
        else:
            center = self.geometry().center()
        targetgeom = QRect(QPoint(0, 0), pixsize)
        targetgeom.moveCenter(center)
        if not available.contains(targetgeom):
            targetgeom = fitRect(targetgeom, available)
        self.__inUpdateWindowGeometry = True
        self.setGeometry(targetgeom)
        self.__inUpdateWindowGeometry = False

    def sizeHint(self):
        return self.__pixmap.size()

    def paintEvent(self, event):
        if self.__pixmap.isNull():
            return

        sourcerect = QRect(QPoint(0, 0), self.__pixmap.size())
        pixsize = QSizeF(self.__pixmap.size())
        rect = self.contentsRect()
        pixsize.scale(QSizeF(rect.size()), Qt.KeepAspectRatio)
        targetrect = QRectF(QPointF(0, 0), pixsize)
        targetrect.moveCenter(QPointF(rect.center()))
        painter = QPainter(self)
        painter.setRenderHint(QPainter.SmoothPixmapTransform)
        painter.drawPixmap(targetrect, self.__pixmap, QRectF(sourcerect))
        painter.end()
コード例 #7
0
class GraphicsPixmapWidget(QGraphicsWidget):
    """
    A QGraphicsWidget displaying a QPixmap
    """
    def __init__(self, pixmap=None, parent=None):
        super().__init__(parent)
        self.setCacheMode(QGraphicsItem.ItemCoordinateCache)
        self._pixmap = QPixmap(pixmap) if pixmap is not None else QPixmap()
        self._keepAspect = True
        self._crop = False
        self._subset = True
        self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)

    def setPixmap(self, pixmap):
        self._pixmap = QPixmap(pixmap)
        self.updateGeometry()
        self.update()

    def pixmap(self):
        return QPixmap(self._pixmap)

    def setKeepAspectRatio(self, keep):
        if self._keepAspect != keep:
            self._keepAspect = bool(keep)
            self.update()

    def keepAspectRatio(self):
        return self._keepAspect

    def crop(self):
        return self._crop

    def setCrop(self, crop):
        if self._crop != crop:
            self._crop = bool(crop)
            self.update()

    def setSubset(self, in_subset):
        if self._subset != in_subset:
            self._subset = bool(in_subset)
            self.update()

    def setGeometry(self, rect):
        self.prepareGeometryChange()
        super().setGeometry(rect)

    def sizeHint(self, which, constraint=QSizeF()):
        if which == Qt.PreferredSize:
            return QSizeF(self._pixmap.size())
        else:
            return QGraphicsWidget.sizeHint(self, which, constraint)

    def paint(self, painter, option, widget=0):
        if self._pixmap.isNull():
            return

        rect = self.contentsRect()
        pixsize = QSizeF(self._pixmap.size())
        aspectmode = (Qt.KeepAspectRatio
                      if self._keepAspect else Qt.IgnoreAspectRatio)

        if self._crop:
            height, width = pixsize.height(), pixsize.width()

            diff = abs(height - width)
            if height > width:
                y, x = diff / 2, 0
                h, w = height - diff, width
            else:
                x, y = diff / 2, 0
                w, h = width - diff, height

            source = QRectF(x, y, w, h)
            pixrect = QRectF(QPointF(0, 0), rect.size())

        else:
            source = QRectF(QPointF(0, 0), pixsize)
            pixsize.scale(rect.size(), aspectmode)
            pixrect = QRectF(QPointF(0, 0), pixsize)

        if self._subset:
            painter.setOpacity(1.0)
        else:
            painter.setOpacity(0.35)

        pixrect.moveCenter(rect.center())
        painter.save()
        painter.setPen(QPen(QColor(0, 0, 0, 50), 3))
        painter.drawRoundedRect(pixrect, 2, 2)
        painter.setRenderHint(QPainter.SmoothPixmapTransform)

        painter.drawPixmap(pixrect, self._pixmap, source)
        painter.restore()
コード例 #8
0
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)
コード例 #9
0
ファイル: share.py プロジェクト: rokups/paste2box
    def __init__(self, parent=None, *, mime=None, image=None):
        QDialog.__init__(self, parent)
        self.setupUi(self)
        self._backend = None
        self._backend_controls = {}
        self._label_anonymous = self.tr('Anonymous')
        self._label_select_login = self.tr('Select Login')
        self._available_backends = []

        data = None
        file_name = None
        if image:
            self._share_type = Bi.Image
            data = image
        elif mime:
            if mime.hasImage():
                self._share_type = Bi.Image
                data = mime.imageData()
            elif mime.hasUrls():
                urls = mime.urls()
                if len(urls) == 1:
                    file_path = os.path.realpath(urls[0].toLocalFile())
                    if not os.path.isfile(file_path):
                        raise ValueError(self.tr('Directories can not be shared'))
                    file_size = os.path.getsize(file_path)
                    file_name = os.path.basename(file_path)

                    if file_size > const.BIG_FILE_WARNING_SIZE:
                        file_name = os.path.basename(file_path)
                        nice_size = format_size(file_size)
                        result = QMessageBox.warning(self, self.tr('Warning'),
                                                     self.tr('File "{file_name}" {nice_size}.\n'
                                                             'Are you sure you want to continue?').format(**locals()),
                                                     QMessageBox.Yes | QMessageBox.Abort)
                        if result == QMessageBox.Abort:
                            QTimer.singleShot(0, self.reject)
                            return

                    if file_has_extension(file_path, ('png', 'jpg', 'jpeg', 'bmp', 'gif')):
                        image = QPixmap(file_path)
                    else:
                        image = None
                    if not image or image.isNull():
                        data = read_text_from_file(file_path)
                        if data:
                            self._share_type = Bi.Text
                        else:
                            self._share_type = Bi.File
                            data = file_path
                    else:
                        self._share_type = Bi.Image
                        data = image
                else:
                    raise ValueError(self.tr('Can not share more than one file'))

            elif mime.hasText():
                self._share_type = Bi.Text
                data = mime.text()
        else:
            raise RuntimeError()

        if not data:
            raise ValueError(self.tr('There is no content in your clipboard.\nCopy something in order to share it.'))

        if self._share_type == Bi.Image:
            if not file_name:
                file_name = '{}-{}.png'.format('screenshot' if image else 'image', int(time()))
            if data.width() > self.image_preview.width() or data.height() > self.image_preview.height():
                preview = data.scaled(self.image_preview.size(), Qt.KeepAspectRatio)
            else:
                preview = data
            if isinstance(preview, QImage):
                preview = QPixmap.fromImage(preview)
            self.image_preview.setPixmap(preview)
            self.preview_stack.setCurrentIndex(0)
            buf = QBuffer()
            data.save(buf, 'png', 100)
            data = buf.data().data()
        elif self._share_type == Bi.Text:
            if not file_name:
                file_name = 'file-{}.txt'.format(int(time()))
            self.text_preview.setPlainText(dedent_text_and_truncate(data, 128))
            self.preview_stack.setCurrentIndex(1)
        elif self._share_type == Bi.File:
            if not file_name:
                file_name = 'file-{}.bin'.format(int(time()))
            self.text_preview.setPlainText(self.tr('No preview available'))
            self.preview_stack.setCurrentIndex(1)

        self._file_name = file_name
        self._data = data

        self.populate_backends()

        self.share.pressed.connect(self.share_item)
        self.add_login.pressed.connect(self.on_add_login)
        self.logout.pressed.connect(self.logout_selected)
        self.login_list.currentIndexChanged.connect(self.select_login)

        min_height = self.backend_selector.minimumSizeHint().height()
        if os.name == 'nt':
            # On windows tab widget and font are rather small
            min_height -= 5
            for el in (self.add_login, self.login_list, self.logout, self.share):
                font = el.font()
                font.setPointSize(12)
                el.setFont(font)
            self.login_list.setFixedHeight(self.add_login.height() - 2)
        self.backend_selector.setFixedHeight(min_height)
        self.backend_selector.currentChanged.connect(self.select_backend)
        if self.backend_selector.height() < self.add_login.height():
            # Move tab widget down based on size of controls on the right. Makes widgets below seem to belong to the
            # selected tab.
            self.backend_selector.move(0, self.add_login.height() - self.backend_selector.height())

        self.resize(self.width(), 0)
        self.setWindowState((self.windowState() & ~Qt.WindowMinimized) | Qt.WindowActive)
        self.raise_()
        self.activateWindow()
コード例 #10
0
class GraphicsPixmapWidget(QGraphicsWidget):
    """
    A QGraphicsWidget displaying a QPixmap
    """

    def __init__(self, pixmap=None, parent=None):
        super().__init__(parent)
        self.setCacheMode(QGraphicsItem.ItemCoordinateCache)
        self._pixmap = QPixmap(pixmap) if pixmap is not None else QPixmap()
        self._keepAspect = True
        self._crop = False
        self._subset = True
        self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)

    def setPixmap(self, pixmap):
        self._pixmap = QPixmap(pixmap)
        self.updateGeometry()
        self.update()

    def pixmap(self):
        return QPixmap(self._pixmap)

    def setKeepAspectRatio(self, keep):
        if self._keepAspect != keep:
            self._keepAspect = bool(keep)
            self.update()

    def keepAspectRatio(self):
        return self._keepAspect

    def crop(self):
        return self._crop

    def setCrop(self, crop):
        if self._crop != crop:
            self._crop = bool(crop)
            self.update()

    def setSubset(self, in_subset):
        if self._subset != in_subset:
            self._subset = bool(in_subset)
            self.update()

    def setGeometry(self, rect):
        self.prepareGeometryChange()
        super().setGeometry(rect)

    def sizeHint(self, which, constraint=QSizeF()):
        if which == Qt.PreferredSize:
            return QSizeF(self._pixmap.size())
        else:
            return QGraphicsWidget.sizeHint(self, which, constraint)

    def paint(self, painter, option, widget=0):
        if self._pixmap.isNull():
            return

        rect = self.contentsRect()
        pixsize = QSizeF(self._pixmap.size())
        aspectmode = (Qt.KeepAspectRatio if self._keepAspect else Qt.IgnoreAspectRatio)

        if self._crop:
            height, width = pixsize.height(), pixsize.width()

            diff = abs(height - width)
            if height > width:
                y, x = diff / 2, 0
                h, w = height - diff, width
            else:
                x, y = diff / 2, 0
                w, h = width - diff, height

            source = QRectF(x, y, w, h)
            pixrect = QRectF(QPointF(0, 0), rect.size())

        else:
            source = QRectF(QPointF(0, 0), pixsize)
            pixsize.scale(rect.size(), aspectmode)
            pixrect = QRectF(QPointF(0, 0), pixsize)

        if self._subset:
            painter.setOpacity(1.0)
        else:
            painter.setOpacity(0.35)

        pixrect.moveCenter(rect.center())
        painter.save()
        painter.setPen(QPen(QColor(0, 0, 0, 50), 3))
        painter.drawRoundedRect(pixrect, 2, 2)
        painter.setRenderHint(QPainter.SmoothPixmapTransform)

        painter.drawPixmap(pixrect, self._pixmap, source)
        painter.restore()