Example #1
0
def main(argv=sys.argv):
    if len(argv) == 1:
        filename = None
    else:
        if argv[1] in ["-h", "--help"]:
            usage(argv)
            return 0
        else:
            filename = argv[1]
    
    app = QApplication(argv)
    app.setAttribute(Qt.AA_EnableHighDpiScaling)
    app.setAttribute(Qt.AA_UseHighDpiPixmaps)
    if filename is None:
        filename, _ = QFileDialog.getOpenFileName(
            None, "Image file", os.path.expanduser("~/Documents"),
            "Image (*.png)")
        if not filename:
            return 1
        print(filename)

    form = MainForm(filename=filename)
    rect = QApplication.desktop().availableGeometry()
    form.show()
    form.raise_()
    return app.exec_()
Example #2
0
 def _get_buffer(size, filename):
     buffer = QtGui.QPdfWriter(filename)
     dpi = QApplication.desktop().logicalDpiX()
     buffer.setResolution(dpi)
     buffer.setPageMargins(QMarginsF(0, 0, 0, 0))
     buffer.setPageSizeMM(QtCore.QSizeF(size.width(), size.height()) / dpi * 25.4)
     return buffer
Example #3
0
    def popup(self, pos=None, searchText=""):
        """
        Popup the menu at `pos` (in screen coordinates). 'Search' text field
        is initialized with `searchText` if provided.

        """
        if pos is None:
            pos = QPoint()

        self.__clearCurrentItems()

        self.__search.setText(searchText)
        patt = QRegExp("(^|\W)"+searchText)
        patt.setCaseSensitivity(False)
        self.__suggestPage.setFilterRegExp(patt)

        self.ensurePolished()

        if self.testAttribute(Qt.WA_Resized) and self.sizeGripEnabled():
            size = self.size()
        else:
            size = self.sizeHint()

        desktop = QApplication.desktop()
        screen_geom = desktop.availableGeometry(pos)

        # Adjust the size to fit inside the screen.
        if size.height() > screen_geom.height():
            size.setHeight(screen_geom.height())
        if size.width() > screen_geom.width():
            size.setWidth(screen_geom.width())

        geom = QRect(pos, size)

        if geom.top() < screen_geom.top():
            geom.setTop(screen_geom.top())

        if geom.left() < screen_geom.left():
            geom.setLeft(screen_geom.left())

        bottom_margin = screen_geom.bottom() - geom.bottom()
        right_margin = screen_geom.right() - geom.right()
        if bottom_margin < 0:
            # Falls over the bottom of the screen, move it up.
            geom.translate(0, bottom_margin)

        # TODO: right to left locale
        if right_margin < 0:
            # Falls over the right screen edge, move the menu to the
            # other side of pos.
            geom.translate(-size.width(), 0)

        self.setGeometry(geom)

        self.show()

        if searchText:
            self.setFocusProxy(self.__search)
        else:
            self.setFocusProxy(None)
Example #4
0
    def popup(self, pos=None, searchText=""):
        """
        Popup the menu at `pos` (in screen coordinates). 'Search' text field
        is initialized with `searchText` if provided.

        """
        if pos is None:
            pos = QPoint()

        self.__clearCurrentItems()

        self.__search.setText(searchText)
        patt = QRegExp("(^|\W)" + searchText)
        patt.setCaseSensitivity(False)
        self.__suggestPage.setFilterRegExp(patt)

        self.ensurePolished()

        if self.testAttribute(Qt.WA_Resized) and self.sizeGripEnabled():
            size = self.size()
        else:
            size = self.sizeHint()

        desktop = QApplication.desktop()
        screen_geom = desktop.availableGeometry(pos)

        # Adjust the size to fit inside the screen.
        if size.height() > screen_geom.height():
            size.setHeight(screen_geom.height())
        if size.width() > screen_geom.width():
            size.setWidth(screen_geom.width())

        geom = QRect(pos, size)

        if geom.top() < screen_geom.top():
            geom.setTop(screen_geom.top())

        if geom.left() < screen_geom.left():
            geom.setLeft(screen_geom.left())

        bottom_margin = screen_geom.bottom() - geom.bottom()
        right_margin = screen_geom.right() - geom.right()
        if bottom_margin < 0:
            # Falls over the bottom of the screen, move it up.
            geom.translate(0, bottom_margin)

        # TODO: right to left locale
        if right_margin < 0:
            # Falls over the right screen edge, move the menu to the
            # other side of pos.
            geom.translate(-size.width(), 0)

        self.setGeometry(geom)

        self.show()

        if searchText:
            self.setFocusProxy(self.__search)
        else:
            self.setFocusProxy(None)
