Snapshot/SnapshotRegionGrabber.py

changeset 1772
f325dfdc8f6b
parent 1770
c17e67e69ef5
child 1778
31e70a6f8e7f
--- a/Snapshot/SnapshotRegionGrabber.py	Sun Apr 08 12:45:44 2012 +0200
+++ b/Snapshot/SnapshotRegionGrabber.py	Mon Apr 09 17:02:31 2012 +0200
@@ -4,12 +4,12 @@
 #
 
 """
-Module implementing the snapshot region grabber widget.
+Module implementing a grabber widget for a rectangular snapshot region.
 """
 
 from PyQt4.QtCore import pyqtSignal, Qt, QRect, QPoint, QTimer
 from PyQt4.QtGui import QWidget, QPixmap, QColor, QRegion, QApplication, QPainter, \
-    QPalette, QToolTip
+    QPalette, QToolTip, QPaintEngine, QPen, QBrush
 
 
 def drawRect(painter, rect, outline, fill=QColor()):
@@ -38,7 +38,7 @@
 
 class SnapshotRegionGrabber(QWidget):
     """
-    Class implementing the snapshot region grabber widget.
+    Class implementing a grabber widget for a rectangular snapshot region.
     
     @signal grabbed(QPixmap) emitted after the region was grabbed
     """
@@ -47,21 +47,22 @@
     StrokeMask = 0
     FillMask = 1
     
-    ModeFullscreen = 0
-    ModeRectangle = 1
+    Rectangle = 0
+    Ellipse = 1
     
-    def __init__(self, mode, delay):
+    def __init__(self, mode=Rectangle):
         """
         Constructor
         
-        @param mode snapshot mode (SnapshotRegionGrabber.ModeFullscreen,
-            SnapshotRegionGrabber.ModeRectangle)
-        @param delay delay in seconds before taking the snapshot (int)
+        @param mode region grabber mode (SnapshotRegionGrabber.Rectangle or
+            SnapshotRegionGrabber.Ellipse)
         """
         super().__init__(None,
             Qt.X11BypassWindowManagerHint | Qt.WindowStaysOnTopHint | 
             Qt.FramelessWindowHint | Qt.Tool)
         
+        assert mode in [SnapshotRegionGrabber.Rectangle,
+                        SnapshotRegionGrabber.Ellipse]
         self.__mode = mode
         
         self.__selection = QRect()
@@ -98,27 +99,20 @@
         
         self.setMouseTracking(True)
         
-        if delay == 0:
-            delay = 200
-        else:
-            delay = delay * 1000
-        QTimer.singleShot(delay, self.__initialize)
+        QTimer.singleShot(200, self.__initialize)
     
     def __initialize(self):
         """
         Private slot to initialize the rest of the widget.
         """
         self.__pixmap = QPixmap.grabWindow(QApplication.desktop().winId())
-        if self.__mode == SnapshotRegionGrabber.ModeFullscreen:
-            self.grabbed.emit(self.__pixmap.copy())
-        else:
-            self.resize(self.__pixmap.size())
-            self.move(0, 0)
-            self.setCursor(Qt.CrossCursor)
-            self.show()
+        self.resize(self.__pixmap.size())
+        self.move(0, 0)
+        self.setCursor(Qt.CrossCursor)
+        self.show()
 
-            self.grabMouse()
-            self.grabKeyboard()
+        self.grabMouse()
+        self.grabKeyboard()
     
     def paintEvent(self, evt):
         """
@@ -144,12 +138,16 @@
         r = QRect(self.__selection)
         if not self.__selection.isNull():
             grey = QRegion(self.rect())
-            grey = grey.subtracted(QRegion(r))
+            if self.__mode == SnapshotRegionGrabber.Ellipse:
+                reg = QRegion(r, QRegion.Ellipse)
+            else:
+                reg = QRegion(r)
+            grey = grey.subtracted(reg)
             painter.setClipRegion(grey)
             painter.setPen(Qt.NoPen)
             painter.setBrush(overlayColor)
             painter.drawRect(self.rect())
-            painter.setClipRegion(QRegion(self.rect()))
+            painter.setClipRect(self.rect())
             drawRect(painter, r, handleColor)
         
         if self.__showHelp:
@@ -168,7 +166,7 @@
         # The grabbed region is everything which is covered by the drawn
         # rectangles (border included). This means that there is no 0px
         # selection, since a 0px wide rectangle will always be drawn as a line.
-        txt = "{0}, {1} ({2}x{3})".format(
+        txt = "{0:n}, {1:n} ({2:n} x {3:n})".format(
             self.__selection.x(), self.__selection.y(),
             self.__selection.width(), self.__selection.height())
         textRect = painter.boundingRect(self.rect(), Qt.AlignLeft, txt)
@@ -451,7 +449,38 @@
         """
         Private method to grab the selected rectangle (i.e. do the snapshot).
         """
-        r = QRect(self.__selection)
-        if not r.isNull() and r.isValid():
-            self.__grabbing = True
-            self.grabbed.emit(self.__pixmap.copy(r))
+        if self.__mode == SnapshotRegionGrabber.Ellipse:
+            ell = QRegion(self.__selection, QRegion.Ellipse)
+            if not ell.isEmpty():
+                self.__grabbing = True
+                
+                xOffset = self.__pixmap.rect().x() - ell.boundingRect().x()
+                yOffset = self.__pixmap.rect().y() - ell.boundingRect().y()
+                translatedEll = ell.translated(xOffset, yOffset)
+                
+                pixmap2 = QPixmap(ell.boundingRect().size())
+                pixmap2.fill(Qt.transparent)
+                
+                pt = QPainter()
+                pt.begin(pixmap2)
+                if pt.paintEngine().hasFeature(QPaintEngine.PorterDuff):
+                    pt.setRenderHints(QPainter.Antialiasing | \
+                        QPainter.HighQualityAntialiasing | QPainter.SmoothPixmapTransform,
+                        True)
+                    pt.setBrush(Qt.black)
+                    pt.setPen(QPen(QBrush(Qt.black), 0.5))
+                    pt.drawEllipse(translatedEll.boundingRect())
+                    pt.setCompositionMode(QPainter.CompositionMode_SourceIn)
+                else:
+                    pt.setClipRegion(translatedEll)
+                    pt.setCompositionMode(QPainter.CompositionMode_Source)
+                
+                pt.drawPixmap(pixmap2.rect(), self.__pixmap, ell.boundingRect())
+                pt.end()
+                
+                self.grabbed.emit(pixmap2)
+        else:
+            r = QRect(self.__selection)
+            if not r.isNull() and r.isValid():
+                self.__grabbing = True
+                self.grabbed.emit(self.__pixmap.copy(r))

eric ide

mercurial