Snapshot/SnapshotDefaultGrabber.py

branch
screenshot
changeset 6914
5ae038f273c4
child 6917
7075ede48c2f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Snapshot/SnapshotDefaultGrabber.py	Mon Apr 01 19:34:58 2019 +0200
@@ -0,0 +1,204 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2019 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a grabber object for non-Wayland desktops.
+"""
+
+from __future__ import unicode_literals
+
+from PyQt5.QtCore import pyqtSignal, Qt, QObject, QTimer, QEvent
+from PyQt5.QtGui import QPixmap, QCursor
+from PyQt5.QtWidgets import QWidget, QApplication
+
+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(SnapshotDefaultGrabber, self).__init__(parent)
+        
+        self.__grabber = None
+        self.__grabberWidget = QWidget(None, Qt.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):
+        """
+        Public method to perform a grab operation potentially after a delay.
+        
+        @param mode screenshot mode
+        @type ScreenshotModes
+        @param delay delay in seconds
+        @type int
+        """
+        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.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:
+            desktop = QApplication.desktop()
+            if Globals.qVersionTuple() >= (5, 0, 0):
+                snapshot = QApplication.screens()[0].grabWindow(
+                    desktop.winId(), desktop.x(), desktop.y(),
+                    desktop.width(), desktop.height())
+            else:
+                snapshot = QPixmap.grabWindow(
+                    desktop.winId(), desktop.x(), desktop.y(),
+                    desktop.width(), desktop.height())
+        elif mode == SnapshotModes.SelectedScreen:
+            desktop = QApplication.desktop()
+            if Globals.qVersionTuple() >= (5, 10, 0):
+                screen = QApplication.screenAt(QCursor.pos())
+                geom = screen.geometry()
+            else:
+                screenId = desktop.screenNumber(QCursor.pos())
+                geom = desktop.screenGeometry(screenId)
+            x = geom.x()
+            y = geom.y()
+            if Globals.qVersionTuple() >= (5, 0, 0):
+                snapshot = QApplication.screens()[0].grabWindow(
+                    desktop.winId(), x, y, geom.width(), geom.height())
+            else:
+                snapshot = QPixmap.grabWindow(
+                    desktop.winId(), x, y, geom.width(), geom.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.MouseButtonPress:
+            if QWidget.mouseGrabber() != self.__grabberWidget:
+                return False
+            if evt.button() == Qt.LeftButton:
+                self.__performGrab(self.__mode)
+        
+        return False

eric ide

mercurial