Example #5
0
    def __setControlAreaVisible(self, visible):
        # type: (bool) -> None
        if self.__splitter is None or self.__splitter.count() < 2:
            return
        self.controlAreaVisible = visible
        splitter = self.__splitter  # type: QSplitter
        w = splitter.widget(0)
        # Set minimum width to 1 (overrides minimumSizeHint) when control area
        # is not visible to allow the main area to shrink further. Reset the
        # minimum width with a 0 if control area is visible.
        w.setMinimumWidth(int(not visible))

        sizes = splitter.sizes()
        current_size = sizes[0]
        if bool(current_size) == visible:
            return

        current_width = w.width()
        geom = self.geometry()
        frame = self.frameGeometry()
        framemargins = QMargins(
            frame.left() - geom.left(),
            frame.top() - geom.top(),
            frame.right() - geom.right(),
            frame.bottom() - geom.bottom()
        )
        splitter.setSizes([int(visible), QWIDGETSIZE_MAX])
        if not self.isWindow() or \
                self.windowState() not in [Qt.WindowNoState, Qt.WindowActive]:
            # not a window or not in state where we can move move/resize
            return

        # force immediate resize recalculation
        splitter.refresh()
        self.layout().invalidate()
        self.layout().activate()

        if visible:
            # move left and expand by the exposing widget's width
            diffx = -w.width()
            diffw = w.width()
        else:
            # move right and shrink by the collapsing width
            diffx = current_width
            diffw = -current_width
        newgeom = QRect(
            geom.x() + diffx, geom.y(), geom.width() + diffw, geom.height()
        )
        # bound/move by available geometry
        bounds = QApplication.desktop().availableGeometry(self)
        bounds = bounds.adjusted(
            framemargins.left(), framemargins.top(),
            -framemargins.right(), -framemargins.bottom()
        )
        newsize = newgeom.size().boundedTo(bounds.size())
        newgeom = QRect(newgeom.topLeft(), newsize)
        newgeom.moveLeft(max(newgeom.left(), bounds.left()))
        newgeom.moveRight(min(newgeom.right(), bounds.right()))
        self.setGeometry(newgeom)
Example #6
0
    def __setControlAreaVisible(self, visible):
        # type: (bool) -> None
        if self.__splitter is None or self.__splitter.count() < 2:
            return
        self.controlAreaVisible = visible
        splitter = self.__splitter  # type: QSplitter
        w = splitter.widget(0)
        # Set minimum width to 1 (overrides minimumSizeHint) when control area
        # is not visible to allow the main area to shrink further. Reset the
        # minimum width with a 0 if control area is visible.
        w.setMinimumWidth(int(not visible))

        sizes = splitter.sizes()
        current_size = sizes[0]
        if bool(current_size) == visible:
            return

        current_width = w.width()
        geom = self.geometry()
        frame = self.frameGeometry()
        framemargins = QMargins(
            frame.left() - geom.left(),
            frame.top() - geom.top(),
            frame.right() - geom.right(),
            frame.bottom() - geom.bottom()
        )
        splitter.setSizes([int(visible), QWIDGETSIZE_MAX])
        if not self.isWindow() or \
                self.windowState() not in [Qt.WindowNoState, Qt.WindowActive]:
            # not a window or not in state where we can move move/resize
            return

        # force immediate resize recalculation
        splitter.refresh()
        self.layout().invalidate()
        self.layout().activate()

        if visible:
            # move left and expand by the exposing widget's width
            diffx = -w.width()
            diffw = w.width()
        else:
            # move right and shrink by the collapsing width
            diffx = current_width
            diffw = -current_width
        newgeom = QRect(
            geom.x() + diffx, geom.y(), geom.width() + diffw, geom.height()
        )
        # bound/move by available geometry
        bounds = QApplication.desktop().availableGeometry(self)
        bounds = bounds.adjusted(
            framemargins.left(), framemargins.top(),
            -framemargins.right(), -framemargins.bottom()
        )
        newsize = newgeom.size().boundedTo(bounds.size())
        newgeom = QRect(newgeom.topLeft(), newsize)
        newgeom.moveLeft(max(newgeom.left(), bounds.left()))
        newgeom.moveRight(min(newgeom.right(), bounds.right()))
        self.setGeometry(newgeom)
