6 """ |
6 """ |
7 Module implementing a grabber widget for a freehand snapshot region. |
7 Module implementing a grabber widget for a freehand snapshot region. |
8 """ |
8 """ |
9 |
9 |
10 from PyQt4.QtCore import pyqtSignal, Qt, QRect, QPoint, QTimer, qVersion |
10 from PyQt4.QtCore import pyqtSignal, Qt, QRect, QPoint, QTimer, qVersion |
11 from PyQt4.QtGui import QWidget, QPixmap, QColor, QRegion, QApplication, QPainter, \ |
11 from PyQt4.QtGui import QWidget, QPixmap, QColor, QRegion, QApplication, \ |
12 QPalette, QToolTip, QPolygon, QPen, QBrush, QPaintEngine |
12 QPainter, QPalette, QToolTip, QPolygon, QPen, QBrush, QPaintEngine |
13 |
13 |
14 |
14 |
15 def drawPolygon(painter, polygon, outline, fill=QColor()): |
15 def drawPolygon(painter, polygon, outline, fill=QColor()): |
16 """ |
16 """ |
17 Module function to draw a polygon with the given parameters. |
17 Module function to draw a polygon with the given parameters. |
61 self.__dragStartPoint = QPoint() |
61 self.__dragStartPoint = QPoint() |
62 self.__selectionBeforeDrag = QPolygon() |
62 self.__selectionBeforeDrag = QPolygon() |
63 |
63 |
64 self.__helpTextRect = QRect() |
64 self.__helpTextRect = QRect() |
65 self.__helpText = self.trUtf8( |
65 self.__helpText = self.trUtf8( |
66 "Select a region using the mouse. To take the snapshot, press the Enter key" |
66 "Select a region using the mouse. To take the snapshot," |
67 " or double click. Press Esc to quit.") |
67 " press the Enter key or double click. Press Esc to quit.") |
68 |
68 |
69 self.__pixmap = QPixmap() |
69 self.__pixmap = QPixmap() |
70 self.__pBefore = QPoint() |
70 self.__pBefore = QPoint() |
71 |
71 |
72 self.setMouseTracking(True) |
72 self.setMouseTracking(True) |
117 painter.setFont(font) |
117 painter.setFont(font) |
118 |
118 |
119 pol = QPolygon(self.__selection) |
119 pol = QPolygon(self.__selection) |
120 if not self.__selection.boundingRect().isNull(): |
120 if not self.__selection.boundingRect().isNull(): |
121 # Draw outline around selection. |
121 # Draw outline around selection. |
122 # Important: the 1px-wide outline is *also* part of the captured free-region |
122 # Important: the 1px-wide outline is *also* part of the |
|
123 # captured free-region |
123 pen = QPen(handleColor, 1, Qt.SolidLine, Qt.SquareCap, Qt.BevelJoin) |
124 pen = QPen(handleColor, 1, Qt.SolidLine, Qt.SquareCap, Qt.BevelJoin) |
124 painter.setPen(pen) |
125 painter.setPen(pen) |
125 painter.drawPolygon(pol) |
126 painter.drawPolygon(pol) |
126 |
127 |
127 # Draw the grey area around the selection. |
128 # Draw the grey area around the selection. |
135 drawPolygon(painter, pol, handleColor) |
136 drawPolygon(painter, pol, handleColor) |
136 |
137 |
137 if self.__showHelp: |
138 if self.__showHelp: |
138 painter.setPen(textColor) |
139 painter.setPen(textColor) |
139 painter.setBrush(textBackgroundColor) |
140 painter.setBrush(textBackgroundColor) |
140 self.__helpTextRect = painter.boundingRect(self.rect().adjusted(2, 2, -2, -2), |
141 self.__helpTextRect = painter.boundingRect( |
|
142 self.rect().adjusted(2, 2, -2, -2), |
141 Qt.TextWordWrap, self.__helpText).translated( |
143 Qt.TextWordWrap, self.__helpText).translated( |
142 -self.__desktop.x(), -self.__desktop.y()) |
144 -self.__desktop.x(), -self.__desktop.y()) |
143 self.__helpTextRect.adjust(-2, -2, 4, 2) |
145 self.__helpTextRect.adjust(-2, -2, 4, 2) |
144 drawPolygon(painter, self.__helpTextRect, textColor, textBackgroundColor) |
146 drawPolygon(painter, self.__helpTextRect, textColor, |
|
147 textBackgroundColor) |
145 painter.drawText(self.__helpTextRect.adjusted(3, 3, -3, -3), |
148 painter.drawText(self.__helpTextRect.adjusted(3, 3, -3, -3), |
146 Qt.TextWordWrap, self.__helpText) |
149 Qt.TextWordWrap, self.__helpText) |
147 |
150 |
148 if self.__selection.isEmpty(): |
151 if self.__selection.isEmpty(): |
149 return |
152 return |
150 |
153 |
151 # The grabbed region is everything which is covered by the drawn |
154 # The grabbed region is everything which is covered by the drawn |
152 # rectangles (border included). This means that there is no 0px |
155 # rectangles (border included). This means that there is no 0px |
153 # selection, since a 0px wide rectangle will always be drawn as a line. |
156 # selection, since a 0px wide rectangle will always be drawn as a line. |
154 boundingRect = self.__selection.boundingRect() |
157 boundingRect = self.__selection.boundingRect() |
155 txt = "{0:n}, {1:n} ({2:n} x {3:n})".format(boundingRect.x(), boundingRect.y(), |
158 txt = "{0:n}, {1:n} ({2:n} x {3:n})".format( |
|
159 boundingRect.x(), boundingRect.y(), |
156 boundingRect.width(), boundingRect.height()) |
160 boundingRect.width(), boundingRect.height()) |
157 textRect = painter.boundingRect(self.rect(), Qt.AlignLeft, txt) |
161 textRect = painter.boundingRect(self.rect(), Qt.AlignLeft, txt) |
158 boundingRect = textRect.adjusted(-4, 0, 0, 0) |
162 boundingRect = textRect.adjusted(-4, 0, 0, 0) |
159 |
163 |
160 polBoundingRect = pol.boundingRect() |
164 polBoundingRect = pol.boundingRect() |
161 if textRect.width() < polBoundingRect.width() - 2 * self.__handleSize and \ |
165 if (textRect.width() < |
162 textRect.height() < polBoundingRect.height() - 2 * self.__handleSize and \ |
166 polBoundingRect.width() - 2 * self.__handleSize) and \ |
|
167 (textRect.height() < |
|
168 polBoundingRect.height() - 2 * self.__handleSize) and \ |
163 polBoundingRect.width() > 100 and \ |
169 polBoundingRect.width() > 100 and \ |
164 polBoundingRect.height() > 100: |
170 polBoundingRect.height() > 100: |
165 # center, unsuitable for small selections |
171 # center, unsuitable for small selections |
166 boundingRect.moveCenter(polBoundingRect.center()) |
172 boundingRect.moveCenter(polBoundingRect.center()) |
167 textRect.moveCenter(polBoundingRect.center()) |
173 textRect.moveCenter(polBoundingRect.center()) |
176 # left, top aligned |
182 # left, top aligned |
177 boundingRect.moveTopRight( |
183 boundingRect.moveTopRight( |
178 QPoint(polBoundingRect.x() - 3, polBoundingRect.y())) |
184 QPoint(polBoundingRect.x() - 3, polBoundingRect.y())) |
179 textRect.moveTopRight( |
185 textRect.moveTopRight( |
180 QPoint(polBoundingRect.x() - 5, polBoundingRect.y())) |
186 QPoint(polBoundingRect.x() - 5, polBoundingRect.y())) |
181 elif polBoundingRect.bottom() + 3 + textRect.height() < self.rect().bottom() and \ |
187 elif (polBoundingRect.bottom() + 3 + textRect.height() < |
|
188 self.rect().bottom()) and \ |
182 polBoundingRect.right() > textRect.width(): |
189 polBoundingRect.right() > textRect.width(): |
183 # at bottom, right aligned |
190 # at bottom, right aligned |
184 boundingRect.moveTopRight( |
191 boundingRect.moveTopRight( |
185 QPoint(polBoundingRect.right(), polBoundingRect.bottom() + 3)) |
192 QPoint(polBoundingRect.right(), polBoundingRect.bottom() + 3)) |
186 textRect.moveTopRight( |
193 textRect.moveTopRight( |
187 QPoint(polBoundingRect.right() - 2, polBoundingRect.bottom() + 3)) |
194 QPoint(polBoundingRect.right() - 2, |
188 elif polBoundingRect.right() + textRect.width() + 3 < self.rect().width(): |
195 polBoundingRect.bottom() + 3)) |
|
196 elif polBoundingRect.right() + textRect.width() + 3 < \ |
|
197 self.rect().width(): |
189 # right, bottom aligned |
198 # right, bottom aligned |
190 boundingRect.moveBottomLeft( |
199 boundingRect.moveBottomLeft( |
191 QPoint(polBoundingRect.right() + 3, polBoundingRect.bottom())) |
200 QPoint(polBoundingRect.right() + 3, polBoundingRect.bottom())) |
192 textRect.moveBottomLeft( |
201 textRect.moveBottomLeft( |
193 QPoint(polBoundingRect.right() + 5, polBoundingRect.bottom())) |
202 QPoint(polBoundingRect.right() + 5, polBoundingRect.bottom())) |
194 |
203 |
195 # If the above didn't catch it, you are running on a very tiny screen... |
204 # If the above didn't catch it, you are running on a very |
|
205 # tiny screen... |
196 drawPolygon(painter, boundingRect, textColor, textBackgroundColor) |
206 drawPolygon(painter, boundingRect, textColor, textBackgroundColor) |
197 painter.drawText(textRect, Qt.AlignHCenter, txt) |
207 painter.drawText(textRect, Qt.AlignHCenter, txt) |
198 |
208 |
199 if (polBoundingRect.height() > self.__handleSize * 2 and \ |
209 if (polBoundingRect.height() > self.__handleSize * 2 and \ |
200 polBoundingRect.width() > self.__handleSize * 2) or \ |
210 polBoundingRect.width() > self.__handleSize * 2) or \ |
307 pixmap2.fill(Qt.transparent) |
318 pixmap2.fill(Qt.transparent) |
308 |
319 |
309 pt = QPainter() |
320 pt = QPainter() |
310 pt.begin(pixmap2) |
321 pt.begin(pixmap2) |
311 if pt.paintEngine().hasFeature(QPaintEngine.PorterDuff): |
322 if pt.paintEngine().hasFeature(QPaintEngine.PorterDuff): |
312 pt.setRenderHints(QPainter.Antialiasing | \ |
323 pt.setRenderHints( |
313 QPainter.HighQualityAntialiasing | QPainter.SmoothPixmapTransform, |
324 QPainter.Antialiasing | \ |
|
325 QPainter.HighQualityAntialiasing | \ |
|
326 QPainter.SmoothPixmapTransform, |
314 True) |
327 True) |
315 pt.setBrush(Qt.black) |
328 pt.setBrush(Qt.black) |
316 pt.setPen(QPen(QBrush(Qt.black), 0.5)) |
329 pt.setPen(QPen(QBrush(Qt.black), 0.5)) |
317 pt.drawPolygon(translatedPol) |
330 pt.drawPolygon(translatedPol) |
318 pt.setCompositionMode(QPainter.CompositionMode_SourceIn) |
331 pt.setCompositionMode(QPainter.CompositionMode_SourceIn) |