17 |
17 |
18 |
18 |
19 class SnapshotDefaultGrabber(QObject): |
19 class SnapshotDefaultGrabber(QObject): |
20 """ |
20 """ |
21 Class implementing a grabber object for non-Wayland desktops. |
21 Class implementing a grabber object for non-Wayland desktops. |
22 |
22 |
23 @signal grabbed(QPixmap) emitted after the grab operation is finished |
23 @signal grabbed(QPixmap) emitted after the grab operation is finished |
24 """ |
24 """ |
|
25 |
25 grabbed = pyqtSignal(QPixmap) |
26 grabbed = pyqtSignal(QPixmap) |
26 |
27 |
27 def __init__(self, parent=None): |
28 def __init__(self, parent=None): |
28 """ |
29 """ |
29 Constructor |
30 Constructor |
30 |
31 |
31 @param parent reference to the parent object |
32 @param parent reference to the parent object |
32 @type QObject |
33 @type QObject |
33 """ |
34 """ |
34 super().__init__(parent) |
35 super().__init__(parent) |
35 |
36 |
36 self.__grabber = None |
37 self.__grabber = None |
37 self.__grabberWidget = QWidget( |
38 self.__grabberWidget = QWidget(None, Qt.WindowType.X11BypassWindowManagerHint) |
38 None, Qt.WindowType.X11BypassWindowManagerHint) |
|
39 self.__grabberWidget.move(-10000, -10000) |
39 self.__grabberWidget.move(-10000, -10000) |
40 self.__grabberWidget.installEventFilter(self) |
40 self.__grabberWidget.installEventFilter(self) |
41 |
41 |
42 from .SnapshotTimer import SnapshotTimer |
42 from .SnapshotTimer import SnapshotTimer |
|
43 |
43 self.__grabTimer = SnapshotTimer() |
44 self.__grabTimer = SnapshotTimer() |
44 self.__grabTimer.timeout.connect(self.__grabTimerTimeout) |
45 self.__grabTimer.timeout.connect(self.__grabTimerTimeout) |
45 |
46 |
46 def supportedModes(self): |
47 def supportedModes(self): |
47 """ |
48 """ |
48 Public method to get the supported screenshot modes. |
49 Public method to get the supported screenshot modes. |
49 |
50 |
50 @return tuple of supported screenshot modes |
51 @return tuple of supported screenshot modes |
51 @rtype tuple of SnapshotModes |
52 @rtype tuple of SnapshotModes |
52 """ |
53 """ |
53 return ( |
54 return ( |
54 SnapshotModes.FULLSCREEN, |
55 SnapshotModes.FULLSCREEN, |
55 SnapshotModes.SELECTEDSCREEN, |
56 SnapshotModes.SELECTEDSCREEN, |
56 SnapshotModes.RECTANGLE, |
57 SnapshotModes.RECTANGLE, |
57 SnapshotModes.FREEHAND, |
58 SnapshotModes.FREEHAND, |
58 SnapshotModes.ELLIPSE, |
59 SnapshotModes.ELLIPSE, |
59 ) |
60 ) |
60 |
61 |
61 def grab(self, mode, delay=0, captureCursor=False, |
62 def grab(self, mode, delay=0, captureCursor=False, captureDecorations=False): |
62 captureDecorations=False): |
|
63 """ |
63 """ |
64 Public method to perform a grab operation potentially after a delay. |
64 Public method to perform a grab operation potentially after a delay. |
65 |
65 |
66 @param mode screenshot mode |
66 @param mode screenshot mode |
67 @type ScreenshotModes |
67 @type ScreenshotModes |
68 @param delay delay in seconds |
68 @param delay delay in seconds |
69 @type int |
69 @type int |
70 @param captureCursor flag indicating to include the mouse cursor |
70 @param captureCursor flag indicating to include the mouse cursor |
107 if Globals.isMacPlatform(): |
107 if Globals.isMacPlatform(): |
108 self.__performGrab(self.__mode) |
108 self.__performGrab(self.__mode) |
109 else: |
109 else: |
110 self.__grabberWidget.show() |
110 self.__grabberWidget.show() |
111 self.__grabberWidget.grabMouse(Qt.CursorShape.CrossCursor) |
111 self.__grabberWidget.grabMouse(Qt.CursorShape.CrossCursor) |
112 |
112 |
113 def __grabRectangle(self): |
113 def __grabRectangle(self): |
114 """ |
114 """ |
115 Private method to grab a rectangular screen region. |
115 Private method to grab a rectangular screen region. |
116 """ |
116 """ |
117 from .SnapshotRegionGrabber import SnapshotRegionGrabber |
117 from .SnapshotRegionGrabber import SnapshotRegionGrabber |
118 self.__grabber = SnapshotRegionGrabber( |
118 |
119 mode=SnapshotRegionGrabber.Rectangle) |
119 self.__grabber = SnapshotRegionGrabber(mode=SnapshotRegionGrabber.Rectangle) |
120 self.__grabber.grabbed.connect(self.__captured) |
120 self.__grabber.grabbed.connect(self.__captured) |
121 |
121 |
122 def __grabEllipse(self): |
122 def __grabEllipse(self): |
123 """ |
123 """ |
124 Private method to grab an elliptical screen region. |
124 Private method to grab an elliptical screen region. |
125 """ |
125 """ |
126 from .SnapshotRegionGrabber import SnapshotRegionGrabber |
126 from .SnapshotRegionGrabber import SnapshotRegionGrabber |
127 self.__grabber = SnapshotRegionGrabber( |
127 |
128 mode=SnapshotRegionGrabber.Ellipse) |
128 self.__grabber = SnapshotRegionGrabber(mode=SnapshotRegionGrabber.Ellipse) |
129 self.__grabber.grabbed.connect(self.__captured) |
129 self.__grabber.grabbed.connect(self.__captured) |
130 |
130 |
131 def __grabFreehand(self): |
131 def __grabFreehand(self): |
132 """ |
132 """ |
133 Private method to grab a non-rectangular screen region. |
133 Private method to grab a non-rectangular screen region. |
134 """ |
134 """ |
135 from .SnapshotFreehandGrabber import SnapshotFreehandGrabber |
135 from .SnapshotFreehandGrabber import SnapshotFreehandGrabber |
|
136 |
136 self.__grabber = SnapshotFreehandGrabber() |
137 self.__grabber = SnapshotFreehandGrabber() |
137 self.__grabber.grabbed.connect(self.__captured) |
138 self.__grabber.grabbed.connect(self.__captured) |
138 |
139 |
139 def __performGrab(self, mode): |
140 def __performGrab(self, mode): |
140 """ |
141 """ |
141 Private method to perform a screen grab other than a selected region. |
142 Private method to perform a screen grab other than a selected region. |
142 |
143 |
143 @param mode screenshot mode |
144 @param mode screenshot mode |
144 @type SnapshotModes |
145 @type SnapshotModes |
145 """ |
146 """ |
146 self.__grabberWidget.releaseMouse() |
147 self.__grabberWidget.releaseMouse() |
147 self.__grabberWidget.hide() |
148 self.__grabberWidget.hide() |
148 self.__grabTimer.stop() |
149 self.__grabTimer.stop() |
149 |
150 |
150 if mode == SnapshotModes.FULLSCREEN: |
151 if mode == SnapshotModes.FULLSCREEN: |
151 screen = QGuiApplication.screens()[0] |
152 screen = QGuiApplication.screens()[0] |
152 vgeom = screen.availableVirtualGeometry() |
153 vgeom = screen.availableVirtualGeometry() |
153 snapshot = screen.grabWindow( |
154 snapshot = screen.grabWindow( |
154 0, vgeom.x(), vgeom.y(), vgeom.width(), vgeom.height()) |
155 0, vgeom.x(), vgeom.y(), vgeom.width(), vgeom.height() |
|
156 ) |
155 elif mode == SnapshotModes.SELECTEDSCREEN: |
157 elif mode == SnapshotModes.SELECTEDSCREEN: |
156 screen = QGuiApplication.screenAt(QCursor.pos()) |
158 screen = QGuiApplication.screenAt(QCursor.pos()) |
157 sgeom = screen.geometry() |
159 sgeom = screen.geometry() |
158 if Globals.isMacPlatform(): |
160 if Globals.isMacPlatform(): |
159 # macOS variant |
161 # macOS variant |
161 0, sgeom.x(), sgeom.y(), sgeom.width(), sgeom.height() |
163 0, sgeom.x(), sgeom.y(), sgeom.width(), sgeom.height() |
162 ) |
164 ) |
163 else: |
165 else: |
164 # Linux variant |
166 # Linux variant |
165 # Windows variant |
167 # Windows variant |
166 snapshot = screen.grabWindow( |
168 snapshot = screen.grabWindow(0, 0, 0, sgeom.width(), sgeom.height()) |
167 0, 0, 0, sgeom.width(), sgeom.height()) |
|
168 else: |
169 else: |
169 snapshot = QPixmap() |
170 snapshot = QPixmap() |
170 |
171 |
171 self.grabbed.emit(snapshot) |
172 self.grabbed.emit(snapshot) |
172 |
173 |
173 def __captured(self, pixmap): |
174 def __captured(self, pixmap): |
174 """ |
175 """ |
175 Private slot to show a preview of the snapshot. |
176 Private slot to show a preview of the snapshot. |
176 |
177 |
177 @param pixmap pixmap of the snapshot (QPixmap) |
178 @param pixmap pixmap of the snapshot (QPixmap) |
178 """ |
179 """ |
179 self.__grabber.close() |
180 self.__grabber.close() |
180 snapshot = QPixmap(pixmap) |
181 snapshot = QPixmap(pixmap) |
181 |
182 |
182 self.__grabber.grabbed.disconnect(self.__captured) |
183 self.__grabber.grabbed.disconnect(self.__captured) |
183 self.__grabber = None |
184 self.__grabber = None |
184 |
185 |
185 self.grabbed.emit(snapshot) |
186 self.grabbed.emit(snapshot) |
186 |
187 |
187 def eventFilter(self, obj, evt): |
188 def eventFilter(self, obj, evt): |
188 """ |
189 """ |
189 Public method to handle event for other objects. |
190 Public method to handle event for other objects. |
190 |
191 |
191 @param obj reference to the object (QObject) |
192 @param obj reference to the object (QObject) |
192 @param evt reference to the event (QEvent) |
193 @param evt reference to the event (QEvent) |
193 @return flag indicating that the event should be filtered out (boolean) |
194 @return flag indicating that the event should be filtered out (boolean) |
194 """ |
195 """ |
195 if ( |
196 if obj == self.__grabberWidget and evt.type() == QEvent.Type.MouseButtonPress: |
196 obj == self.__grabberWidget and |
|
197 evt.type() == QEvent.Type.MouseButtonPress |
|
198 ): |
|
199 if QWidget.mouseGrabber() != self.__grabberWidget: |
197 if QWidget.mouseGrabber() != self.__grabberWidget: |
200 return False |
198 return False |
201 if evt.button() == Qt.MouseButton.LeftButton: |
199 if evt.button() == Qt.MouseButton.LeftButton: |
202 self.__performGrab(self.__mode) |
200 self.__performGrab(self.__mode) |
203 |
201 |
204 return False |
202 return False |