Example #7
0
    def __init__(self, parent=None):
        super().__init__(parent, Qt.CustomizeWindowHint | Qt.FramelessWindowHint | Qt.Window |
                         Qt.WindowStaysOnTopHint | Qt.X11BypassWindowManagerHint)
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.installEventFilter(self)
        self.setMouseTracking(True)
        self._band = QRubberBand(QRubberBand.Rectangle, self)

        self._resize_origin = None
        self._drag_mask = 0
        self._origin = None
        self.selected_image = None

        # Window background
        desktop = QApplication.desktop()
        if is_qt5():
            g = desktop.geometry()
            self._snapshot = QPixmap(g.width(), g.height())
            painter = QPainter(self._snapshot)
            for screen in QApplication.screens():
                g = screen.geometry()
                painter.drawPixmap(g, screen.grabWindow(0, g.x(), g.y(), g.width(), g.height()))
            painter.end()
        else:
            self._snapshot = QPixmap.grabWindow(desktop.winId(), 0, 0, desktop.width(), desktop.height())

        self.setGeometry(desktop.geometry())
        self._darken = self._snapshot.copy()
        painter = QPainter(self._darken)
        brush = QBrush(QColor(0, 0, 0, 128))
        painter.setBrush(brush)
        painter.drawRect(self._darken.rect())
        painter.end()

        # Buttons
        self._buttons = QWidget(self)
        self._button_layout = QHBoxLayout(self._buttons)
        self._button_layout.setSpacing(0)
        self._button_layout.setContentsMargins(0, 0, 0, 0)
        self._button_layout.setContentsMargins(0, 0, 0, 0)
        self.save_as = QPushButton(self.tr('Save As'))
        self.save_as.pressed.connect(self.save_image_as)
        self.save_as.setCursor(Qt.ArrowCursor)
        self._button_layout.addWidget(self.save_as)
        self.copy = QPushButton(self.tr('Copy'))
        self.copy.pressed.connect(self.copy_to_clipboard)
        self.copy.setCursor(Qt.ArrowCursor)
        self._button_layout.addWidget(self.copy)
        self.share = QPushButton(self.tr('Share'))
        self.share.pressed.connect(self.share_selection)
        self.share.setCursor(Qt.ArrowCursor)
        self._button_layout.addWidget(self.share)
        self._buttons.hide()
    def __restoreWidgetGeometry(self):
        def _fullscreen_to_maximized(geometry):
            """Don't restore windows into full screen mode because it loses
            decorations and can't be de-fullscreened at least on some platforms.
            Use Maximized state insted."""
            w = QWidget(visible=False)
            w.restoreGeometry(QByteArray(geometry))
            if w.isFullScreen():
                w.setWindowState(
                    w.windowState() & ~Qt.WindowFullScreen | Qt.WindowMaximized
                )
            return w.saveGeometry()

        restored = False
        if self.save_position:
            geometry = self.savedWidgetGeometry
            if geometry is not None:
                geometry = _fullscreen_to_maximized(geometry)
                restored = self.restoreGeometry(geometry)

            if restored and not self.windowState() & (
                Qt.WindowMaximized | Qt.WindowFullScreen
            ):
                space = QApplication.desktop().availableGeometry(self)
                frame, geometry = self.frameGeometry(), self.geometry()

                # Fix the widget size to fit inside the available space
                width = space.width() - (frame.width() - geometry.width())
                width = min(width, geometry.width())
                height = space.height() - (frame.height() - geometry.height())
                height = min(height, geometry.height())
                self.resize(width, height)

                # Move the widget to the center of available space if it is
                # currently outside it
                if not space.contains(self.frameGeometry()):
                    x = max(0, space.width() / 2 - width / 2)
                    y = max(0, space.height() / 2 - height / 2)

                    self.move(x, y)

        # Mark as explicitly moved/resized if not already. QDialog would
        # otherwise adjust position/size on subsequent hide/show
        # (move/resize events coming from the window manager do not set
        # these flags).
        if not self.testAttribute(Qt.WA_Moved):
            self.setAttribute(Qt.WA_Moved)
        if not self.testAttribute(Qt.WA_Resized):
            self.setAttribute(Qt.WA_Resized)

        return restored
