14 # |
14 # |
15 |
15 |
16 import os |
16 import os |
17 |
17 |
18 from PyQt5.QtCore import pyqtSlot, QFile, QFileInfo, QTimer, QPoint, \ |
18 from PyQt5.QtCore import pyqtSlot, QFile, QFileInfo, QTimer, QPoint, \ |
19 QMimeData, Qt, QEvent, QRegExp, QLocale, PYQT_VERSION_STR |
19 QMimeData, Qt, QRegExp, QLocale, PYQT_VERSION_STR |
20 from PyQt5.QtGui import QImageWriter, QPixmap, QCursor, QDrag, QKeySequence |
20 from PyQt5.QtGui import QImageWriter, QPixmap, QDrag, QKeySequence |
21 from PyQt5.QtWidgets import QWidget, QApplication, QShortcut |
21 from PyQt5.QtWidgets import QWidget, QApplication, QShortcut |
22 |
22 |
23 from E5Gui import E5FileDialog, E5MessageBox |
23 from E5Gui import E5FileDialog, E5MessageBox |
24 |
24 |
25 from .Ui_SnapWidget import Ui_SnapWidget |
25 from .Ui_SnapWidget import Ui_SnapWidget |
26 |
26 |
27 import UI.PixmapCache |
27 import UI.PixmapCache |
28 import Preferences |
28 import Preferences |
29 import Globals |
29 import Globals |
30 from Globals import qVersionTuple |
30 |
|
31 from .SnapshotModes import SnapshotModes |
31 |
32 |
32 |
33 |
33 class SnapWidget(QWidget, Ui_SnapWidget): |
34 class SnapWidget(QWidget, Ui_SnapWidget): |
34 """ |
35 """ |
35 Class implementing the snapshot widget. |
36 Class implementing the snapshot widget. |
36 """ |
37 """ |
37 ModeFullscreen = 0 |
|
38 ModeScreen = 1 |
|
39 ModeRectangle = 2 |
|
40 ModeFreehand = 3 |
|
41 ModeEllipse = 4 |
|
42 |
|
43 def __init__(self, parent=None): |
38 def __init__(self, parent=None): |
44 """ |
39 """ |
45 Constructor |
40 Constructor |
46 |
41 |
47 @param parent reference to the parent widget (QWidget) |
42 @param parent reference to the parent widget (QWidget) |
53 self.takeButton.setIcon(UI.PixmapCache.getIcon("cameraPhoto.png")) |
48 self.takeButton.setIcon(UI.PixmapCache.getIcon("cameraPhoto.png")) |
54 self.copyButton.setIcon(UI.PixmapCache.getIcon("editCopy.png")) |
49 self.copyButton.setIcon(UI.PixmapCache.getIcon("editCopy.png")) |
55 self.copyPreviewButton.setIcon(UI.PixmapCache.getIcon("editCopy.png")) |
50 self.copyPreviewButton.setIcon(UI.PixmapCache.getIcon("editCopy.png")) |
56 self.setWindowIcon(UI.PixmapCache.getIcon("ericSnap.png")) |
51 self.setWindowIcon(UI.PixmapCache.getIcon("ericSnap.png")) |
57 |
52 |
58 self.modeCombo.addItem(self.tr("Fullscreen"), |
53 if Globals.isWaylandSession(): |
59 SnapWidget.ModeFullscreen) |
54 from .SnapshotWaylandGrabber import SnapshotWaylandGrabber |
60 if qVersionTuple() >= (5, 10, 0): |
55 self.__grabber = SnapshotWaylandGrabber(self) |
61 if len(QApplication.screens()) > 1: |
|
62 self.modeCombo.addItem(self.tr("Select Screen"), |
|
63 SnapWidget.ModeScreen) |
|
64 else: |
56 else: |
65 if QApplication.desktop().screenCount() > 1: |
57 from .SnapshotDefaultGrabber import SnapshotDefaultGrabber |
66 self.modeCombo.addItem(self.tr("Select Screen"), |
58 self.__grabber = SnapshotDefaultGrabber(self) |
67 SnapWidget.ModeScreen) |
59 self.decorationsCheckBox.hide() |
68 self.modeCombo.addItem(self.tr("Rectangular Selection"), |
60 self.mouseCursorCheckBox.hide() |
69 SnapWidget.ModeRectangle) |
61 self.__grabber.grabbed.connect(self.__captured) |
70 self.modeCombo.addItem(self.tr("Elliptical Selection"), |
62 supportedModes = self.__grabber.supportedModes() |
71 SnapWidget.ModeEllipse) |
63 |
72 self.modeCombo.addItem(self.tr("Freehand Selection"), |
64 if SnapshotModes.Fullscreen in supportedModes: |
73 SnapWidget.ModeFreehand) |
65 self.modeCombo.addItem(self.tr("Fullscreen"), |
74 self.__mode = int(Preferences.Prefs.settings.value("Snapshot/Mode", 0)) |
66 SnapshotModes.Fullscreen) |
75 index = self.modeCombo.findData(self.__mode) |
67 if SnapshotModes.SelectedScreen in supportedModes: |
|
68 if Globals.qVersionTuple() >= (5, 10, 0): |
|
69 if len(QApplication.screens()) > 1: |
|
70 self.modeCombo.addItem(self.tr("Select Screen"), |
|
71 SnapshotModes.SelectedScreen) |
|
72 else: |
|
73 if QApplication.desktop().screenCount() > 1: |
|
74 self.modeCombo.addItem(self.tr("Select Screen"), |
|
75 SnapshotModes.SelectedScreen) |
|
76 if SnapshotModes.SelectedWindow in supportedModes: |
|
77 self.modeCombo.addItem(self.tr("Select Window"), |
|
78 SnapshotModes.SelectedWindow) |
|
79 if SnapshotModes.Rectangle in supportedModes: |
|
80 self.modeCombo.addItem(self.tr("Rectangular Selection"), |
|
81 SnapshotModes.Rectangle) |
|
82 if SnapshotModes.Ellipse in supportedModes: |
|
83 self.modeCombo.addItem(self.tr("Elliptical Selection"), |
|
84 SnapshotModes.Ellipse) |
|
85 if SnapshotModes.Freehand in supportedModes: |
|
86 self.modeCombo.addItem(self.tr("Freehand Selection"), |
|
87 SnapshotModes.Freehand) |
|
88 mode = int(Preferences.Prefs.settings.value("Snapshot/Mode", 0)) |
|
89 index = self.modeCombo.findData(SnapshotModes(mode)) |
76 if index == -1: |
90 if index == -1: |
77 index = 0 |
91 index = 0 |
78 self.modeCombo.setCurrentIndex(index) |
92 self.modeCombo.setCurrentIndex(index) |
79 |
93 |
80 self.__delay = int( |
94 delay = int(Preferences.Prefs.settings.value("Snapshot/Delay", 0)) |
81 Preferences.Prefs.settings.value("Snapshot/Delay", 0)) |
95 self.delaySpin.setValue(delay) |
82 self.delaySpin.setValue(self.__delay) |
|
83 |
96 |
84 if PYQT_VERSION_STR >= "5.0.0": |
97 if PYQT_VERSION_STR >= "5.0.0": |
85 from PyQt5.QtCore import QStandardPaths |
98 from PyQt5.QtCore import QStandardPaths |
86 picturesLocation = QStandardPaths.writableLocation( |
99 picturesLocation = QStandardPaths.writableLocation( |
87 QStandardPaths.PicturesLocation) |
100 QStandardPaths.PicturesLocation) |
92 self.__filename = Preferences.Prefs.settings.value( |
105 self.__filename = Preferences.Prefs.settings.value( |
93 "Snapshot/Filename", |
106 "Snapshot/Filename", |
94 os.path.join(picturesLocation, |
107 os.path.join(picturesLocation, |
95 self.tr("snapshot") + "1.png")) |
108 self.tr("snapshot") + "1.png")) |
96 |
109 |
97 self.__grabber = None |
|
98 self.__snapshot = QPixmap() |
110 self.__snapshot = QPixmap() |
99 self.__savedPosition = QPoint() |
111 self.__savedPosition = QPoint() |
100 self.__modified = False |
112 self.__modified = False |
101 self.__locale = QLocale() |
113 self.__locale = QLocale() |
102 |
114 |
103 self.__grabberWidget = QWidget(None, Qt.X11BypassWindowManagerHint) |
|
104 self.__grabberWidget.move(-10000, -10000) |
|
105 self.__grabberWidget.installEventFilter(self) |
|
106 |
|
107 self.__initFileFilters() |
115 self.__initFileFilters() |
108 |
|
109 self.__initShortcuts() |
116 self.__initShortcuts() |
110 |
117 |
111 self.preview.startDrag.connect(self.__dragSnapshot) |
118 self.preview.startDrag.connect(self.__dragSnapshot) |
112 |
119 |
113 from .SnapshotTimer import SnapshotTimer |
|
114 self.__grabTimer = SnapshotTimer() |
|
115 self.__grabTimer.timeout.connect(self.__grabTimerTimeout) |
|
116 self.__updateTimer = QTimer() |
120 self.__updateTimer = QTimer() |
117 self.__updateTimer.setSingleShot(True) |
121 self.__updateTimer.setSingleShot(True) |
118 self.__updateTimer.timeout.connect(self.__updatePreview) |
122 self.__updateTimer.timeout.connect(self.__updatePreview) |
119 |
123 |
120 self.__updateCaption() |
124 self.__updateCaption() |
299 @pyqtSlot() |
303 @pyqtSlot() |
300 def on_takeButton_clicked(self): |
304 def on_takeButton_clicked(self): |
301 """ |
305 """ |
302 Private slot to take a snapshot. |
306 Private slot to take a snapshot. |
303 """ |
307 """ |
304 self.__mode = self.modeCombo.itemData(self.modeCombo.currentIndex()) |
|
305 self.__delay = self.delaySpin.value() |
|
306 |
|
307 self.__savedPosition = self.pos() |
308 self.__savedPosition = self.pos() |
308 self.hide() |
309 self.hide() |
309 |
310 |
310 if self.__delay: |
311 self.__grabber.grab( |
311 self.__grabTimer.start(self.__delay) |
312 self.modeCombo.itemData(self.modeCombo.currentIndex()), |
312 else: |
313 self.delaySpin.value(), |
313 QTimer.singleShot(200, self.__startUndelayedGrab) |
314 self.mouseCursorCheckBox.isChecked(), |
314 |
315 self.decorationsCheckBox.isChecked(), |
315 def __grabTimerTimeout(self): |
316 ) |
316 """ |
|
317 Private slot to perform a delayed grab operation. |
|
318 """ |
|
319 if self.__mode == SnapWidget.ModeRectangle: |
|
320 self.__grabRectangle() |
|
321 elif self.__mode == SnapWidget.ModeEllipse: |
|
322 self.__grabEllipse() |
|
323 elif self.__mode == SnapWidget.ModeFreehand: |
|
324 self.__grabFreehand() |
|
325 else: |
|
326 self.__performGrab() |
|
327 |
|
328 def __startUndelayedGrab(self): |
|
329 """ |
|
330 Private slot to perform an undelayed grab operation. |
|
331 """ |
|
332 if self.__mode == SnapWidget.ModeRectangle: |
|
333 self.__grabRectangle() |
|
334 elif self.__mode == SnapWidget.ModeEllipse: |
|
335 self.__grabEllipse() |
|
336 elif self.__mode == SnapWidget.ModeFreehand: |
|
337 self.__grabFreehand() |
|
338 else: |
|
339 if Globals.isMacPlatform(): |
|
340 self.__performGrab() |
|
341 else: |
|
342 self.__grabberWidget.show() |
|
343 self.__grabberWidget.grabMouse(Qt.CrossCursor) |
|
344 |
|
345 def __grabRectangle(self): |
|
346 """ |
|
347 Private method to grab a rectangular screen region. |
|
348 """ |
|
349 from .SnapshotRegionGrabber import SnapshotRegionGrabber |
|
350 self.__grabber = SnapshotRegionGrabber( |
|
351 mode=SnapshotRegionGrabber.Rectangle) |
|
352 self.__grabber.grabbed.connect(self.__captured) |
|
353 |
|
354 def __grabEllipse(self): |
|
355 """ |
|
356 Private method to grab an elliptical screen region. |
|
357 """ |
|
358 from .SnapshotRegionGrabber import SnapshotRegionGrabber |
|
359 self.__grabber = SnapshotRegionGrabber( |
|
360 mode=SnapshotRegionGrabber.Ellipse) |
|
361 self.__grabber.grabbed.connect(self.__captured) |
|
362 |
|
363 def __grabFreehand(self): |
|
364 """ |
|
365 Private method to grab a non-rectangular screen region. |
|
366 """ |
|
367 from .SnapshotFreehandGrabber import SnapshotFreehandGrabber |
|
368 self.__grabber = SnapshotFreehandGrabber() |
|
369 self.__grabber.grabbed.connect(self.__captured) |
|
370 |
|
371 def __performGrab(self): |
|
372 """ |
|
373 Private method to perform a screen grab other than a selected region. |
|
374 """ |
|
375 self.__grabberWidget.releaseMouse() |
|
376 self.__grabberWidget.hide() |
|
377 self.__grabTimer.stop() |
|
378 |
|
379 if self.__mode == SnapWidget.ModeFullscreen: |
|
380 desktop = QApplication.desktop() |
|
381 if qVersionTuple() >= (5, 0, 0): |
|
382 self.__snapshot = QApplication.screens()[0].grabWindow( |
|
383 desktop.winId(), desktop.x(), desktop.y(), |
|
384 desktop.width(), desktop.height()) |
|
385 else: |
|
386 self.__snapshot = QPixmap.grabWindow( |
|
387 desktop.winId(), desktop.x(), desktop.y(), |
|
388 desktop.width(), desktop.height()) |
|
389 elif self.__mode == SnapWidget.ModeScreen: |
|
390 desktop = QApplication.desktop() |
|
391 if qVersionTuple() >= (5, 10, 0): |
|
392 screen = QApplication.screenAt(QCursor.pos()) |
|
393 geom = screen.geometry() |
|
394 else: |
|
395 screenId = desktop.screenNumber(QCursor.pos()) |
|
396 geom = desktop.screenGeometry(screenId) |
|
397 x = geom.x() |
|
398 y = geom.y() |
|
399 if qVersionTuple() >= (5, 0, 0): |
|
400 self.__snapshot = QApplication.screens()[0].grabWindow( |
|
401 desktop.winId(), x, y, geom.width(), geom.height()) |
|
402 else: |
|
403 self.__snapshot = QPixmap.grabWindow( |
|
404 desktop.winId(), x, y, geom.width(), geom.height()) |
|
405 else: |
|
406 self.__snapshot = QPixmap() |
|
407 |
|
408 self.__redisplay() |
|
409 self.__modified = True |
|
410 self.__updateCaption() |
|
411 |
317 |
412 def __redisplay(self): |
318 def __redisplay(self): |
413 """ |
319 """ |
414 Private method to redisplay the window. |
320 Private method to redisplay the window. |
415 """ |
321 """ |
483 mimeData = QMimeData() |
385 mimeData = QMimeData() |
484 mimeData.setImageData(self.__snapshot) |
386 mimeData.setImageData(self.__snapshot) |
485 drag.setMimeData(mimeData) |
387 drag.setMimeData(mimeData) |
486 drag.setPixmap(self.preview.pixmap()) |
388 drag.setPixmap(self.preview.pixmap()) |
487 drag.exec_(Qt.CopyAction) |
389 drag.exec_(Qt.CopyAction) |
488 |
|
489 def eventFilter(self, obj, evt): |
|
490 """ |
|
491 Public method to handle event for other objects. |
|
492 |
|
493 @param obj reference to the object (QObject) |
|
494 @param evt reference to the event (QEvent) |
|
495 @return flag indicating that the event should be filtered out (boolean) |
|
496 """ |
|
497 if obj == self.__grabberWidget and \ |
|
498 evt.type() == QEvent.MouseButtonPress: |
|
499 if QWidget.mouseGrabber() != self.__grabberWidget: |
|
500 return False |
|
501 if evt.button() == Qt.LeftButton: |
|
502 self.__performGrab() |
|
503 |
|
504 return False |
|
505 |
390 |
506 def closeEvent(self, evt): |
391 def closeEvent(self, evt): |
507 """ |
392 """ |
508 Protected method handling the close event. |
393 Protected method handling the close event. |
509 |
394 |
525 elif res == E5MessageBox.Save: |
410 elif res == E5MessageBox.Save: |
526 self.on_saveButton_clicked() |
411 self.on_saveButton_clicked() |
527 |
412 |
528 Preferences.Prefs.settings.setValue( |
413 Preferences.Prefs.settings.setValue( |
529 "Snapshot/Delay", self.delaySpin.value()) |
414 "Snapshot/Delay", self.delaySpin.value()) |
530 Preferences.Prefs.settings.setValue( |
415 modeData = self.modeCombo.itemData(self.modeCombo.currentIndex()) |
531 "Snapshot/Mode", |
416 if modeData is not None: |
532 self.modeCombo.itemData(self.modeCombo.currentIndex())) |
417 Preferences.Prefs.settings.setValue( |
|
418 "Snapshot/Mode", |
|
419 modeData.value) |
533 Preferences.Prefs.settings.setValue( |
420 Preferences.Prefs.settings.setValue( |
534 "Snapshot/Filename", self.__filename) |
421 "Snapshot/Filename", self.__filename) |
535 Preferences.Prefs.settings.sync() |
422 Preferences.Prefs.settings.sync() |
536 |
423 |
537 def __updateCaption(self): |
424 def __updateCaption(self): |
541 self.setWindowTitle("{0}[*] - {1}".format( |
428 self.setWindowTitle("{0}[*] - {1}".format( |
542 os.path.basename(self.__filename), |
429 os.path.basename(self.__filename), |
543 self.tr("eric6 Snapshot"))) |
430 self.tr("eric6 Snapshot"))) |
544 self.setWindowModified(self.__modified) |
431 self.setWindowModified(self.__modified) |
545 self.pathNameEdit.setText(os.path.dirname(self.__filename)) |
432 self.pathNameEdit.setText(os.path.dirname(self.__filename)) |
|
433 |
|
434 @pyqtSlot(int) |
|
435 def on_modeCombo_currentIndexChanged(self, index): |
|
436 """ |
|
437 Private slot handling the selection of a screenshot mode. |
|
438 |
|
439 @param index index of the selection |
|
440 @type int |
|
441 """ |
|
442 isWindowMode = False |
|
443 if index >= 0: |
|
444 mode = self.modeCombo.itemData(index) |
|
445 isWindowMode = (mode == SnapshotModes.SelectedWindow) |
|
446 |
|
447 self.decorationsCheckBox.setEnabled(isWindowMode) |
|
448 self.decorationsCheckBox.setChecked(isWindowMode) |