src/eric7/Snapshot/SnapshotDefaultGrabber.py

branch
eric7
changeset 9209
b99e7fd55fd3
parent 8881
54e42bc2437a
child 9221
bf71ee032bb4
diff -r 3fc8dfeb6ebe -r b99e7fd55fd3 src/eric7/Snapshot/SnapshotDefaultGrabber.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/Snapshot/SnapshotDefaultGrabber.py	Thu Jul 07 11:23:56 2022 +0200
@@ -0,0 +1,204 @@
+# -*- 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 pyqtSignal, Qt, QObject, QTimer, QEvent
+from PyQt6.QtGui import QPixmap, QCursor, QGuiApplication
+from PyQt6.QtWidgets import QWidget
+
+from .SnapshotModes import SnapshotModes
+
+import Globals
+
+
+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)
+        
+        from .SnapshotTimer import SnapshotTimer
+        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