Example #9
0
    def __restoreWidgetGeometry(self):

        def _fullscreen_to_maximized(geometry):
            """Don't restore windows into full screen mode because it loses
            decorations and can't be de-fullscreened at least on some platforms.
            Use Maximized state insted."""
            w = QWidget(visible=False)
            w.restoreGeometry(QByteArray(geometry))
            if w.isFullScreen():
                w.setWindowState(
                    w.windowState() & ~Qt.WindowFullScreen | Qt.WindowMaximized)
            return w.saveGeometry()

        restored = False
        if self.save_position:
            geometry = self.savedWidgetGeometry
            if geometry is not None:
                geometry = _fullscreen_to_maximized(geometry)
                restored = self.restoreGeometry(geometry)

            if restored and not self.windowState() & \
                    (Qt.WindowMaximized | Qt.WindowFullScreen):
                space = QApplication.desktop().availableGeometry(self)
                frame, geometry = self.frameGeometry(), self.geometry()

                #Fix the widget size to fit inside the available space
                width = space.width() - (frame.width() - geometry.width())
                width = min(width, geometry.width())
                height = space.height() - (frame.height() - geometry.height())
                height = min(height, geometry.height())
                self.resize(width, height)

                # Move the widget to the center of available space if it is
                # currently outside it
                if not space.contains(self.frameGeometry()):
                    x = max(0, space.width() / 2 - width / 2)
                    y = max(0, space.height() / 2 - height / 2)

                    self.move(x, y)

        # Mark as explicitly moved/resized if not already. QDialog would
        # otherwise adjust position/size on subsequent hide/show
        # (move/resize events coming from the window manager do not set
        # these flags).
        if not self.testAttribute(Qt.WA_Moved):
            self.setAttribute(Qt.WA_Moved)
        if not self.testAttribute(Qt.WA_Resized):
            self.setAttribute(Qt.WA_Resized)

        return restored
Example #10
0
    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
Example #11
0
    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
Example #12
0
 def export(self, filename=None):
     pw = QPdfWriter(filename)
     dpi = QApplication.desktop().logicalDpiX()
     pw.setResolution(dpi)
     pw.setPageMargins(QMarginsF(0, 0, 0, 0))
     pw.setPageSizeMM(QSizeF(self.getTargetRect().size()) / dpi * 25.4)
     painter = QPainter(pw)
     try:
         self.setExportMode(True, {'antialias': True,
                                   'background': self.background,
                                   'painter': painter})
         painter.setRenderHint(QPainter.Antialiasing, True)
         if QtCore.QT_VERSION >= 0x050D00:
             painter.setRenderHint(QPainter.LosslessImageRendering, True)
         self.getScene().render(painter,
                                QRectF(self.getTargetRect()),
                                QRectF(self.getSourceRect()))
     finally:
         self.setExportMode(False)
     painter.end()
