6 """ |
6 """ |
7 Module implementing a grabber widget for a rectangular snapshot region. |
7 Module implementing a grabber widget for a rectangular 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, QPaintEngine, QPen, QBrush |
12 QPainter, QPalette, QToolTip, QPaintEngine, QPen, QBrush |
13 |
13 |
14 |
14 |
15 def drawRect(painter, rect, outline, fill=QColor()): |
15 def drawRect(painter, rect, outline, fill=QColor()): |
16 """ |
16 """ |
17 Module function to draw a rectangle with the given parameters. |
17 Module function to draw a rectangle with the given parameters. |
90 self.__handles = [self.__TLHandle, self.__TRHandle, self.__BLHandle, |
90 self.__handles = [self.__TLHandle, self.__TRHandle, self.__BLHandle, |
91 self.__BRHandle, self.__LHandle, self.__THandle, |
91 self.__BRHandle, self.__LHandle, self.__THandle, |
92 self.__RHandle, self.__BHandle] |
92 self.__RHandle, self.__BHandle] |
93 self.__helpTextRect = QRect() |
93 self.__helpTextRect = QRect() |
94 self.__helpText = self.trUtf8( |
94 self.__helpText = self.trUtf8( |
95 "Select a region using the mouse. To take the snapshot, press the Enter key" |
95 "Select a region using the mouse. To take the snapshot, press" |
96 " or double click. Press Esc to quit.") |
96 " the Enter key or double click. Press Esc to quit.") |
97 |
97 |
98 self.__pixmap = QPixmap() |
98 self.__pixmap = QPixmap() |
99 |
99 |
100 self.setMouseTracking(True) |
100 self.setMouseTracking(True) |
101 |
101 |
160 drawRect(painter, r, handleColor) |
160 drawRect(painter, r, handleColor) |
161 |
161 |
162 if self.__showHelp: |
162 if self.__showHelp: |
163 painter.setPen(textColor) |
163 painter.setPen(textColor) |
164 painter.setBrush(textBackgroundColor) |
164 painter.setBrush(textBackgroundColor) |
165 self.__helpTextRect = painter.boundingRect(self.rect().adjusted(2, 2, -2, -2), |
165 self.__helpTextRect = painter.boundingRect( |
|
166 self.rect().adjusted(2, 2, -2, -2), |
166 Qt.TextWordWrap, self.__helpText).translated( |
167 Qt.TextWordWrap, self.__helpText).translated( |
167 -self.__desktop.x(), -self.__desktop.y()) |
168 -self.__desktop.x(), -self.__desktop.y()) |
168 self.__helpTextRect.adjust(-2, -2, 4, 2) |
169 self.__helpTextRect.adjust(-2, -2, 4, 2) |
169 drawRect(painter, self.__helpTextRect, textColor, textBackgroundColor) |
170 drawRect(painter, self.__helpTextRect, textColor, |
|
171 textBackgroundColor) |
170 painter.drawText(self.__helpTextRect.adjusted(3, 3, -3, -3), |
172 painter.drawText(self.__helpTextRect.adjusted(3, 3, -3, -3), |
171 Qt.TextWordWrap, self.__helpText) |
173 Qt.TextWordWrap, self.__helpText) |
172 |
174 |
173 if self.__selection.isNull(): |
175 if self.__selection.isNull(): |
174 return |
176 return |
206 elif r.right() + textRect.width() + 3 < self.rect().width(): |
208 elif r.right() + textRect.width() + 3 < self.rect().width(): |
207 # right, bottom aligned |
209 # right, bottom aligned |
208 boundingRect.moveBottomLeft(QPoint(r.right() + 3, r.bottom())) |
210 boundingRect.moveBottomLeft(QPoint(r.right() + 3, r.bottom())) |
209 textRect.moveBottomLeft(QPoint(r.right() + 5, r.bottom())) |
211 textRect.moveBottomLeft(QPoint(r.right() + 5, r.bottom())) |
210 |
212 |
211 # If the above didn't catch it, you are running on a very tiny screen... |
213 # If the above didn't catch it, you are running on a very |
|
214 # tiny screen... |
212 drawRect(painter, boundingRect, textColor, textBackgroundColor) |
215 drawRect(painter, boundingRect, textColor, textBackgroundColor) |
213 painter.drawText(textRect, Qt.AlignHCenter, txt) |
216 painter.drawText(textRect, Qt.AlignHCenter, txt) |
214 |
217 |
215 if (r.height() > self.__handleSize * 2 and \ |
218 if (r.height() > self.__handleSize * 2 and \ |
216 r.width() > self.__handleSize * 2) or \ |
219 r.width() > self.__handleSize * 2) or \ |
217 not self.__mouseDown: |
220 not self.__mouseDown: |
218 self.__updateHandles() |
221 self.__updateHandles() |
219 painter.setPen(Qt.NoPen) |
222 painter.setPen(Qt.NoPen) |
220 painter.setBrush(handleColor) |
223 painter.setBrush(handleColor) |
221 painter.setClipRegion(self.__handleMask(SnapshotRegionGrabber.StrokeMask)) |
224 painter.setClipRegion( |
|
225 self.__handleMask(SnapshotRegionGrabber.StrokeMask)) |
222 painter.drawRect(self.rect()) |
226 painter.drawRect(self.rect()) |
223 handleColor.setAlpha(60) |
227 handleColor.setAlpha(60) |
224 painter.setBrush(handleColor) |
228 painter.setBrush(handleColor) |
225 painter.setClipRegion(self.__handleMask(SnapshotRegionGrabber.FillMask)) |
229 painter.setClipRegion( |
|
230 self.__handleMask(SnapshotRegionGrabber.FillMask)) |
226 painter.drawRect(self.rect()) |
231 painter.drawRect(self.rect()) |
227 |
232 |
228 def resizeEvent(self, evt): |
233 def resizeEvent(self, evt): |
229 """ |
234 """ |
230 Protected method to handle resize events. |
235 Protected method to handle resize events. |
279 if self.__mouseDown: |
284 if self.__mouseDown: |
280 if self.__newSelection: |
285 if self.__newSelection: |
281 p = evt.pos() |
286 p = evt.pos() |
282 r = self.rect() |
287 r = self.rect() |
283 self.__selection = self.__normalizeSelection( |
288 self.__selection = self.__normalizeSelection( |
284 QRect(self.__dragStartPoint, self.__limitPointToRect(p, r))) |
289 QRect(self.__dragStartPoint, |
|
290 self.__limitPointToRect(p, r))) |
285 elif self.__mouseOverHandle is None: |
291 elif self.__mouseOverHandle is None: |
286 # moving the whole selection |
292 # moving the whole selection |
287 r = self.rect().normalized() |
293 r = self.rect().normalized() |
288 s = self.__selectionBeforeDrag.normalized() |
294 s = self.__selectionBeforeDrag.normalized() |
289 p = s.topLeft() + evt.pos() - self.__dragStartPoint |
295 p = s.topLeft() + evt.pos() - self.__dragStartPoint |
290 r.setBottomRight( |
296 r.setBottomRight( |
291 r.bottomRight() - QPoint(s.width(), s.height()) + QPoint(1, 1)) |
297 r.bottomRight() - QPoint(s.width(), |
|
298 s.height()) + QPoint(1, 1)) |
292 if not r.isNull() and r.isValid(): |
299 if not r.isNull() and r.isValid(): |
293 self.__selection.moveTo(self.__limitPointToRect(p, r)) |
300 self.__selection.moveTo(self.__limitPointToRect(p, r)) |
294 else: |
301 else: |
295 # dragging a handle |
302 # dragging a handle |
296 r = QRect(self.__selectionBeforeDrag) |
303 r = QRect(self.__selectionBeforeDrag) |
311 if self.__mouseOverHandle in \ |
318 if self.__mouseOverHandle in \ |
312 [self.__TRHandle, self.__RHandle, self.__BRHandle]: |
319 [self.__TRHandle, self.__RHandle, self.__BRHandle]: |
313 r.setRight(r.right() + offset.x()) |
320 r.setRight(r.right() + offset.x()) |
314 |
321 |
315 r.setTopLeft(self.__limitPointToRect(r.topLeft(), self.rect())) |
322 r.setTopLeft(self.__limitPointToRect(r.topLeft(), self.rect())) |
316 r.setBottomRight(self.__limitPointToRect(r.bottomRight(), self.rect())) |
323 r.setBottomRight( |
|
324 self.__limitPointToRect(r.bottomRight(), self.rect())) |
317 self.__selection = self.__normalizeSelection(r) |
325 self.__selection = self.__normalizeSelection(r) |
318 |
326 |
319 self.update() |
327 self.update() |
320 else: |
328 else: |
321 if self.__selection.isNull(): |
329 if self.__selection.isNull(): |
333 if self.__selection.contains(evt.pos()): |
341 if self.__selection.contains(evt.pos()): |
334 self.setCursor(Qt.OpenHandCursor) |
342 self.setCursor(Qt.OpenHandCursor) |
335 else: |
343 else: |
336 self.setCursor(Qt.CrossCursor) |
344 self.setCursor(Qt.CrossCursor) |
337 else: |
345 else: |
338 if self.__mouseOverHandle in [self.__TLHandle, self.__BRHandle]: |
346 if self.__mouseOverHandle in [self.__TLHandle, |
|
347 self.__BRHandle]: |
339 self.setCursor(Qt.SizeFDiagCursor) |
348 self.setCursor(Qt.SizeFDiagCursor) |
340 elif self.__mouseOverHandle in [self.__TRHandle, self.__BLHandle]: |
349 elif self.__mouseOverHandle in [self.__TRHandle, |
|
350 self.__BLHandle]: |
341 self.setCursor(Qt.SizeBDiagCursor) |
351 self.setCursor(Qt.SizeBDiagCursor) |
342 elif self.__mouseOverHandle in [self.__LHandle, self.__RHandle]: |
352 elif self.__mouseOverHandle in [self.__LHandle, |
|
353 self.__RHandle]: |
343 self.setCursor(Qt.SizeHorCursor) |
354 self.setCursor(Qt.SizeHorCursor) |
344 elif self.__mouseOverHandle in [self.__THandle, self.__BHandle]: |
355 elif self.__mouseOverHandle in [self.__THandle, |
|
356 self.__BHandle]: |
345 self.setCursor(Qt.SizeVerCursor) |
357 self.setCursor(Qt.SizeVerCursor) |
346 |
358 |
347 def mouseReleaseEvent(self, evt): |
359 def mouseReleaseEvent(self, evt): |
348 """ |
360 """ |
349 Protected method to handle mouse button releases. |
361 Protected method to handle mouse button releases. |
390 self.__BLHandle.moveBottomLeft(r.bottomLeft()) |
402 self.__BLHandle.moveBottomLeft(r.bottomLeft()) |
391 self.__BRHandle.moveBottomRight(r.bottomRight()) |
403 self.__BRHandle.moveBottomRight(r.bottomRight()) |
392 |
404 |
393 self.__LHandle.moveTopLeft(QPoint(r.x(), r.y() + r.height() // 2 - s2)) |
405 self.__LHandle.moveTopLeft(QPoint(r.x(), r.y() + r.height() // 2 - s2)) |
394 self.__THandle.moveTopLeft(QPoint(r.x() + r.width() // 2 - s2, r.y())) |
406 self.__THandle.moveTopLeft(QPoint(r.x() + r.width() // 2 - s2, r.y())) |
395 self.__RHandle.moveTopRight(QPoint(r.right(), r.y() + r.height() // 2 - s2)) |
407 self.__RHandle.moveTopRight( |
396 self.__BHandle.moveBottomLeft(QPoint(r.x() + r.width() // 2 - s2, r.bottom())) |
408 QPoint(r.right(), r.y() + r.height() // 2 - s2)) |
|
409 self.__BHandle.moveBottomLeft( |
|
410 QPoint(r.x() + r.width() // 2 - s2, r.bottom())) |
397 |
411 |
398 def __handleMask(self, maskType): |
412 def __handleMask(self, maskType): |
399 """ |
413 """ |
400 Private method to calculate the handle mask. |
414 Private method to calculate the handle mask. |
401 |
415 |
402 @param maskType type of the mask to be used (SnapshotRegionGrabber.FillMask or |
416 @param maskType type of the mask to be used |
|
417 (SnapshotRegionGrabber.FillMask or |
403 SnapshotRegionGrabber.StrokeMask) |
418 SnapshotRegionGrabber.StrokeMask) |
404 @return calculated mask (QRegion) |
419 @return calculated mask (QRegion) |
405 """ |
420 """ |
406 mask = QRegion() |
421 mask = QRegion() |
407 for rect in self.__handles: |
422 for rect in self.__handles: |
472 pixmap2.fill(Qt.transparent) |
487 pixmap2.fill(Qt.transparent) |
473 |
488 |
474 pt = QPainter() |
489 pt = QPainter() |
475 pt.begin(pixmap2) |
490 pt.begin(pixmap2) |
476 if pt.paintEngine().hasFeature(QPaintEngine.PorterDuff): |
491 if pt.paintEngine().hasFeature(QPaintEngine.PorterDuff): |
477 pt.setRenderHints(QPainter.Antialiasing | \ |
492 pt.setRenderHints( |
478 QPainter.HighQualityAntialiasing | QPainter.SmoothPixmapTransform, |
493 QPainter.Antialiasing | \ |
|
494 QPainter.HighQualityAntialiasing | \ |
|
495 QPainter.SmoothPixmapTransform, |
479 True) |
496 True) |
480 pt.setBrush(Qt.black) |
497 pt.setBrush(Qt.black) |
481 pt.setPen(QPen(QBrush(Qt.black), 0.5)) |
498 pt.setPen(QPen(QBrush(Qt.black), 0.5)) |
482 pt.drawEllipse(translatedEll.boundingRect()) |
499 pt.drawEllipse(translatedEll.boundingRect()) |
483 pt.setCompositionMode(QPainter.CompositionMode_SourceIn) |
500 pt.setCompositionMode(QPainter.CompositionMode_SourceIn) |
484 else: |
501 else: |
485 pt.setClipRegion(translatedEll) |
502 pt.setClipRegion(translatedEll) |
486 pt.setCompositionMode(QPainter.CompositionMode_Source) |
503 pt.setCompositionMode(QPainter.CompositionMode_Source) |
487 |
504 |
488 pt.drawPixmap(pixmap2.rect(), self.__pixmap, ell.boundingRect()) |
505 pt.drawPixmap(pixmap2.rect(), self.__pixmap, |
|
506 ell.boundingRect()) |
489 pt.end() |
507 pt.end() |
490 |
508 |
491 self.grabbed.emit(pixmap2) |
509 self.grabbed.emit(pixmap2) |
492 else: |
510 else: |
493 r = QRect(self.__selection) |
511 r = QRect(self.__selection) |