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