Example #13
0
def popup_position_from_source(popup, source, orientation=Qt.Vertical):
    # type: (QWidget, QWidget, Qt.Orientation) -> QPoint
    popup.ensurePolished()
    source.ensurePolished()

    if popup.testAttribute(Qt.WA_Resized):
        size = popup.size()
    else:
        size = popup.sizeHint()

    desktop = QApplication.desktop()
    screen_geom = desktop.availableGeometry(source)
    source_rect = QRect(source.mapToGlobal(QPoint(0, 0)), source.size())

    if orientation == Qt.Vertical:
        if source_rect.right() + size.width() < screen_geom.right():
            x = source_rect.right()
        else:
            x = source_rect.left() - size.width()

        # bottom overflow
        dy = source_rect.top() + size.height() - screen_geom.bottom()
        if dy < 0:
            y = source_rect.top()
        else:
            y = source_rect.top() - dy
    else:
        # right overflow
        dx = source_rect.left() + size.width() - screen_geom.right()
        if dx < 0:
            x = source_rect.left()
        else:
            x = source_rect.left() - dx

        if source_rect.bottom() + size.height() < screen_geom.bottom():
            y = source_rect.bottom()
        else:
            y = source_rect.top() - size.height()

    return QPoint(x, y)
Example #14
0
    def __restoreWidgetGeometry(self):

        def _fullscreen_to_maximized(geometry):
            """Don't restore windows into full screen mode because it loses
            decorations and can't be de-fullscreened at least on some platforms.
            Use Maximized state insted."""
            w = QWidget(visible=False)
            w.restoreGeometry(QByteArray(geometry))
            if w.isFullScreen():
                w.setWindowState(
                    w.windowState() & ~Qt.WindowFullScreen | Qt.WindowMaximized)
            return w.saveGeometry()

        restored = False
        if self.save_position:
            geometry = self.savedWidgetGeometry
            if geometry is not None:
                geometry = _fullscreen_to_maximized(geometry)
                restored = self.restoreGeometry(geometry)

            if restored and not self.windowState() & \
                    (Qt.WindowMaximized | Qt.WindowFullScreen):
                space = QApplication.desktop().availableGeometry(self)
                frame, geometry = self.frameGeometry(), self.geometry()

                #Fix the widget size to fit inside the available space
                width = space.width() - (frame.width() - geometry.width())
                width = min(width, geometry.width())
                height = space.height() - (frame.height() - geometry.height())
                height = min(height, geometry.height())
                self.resize(width, height)

                # Move the widget to the center of available space if it is
                # currently outside it
                if not space.contains(self.frameGeometry()):
                    x = max(0, space.width() / 2 - width / 2)
                    y = max(0, space.height() / 2 - height / 2)

                    self.move(x, y)
        return restored
Example #15
0
    def __restoreWidgetGeometry(self):

        def _fullscreen_to_maximized(geometry):
            """Don't restore windows into full screen mode because it loses
            decorations and can't be de-fullscreened at least on some platforms.
            Use Maximized state insted."""
            w = QWidget(visible=False)
            w.restoreGeometry(QByteArray(geometry))
            if w.isFullScreen():
                w.setWindowState(
                    w.windowState() & ~Qt.WindowFullScreen | Qt.WindowMaximized)
            return w.saveGeometry()

        restored = False
        if self.save_position:
            geometry = self.savedWidgetGeometry
            if geometry is not None:
                geometry = _fullscreen_to_maximized(geometry)
                restored = self.restoreGeometry(geometry)

            if restored and not self.windowState() & \
                    (Qt.WindowMaximized | Qt.WindowFullScreen):
                space = QApplication.desktop().availableGeometry(self)
                frame, geometry = self.frameGeometry(), self.geometry()

                #Fix the widget size to fit inside the available space
                width = space.width() - (frame.width() - geometry.width())
                width = min(width, geometry.width())
                height = space.height() - (frame.height() - geometry.height())
                height = min(height, geometry.height())
                self.resize(width, height)

                # Move the widget to the center of available space if it is
                # currently outside it
                if not space.contains(self.frameGeometry()):
                    x = max(0, space.width() / 2 - width / 2)
                    y = max(0, space.height() / 2 - height / 2)

                    self.move(x, y)
        return restored
