src/eric7/Snapshot/SnapshotDefaultGrabber.py

Mon, 07 Nov 2022 17:19:58 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Mon, 07 Nov 2022 17:19:58 +0100
branch
eric7
changeset 9482
a2bc06a54d9d
parent 9473
3f23dbf37dbe
child 9624
b47dfa7a137d
permissions
-rw-r--r--

Corrected/acknowledged some bad import style and removed some obsolete code.

# -*- coding: utf-8 -*-

# Copyright (c) 2019 - 2022 Detlev Offenbach <detlev@die-offenbachs.de>
#

"""
Module implementing a grabber object for non-Wayland desktops.
"""

from PyQt6.QtCore import QEvent, QObject, Qt, QTimer, pyqtSignal
from PyQt6.QtGui import QCursor, QGuiApplication, QPixmap
from PyQt6.QtWidgets import QWidget

from eric7 import Globals

from .SnapshotModes import SnapshotModes
from .SnapshotTimer import SnapshotTimer


class SnapshotDefaultGrabber(QObject):
    """
    Class implementing a grabber object for non-Wayland desktops.

    @signal grabbed(QPixmap) emitted after the grab operation is finished
    """

    grabbed = pyqtSignal(QPixmap)

    def __init__(self, parent=None):
        """
        Constructor

        @param parent reference to the parent object
        @type QObject
        """
        super().__init__(parent)

        self.__grabber = None
        self.__grabberWidget = QWidget(None, Qt.WindowType.X11BypassWindowManagerHint)
        self.__grabberWidget.move(-10000, -10000)
        self.__grabberWidget.installEventFilter(self)

        self.__grabTimer = SnapshotTimer()
        self.__grabTimer.timeout.connect(self.__grabTimerTimeout)

    def supportedModes(self):
        """
        Public method to get the supported screenshot modes.

        @return tuple of supported screenshot modes
        @rtype tuple of SnapshotModes
        """
        return (
            SnapshotModes.FULLSCREEN,
            SnapshotModes.SELECTEDSCREEN,
            SnapshotModes.RECTANGLE,
            SnapshotModes.FREEHAND,
            SnapshotModes.ELLIPSE,
        )

    def grab(self, mode, delay=0, captureCursor=False, captureDecorations=False):
        """
        Public method to perform a grab operation potentially after a delay.

        @param mode screenshot mode
        @type ScreenshotModes
        @param delay delay in seconds
        @type int
        @param captureCursor flag indicating to include the mouse cursor
            (not used)
        @type bool
        @param captureDecorations flag indicating to include the window
            decorations (not used)
        @type bool
        """
        self.__mode = mode
        if delay:
            self.__grabTimer.start(delay)
        else:
            QTimer.singleShot(200, self.__startUndelayedGrab)

    def __grabTimerTimeout(self):
        """
        Private slot to perform a delayed grab operation.
        """
        if self.__mode == SnapshotModes.RECTANGLE:
            self.__grabRectangle()
        elif self.__mode == SnapshotModes.ELLIPSE:
            self.__grabEllipse()
        elif self.__mode == SnapshotModes.FREEHAND:
            self.__grabFreehand()
        else:
            self.__performGrab(self.__mode)

    def __startUndelayedGrab(self):
        """
        Private slot to perform an undelayed grab operation.
        """
        if self.__mode == SnapshotModes.RECTANGLE:
            self.__grabRectangle()
        elif self.__mode == SnapshotModes.ELLIPSE:
            self.__grabEllipse()
        elif self.__mode == SnapshotModes.FREEHAND:
            self.__grabFreehand()
        else:
            if Globals.isMacPlatform():
                self.__performGrab(self.__mode)
            else:
                self.__grabberWidget.show()
                self.__grabberWidget.grabMouse(Qt.CursorShape.CrossCursor)

    def __grabRectangle(self):
        """
        Private method to grab a rectangular screen region.
        """
        from .SnapshotRegionGrabber import SnapshotRegionGrabber

        self.__grabber = SnapshotRegionGrabber(mode=SnapshotRegionGrabber.Rectangle)
        self.__grabber.grabbed.connect(self.__captured)

    def __grabEllipse(self):
        """
        Private method to grab an elliptical screen region.
        """
        from .SnapshotRegionGrabber import SnapshotRegionGrabber

        self.__grabber = SnapshotRegionGrabber(mode=SnapshotRegionGrabber.Ellipse)
        self.__grabber.grabbed.connect(self.__captured)

    def __grabFreehand(self):
        """
        Private method to grab a non-rectangular screen region.
        """
        from .SnapshotFreehandGrabber import SnapshotFreehandGrabber

        self.__grabber = SnapshotFreehandGrabber()
        self.__grabber.grabbed.connect(self.__captured)

    def __performGrab(self, mode):
        """
        Private method to perform a screen grab other than a selected region.

        @param mode screenshot mode
        @type SnapshotModes
        """
        self.__grabberWidget.releaseMouse()
        self.__grabberWidget.hide()
        self.__grabTimer.stop()

        if mode == SnapshotModes.FULLSCREEN:
            screen = QGuiApplication.screens()[0]
            vgeom = screen.availableVirtualGeometry()
            snapshot = screen.grabWindow(
                0, vgeom.x(), vgeom.y(), vgeom.width(), vgeom.height()
            )
        elif mode == SnapshotModes.SELECTEDSCREEN:
            screen = QGuiApplication.screenAt(QCursor.pos())
            sgeom = screen.geometry()
            if Globals.isMacPlatform():
                # macOS variant
                snapshot = screen.grabWindow(
                    0, sgeom.x(), sgeom.y(), sgeom.width(), sgeom.height()
                )
            else:
                # Linux variant
                # Windows variant
                snapshot = screen.grabWindow(0, 0, 0, sgeom.width(), sgeom.height())
        else:
            snapshot = QPixmap()

        self.grabbed.emit(snapshot)

    def __captured(self, pixmap):
        """
        Private slot to show a preview of the snapshot.

        @param pixmap pixmap of the snapshot (QPixmap)
        """
        self.__grabber.close()
        snapshot = QPixmap(pixmap)

        self.__grabber.grabbed.disconnect(self.__captured)
        self.__grabber = None

        self.grabbed.emit(snapshot)

    def eventFilter(self, obj, evt):
        """
        Public method to handle event for other objects.

        @param obj reference to the object (QObject)
        @param evt reference to the event (QEvent)
        @return flag indicating that the event should be filtered out (boolean)
        """
        if obj == self.__grabberWidget and evt.type() == QEvent.Type.MouseButtonPress:
            if QWidget.mouseGrabber() != self.__grabberWidget:
                return False
            if evt.button() == Qt.MouseButton.LeftButton:
                self.__performGrab(self.__mode)

        return False

eric ide

mercurial