Example #16
0
def widget_popup_geometry(pos, widget):
    # type: (QPoint, QWidget) -> QRect
    widget.ensurePolished()

    if widget.testAttribute(Qt.WA_Resized):
        size = widget.size()
    else:
        size = widget.sizeHint()

    desktop = QApplication.desktop()
    screen_geom = desktop.availableGeometry(pos)

    # Adjust the size to fit inside the screen.
    if size.height() > screen_geom.height():
        size.setHeight(screen_geom.height())
    if size.width() > screen_geom.width():
        size.setWidth(screen_geom.width())

    geom = QRect(pos, size)

    if geom.top() < screen_geom.top():
        geom.setTop(screen_geom.top())

    if geom.left() < screen_geom.left():
        geom.setLeft(screen_geom.left())

    bottom_margin = screen_geom.bottom() - geom.bottom()
    right_margin = screen_geom.right() - geom.right()
    if bottom_margin < 0:
        # Falls over the bottom of the screen, move it up.
        geom.translate(0, bottom_margin)

    # TODO: right to left locale
    if right_margin < 0:
        # Falls over the right screen edge, move the menu to the
        # other side of pos.
        geom.translate(-size.width(), 0)

    return geom
def popup_position_from_source(popup, source, orientation=Qt.Vertical):
    popup.ensurePolished()
    source.ensurePolished()

    if popup.testAttribute(Qt.WA_Resized):
        size = popup.size()
    else:
        size = popup.sizeHint()

    desktop = QApplication.desktop()
    screen_geom = desktop.availableGeometry(source)
    source_rect = QRect(source.mapToGlobal(QPoint(0, 0)), source.size())

    if orientation == Qt.Vertical:
        if source_rect.right() + size.width() < screen_geom.right():
            x = source_rect.right()
        else:
            x = source_rect.left() - size.width()

        # bottom overflow
        dy = source_rect.top() + size.height() - screen_geom.bottom()
        if dy < 0:
            y = source_rect.top()
        else:
            y = source_rect.top() - dy
    else:
        # right overflow
        dx = source_rect.left() + size.width() - screen_geom.right()
        if dx < 0:
            x = source_rect.left()
        else:
            x = source_rect.left() - dx

        if source_rect.bottom() + size.height() < screen_geom.bottom():
            y = source_rect.bottom()
        else:
            y = source_rect.top() - size.height()

    return QPoint(x, y)
def widget_popup_geometry(pos, widget):
    widget.ensurePolished()

    if widget.testAttribute(Qt.WA_Resized):
        size = widget.size()
    else:
        size = widget.sizeHint()

    desktop = QApplication.desktop()
    screen_geom = desktop.availableGeometry(pos)

    # Adjust the size to fit inside the screen.
    if size.height() > screen_geom.height():
        size.setHeight(screen_geom.height())
    if size.width() > screen_geom.width():
        size.setWidth(screen_geom.width())

    geom = QRect(pos, size)

    if geom.top() < screen_geom.top():
        geom.setTop(screen_geom.top())

    if geom.left() < screen_geom.left():
        geom.setLeft(screen_geom.left())

    bottom_margin = screen_geom.bottom() - geom.bottom()
    right_margin = screen_geom.right() - geom.right()
    if bottom_margin < 0:
        # Falls over the bottom of the screen, move it up.
        geom.translate(0, bottom_margin)

    # TODO: right to left locale
    if right_margin < 0:
        # Falls over the right screen edge, move the menu to the
        # other side of pos.
        geom.translate(-size.width(), 0)

    return geom
Example #19
0
    def showPopup(self):
        # type: () -> None
        """
        Reimplemented from QComboBox.showPopup

        Popup up a customized view and filter edit line.

        Note
        ----
        The .popup(), .lineEdit(), .completer() of the base class are not used.
        """
        if self.__popup is not None:
            # We have user entered state that cannot be disturbed
            # (entered filter text, scroll offset, ...)
            return  # pragma: no cover

        if self.count() == 0:
            return

        opt = QStyleOptionComboBox()
        self.initStyleOption(opt)
        popup = QListView(
            uniformItemSizes=True,
            horizontalScrollBarPolicy=Qt.ScrollBarAlwaysOff,
            verticalScrollBarPolicy=Qt.ScrollBarAsNeeded,
            iconSize=self.iconSize(),
        )
        popup.setFocusProxy(self.__searchline)
        popup.setParent(self, Qt.Popup | Qt.FramelessWindowHint)
        popup.setItemDelegate(_ComboBoxListDelegate(popup))
        proxy = QSortFilterProxyModel(
            popup, filterCaseSensitivity=Qt.CaseInsensitive
        )
        proxy.setFilterKeyColumn(self.modelColumn())
        proxy.setSourceModel(self.model())
        popup.setModel(proxy)
        root = proxy.mapFromSource(self.rootModelIndex())
        popup.setRootIndex(root)

        self.__popup = popup
        self.__proxy = proxy
        self.__searchline.setText("")
        self.__searchline.setPlaceholderText("Filter...")
        self.__searchline.setVisible(True)
        self.__searchline.textEdited.connect(proxy.setFilterFixedString)

        style = self.style()  # type: QStyle

        popuprect_origin = style.subControlRect(
            QStyle.CC_ComboBox, opt, QStyle.SC_ComboBoxListBoxPopup, self
        )  # type: QRect
        popuprect_origin = QRect(
            self.mapToGlobal(popuprect_origin.topLeft()),
            popuprect_origin.size()
        )
        editrect = style.subControlRect(
            QStyle.CC_ComboBox, opt, QStyle.SC_ComboBoxEditField, self
        )  # type: QRect
        self.__searchline.setGeometry(editrect)
        desktop = QApplication.desktop()
        screenrect = desktop.availableGeometry(self)  # type: QRect

        # get the height for the view
        listrect = QRect()
        for i in range(min(proxy.rowCount(root), self.maxVisibleItems())):
            index = proxy.index(i, self.modelColumn(), root)
            if index.isValid():
                listrect = listrect.united(popup.visualRect(index))
            if listrect.height() >= screenrect.height():
                break
        window = popup.window()  # type: QWidget
        window.ensurePolished()
        if window.layout() is not None:
            window.layout().activate()
        else:
            QApplication.sendEvent(window, QEvent(QEvent.LayoutRequest))

        margins = qwidget_margin_within(popup.viewport(), window)
        height = (listrect.height() + 2 * popup.spacing() +
                  margins.top() + margins.bottom())

        popup_size = (QSize(popuprect_origin.width(), height)
                      .expandedTo(window.minimumSize())
                      .boundedTo(window.maximumSize())
                      .boundedTo(screenrect.size()))
        popuprect = QRect(popuprect_origin.bottomLeft(), popup_size)

        popuprect = dropdown_popup_geometry(
            popuprect, popuprect_origin, screenrect)
        popup.setGeometry(popuprect)

        current = proxy.mapFromSource(
            self.model().index(self.currentIndex(), self.modelColumn(),
                               self.rootModelIndex()))
        popup.setCurrentIndex(current)
        popup.scrollTo(current, QAbstractItemView.EnsureVisible)
        popup.show()
        popup.setFocus(Qt.PopupFocusReason)
        popup.installEventFilter(self)
        popup.viewport().installEventFilter(self)
        popup.viewport().setMouseTracking(True)
        self.update()
        self.__popupTimer.restart()
Example #20
0
    def showPopup(self):
        # type: () -> None
        """
        Reimplemented from QComboBox.showPopup

        Popup up a customized view and filter edit line.

        Note
        ----
        The .popup(), .lineEdit(), .completer() of the base class are not used.
        """
        if self.__popup is not None:
            # We have user entered state that cannot be disturbed
            # (entered filter text, scroll offset, ...)
            return  # pragma: no cover

        if self.count() == 0:
            return

        opt = QStyleOptionComboBox()
        self.initStyleOption(opt)
        popup = QListView(
            uniformItemSizes=True,
            horizontalScrollBarPolicy=Qt.ScrollBarAlwaysOff,
            verticalScrollBarPolicy=Qt.ScrollBarAsNeeded,
            iconSize=self.iconSize(),
        )
        popup.setFocusProxy(self.__searchline)
        popup.setParent(self, Qt.Popup | Qt.FramelessWindowHint)
        popup.setItemDelegate(_ComboBoxListDelegate(popup))
        proxy = QSortFilterProxyModel(
            popup, filterCaseSensitivity=Qt.CaseInsensitive
        )
        proxy.setFilterKeyColumn(self.modelColumn())
        proxy.setSourceModel(self.model())
        popup.setModel(proxy)
        root = proxy.mapFromSource(self.rootModelIndex())
        popup.setRootIndex(root)

        self.__popup = popup
        self.__proxy = proxy
        self.__searchline.setText("")
        self.__searchline.setPlaceholderText("Filter...")
        self.__searchline.setVisible(True)
        self.__searchline.textEdited.connect(proxy.setFilterFixedString)

        style = self.style()  # type: QStyle

        popuprect_origin = style.subControlRect(
            QStyle.CC_ComboBox, opt, QStyle.SC_ComboBoxListBoxPopup, self
        )  # type: QRect
        popuprect_origin = QRect(
            self.mapToGlobal(popuprect_origin.topLeft()),
            popuprect_origin.size()
        )
        editrect = style.subControlRect(
            QStyle.CC_ComboBox, opt, QStyle.SC_ComboBoxEditField, self
        )  # type: QRect
        self.__searchline.setGeometry(editrect)
        desktop = QApplication.desktop()
        screenrect = desktop.availableGeometry(self)  # type: QRect

        # get the height for the view
        listrect = QRect()
        for i in range(min(proxy.rowCount(root), self.maxVisibleItems())):
            index = proxy.index(i, self.modelColumn(), root)
            if index.isValid():
                listrect = listrect.united(popup.visualRect(index))
            if listrect.height() >= screenrect.height():
                break
        window = popup.window()  # type: QWidget
        window.ensurePolished()
        if window.layout() is not None:
            window.layout().activate()
        else:
            QApplication.sendEvent(window, QEvent(QEvent.LayoutRequest))

        margins = qwidget_margin_within(popup.viewport(), window)
        height = (listrect.height() + 2 * popup.spacing() +
                  margins.top() + margins.bottom())

        popup_size = (QSize(popuprect_origin.width(), height)
                      .expandedTo(window.minimumSize())
                      .boundedTo(window.maximumSize())
                      .boundedTo(screenrect.size()))
        popuprect = QRect(popuprect_origin.bottomLeft(), popup_size)

        popuprect = dropdown_popup_geometry(
            popuprect, popuprect_origin, screenrect)
        popup.setGeometry(popuprect)

        current = proxy.mapFromSource(
            self.model().index(self.currentIndex(), self.modelColumn(),
                               self.rootModelIndex()))
        popup.setCurrentIndex(current)
        popup.scrollTo(current, QAbstractItemView.EnsureVisible)
        popup.show()
        popup.setFocus(Qt.PopupFocusReason)
        popup.installEventFilter(self)
        popup.viewport().installEventFilter(self)
        popup.viewport().setMouseTracking(True)
        self.update()
        self.__popupTimer.restart()
Example #21
0
 def _get_buffer(size, filename):
     buffer = QtSvg.QSvgGenerator()
     buffer.setResolution(QApplication.desktop().logicalDpiX())
     buffer.setFileName(filename)
     buffer.setSize(QtCore.QSize(int(size.width()), int(size.height())))
     return buffer
Example #22
0
 def _get_buffer(size, filename):
     buffer = QtSvg.QSvgGenerator()
     buffer.setResolution(QApplication.desktop().logicalDpiX())
     buffer.setFileName(filename)
     buffer.setViewBox(QtCore.QRectF(0, 0, size.width(), size.height()))
     return buffer