class frame(QtGui.QLabel): def __init__(self, parent=None): QtGui.QLabel.__init__(self, parent) self.rubberBand = QRubberBand(QRubberBand.Rectangle, self) self.origin = QPoint() def mousePressEvent(self, event): if event.button() == Qt.LeftButton: global LTx, LTy [LTx, LTy] = [event.pos().x(), event.pos().y()] self.origin = QPoint(event.pos()) self.rubberBand.setGeometry(QRect(self.origin, QSize())) self.rubberBand.show() def mouseMoveEvent(self, event): if not self.origin.isNull(): self.rubberBand.setGeometry( QRect(self.origin, event.pos()).normalized()) def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton: global RBx, RBy [RBx, RBy] = [event.pos().x(), event.pos().y()] self.rubberBand.hide()
class MyLabel(QLabel): def __init__(self, parent=None): QLabel.__init__(self, parent) self.rubberBand = QRubberBand(QRubberBand.Rectangle, self) self.origin = QPoint() def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.origin = QPoint(event.pos()) self.rubberBand.setGeometry(QRect(self.origin, QSize())) self.rubberBand.show() def mouseMoveEvent(self, event): if not self.origin.isNull(): self.rubberBand.setGeometry( QRect(self.origin, event.pos()).normalized()) def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton: self.rubberBand.hide()
class Surface(QLabel): imageReady = pyqtSignal(object) def __init__(self, parent=None): super(Surface, self).__init__(parent) self.setWindowFlags(Qt.SplashScreen | Qt.WindowStaysOnTopHint) self.setCursor(QCursor(Qt.CrossCursor)) self.setGeometry(getScreenDimensions()) self.prepareSurface() def prepareSurface(self): """Cover the entire screen with a screenshot of the screen.""" self.surfaceImage = captureFullScreen() self.setPixmap(self.surfaceImage) self.rubberband = QRubberBand(QRubberBand.Rectangle, self) def mousePressEvent(self, event): """Creates the starting point in any corner of a rectangle.""" if event.button() == Qt.LeftButton: self.origin = event.pos() self.rubberband.setGeometry(QRect(self.origin, QSize())) self.rubberband.show() if event.button() == Qt.RightButton and self.rubberband.isVisible(): self.dispose() def keyPressEvent(self, event): """Adds hotkey cancel functionality.""" if event.key() == Qt.Key_Escape: self.dispose() def mouseMoveEvent(self, event): """Expands the rectangle created in mousePressEvent to the mouse location.""" if self.rubberband.isVisible(): self.rubberband.setGeometry( QRect(self.origin, event.pos()).normalized()) def mouseReleaseEvent(self, event): """Takes a screenshot of region specified by the rectangle created with mousePressEvent & mouseMoveEvent.""" if self.rubberband.isVisible(): printRect = QRect(QPoint(self.origin.x(), self.origin.y()), QPoint(event.pos().x(), event.pos().y())) self.image = cropImage(self.surfaceImage, printRect) self.imageReady.emit("QPixmap ready") self.dispose() def dispose(self): """General clean-up of the QWidget and its children.""" self.rubberband.hide() self.hide() self.deleteLater()
class ClickReportingInterpreter(QObject): rightClickReceived = pyqtSignal(object, QPoint) # list of indexes, global window coordinate of click leftClickReceived = pyqtSignal(object, QPoint) # ditto leftClickReleased = pyqtSignal(object, object) def __init__(self, navigationInterpreter, positionModel, editor): QObject.__init__(self) self.baseInterpret = navigationInterpreter self.posModel = positionModel self.rubberBand = QRubberBand(QRubberBand.Rectangle, editor) self.origin = QPoint() self.originpos = object() def start( self ): self.baseInterpret.start() def stop( self ): self.baseInterpret.stop() def eventFilter( self, watched, event ): if event.type() == QEvent.MouseButtonPress: pos = [int(i) for i in self.posModel.cursorPos] pos = [self.posModel.time] + pos + [self.posModel.channel] if event.button() == Qt.LeftButton: self.origin = QPoint(event.pos()) self.originpos = pos self.rubberBand.setGeometry(QRect(self.origin, QSize())) self.rubberBand.show() gPos = watched.mapToGlobal( event.pos() ) self.leftClickReceived.emit( pos, gPos ) if event.button() == Qt.RightButton: gPos = watched.mapToGlobal( event.pos() ) self.rightClickReceived.emit( pos, gPos ) if event.type() == QEvent.MouseMove: if not self.origin.isNull(): self.rubberBand.setGeometry(QRect(self.origin, event.pos()).normalized()) if event.type() == QEvent.MouseButtonRelease: pos = [int(i) for i in self.posModel.cursorPos] pos = [self.posModel.time] + pos + [self.posModel.channel] if event.button() == Qt.LeftButton: self.rubberBand.hide() self.leftClickReleased.emit( self.originpos,pos ) # Event is always forwarded to the navigation interpreter. return self.baseInterpret.eventFilter(watched, event)
class PDFLabel(QLabel): def __init__(self, parent=None): QLabel.__init__(self, parent) self.currentPage = -1 self.doc = None self.rubberBand = None self.scaleFactor = 1.0 self.setAlignment(Qt.AlignCenter) self.dragPosition = QPoint() self.searchLocation = QRectF() self.copyMenu = CopyMenu(self) self.copySelectionMenu = CopySelectionMenu(self) def document(self): return self.doc def matrix(self): return QMatrix(self.scaleFactor * self.physicalDpiX() / 72.0, 0, 0, self.scaleFactor * self.physicalDpiY() / 72.0, 0, 0) def mousePressEvent(self, event): if not self.doc: return self.dragPosition = event.pos() if not self.rubberBand: self.rubberBand = QRubberBand(QRubberBand.Rectangle, self) self.rubberBand.setGeometry(QRect(self.dragPosition, QSize())) self.rubberBand.show() def mouseMoveEvent(self, event): if not self.doc: return self.rubberBand.setGeometry( QRect(self.dragPosition, event.pos()).normalized()) def mouseReleaseEvent(self, event): if not self.doc: return if not self.rubberBand.size().isEmpty(): rect = QRect(self.rubberBand.pos(), self.rubberBand.size()) rect.moveLeft(rect.left() - (self.width() - self.pixmap().width()) / 2.0) rect.moveTop(rect.top() - (self.height() - self.pixmap().height()) / 2.0) self.currentSelection = rect self.copySelectionMenu.popup(QCursor.pos()) #self.selectedText(rect) else: self.copyMenu.popup(QCursor.pos()) self.rubberBand.hide() def scale(self): return self.scaleFactor def showPage(self, page=-1): if (page != -1 and page != self.currentPage + 1): self.currentPage = page - 1 self.emit(SIGNAL("pageChanged"), page) image = self.doc.page(self.currentPage).renderToImage( self.scaleFactor * self.physicalDpiX(), self.scaleFactor * self.physicalDpiY()) if not self.searchLocation.isEmpty(): highlightRect = self.matrix().mapRect(self.searchLocation).toRect() highlightRect.adjust(-2, -2, 2, 2) highlight = image.copy(highlightRect) painter = QPainter() painter.begin(image) painter.fillRect(image.rect(), QColor(0, 0, 0, 128)) painter.drawImage(highlightRect, highlight) painter.end() self.setPixmap(QPixmap.fromImage(image)) def searchBackwards(self, text): oldLocation = self.searchLocation page = self.currentPage if oldLocation.isNull(): page -= 1 while page > -1: locations = [] self.searchLocation = QRectF() while self.doc.page(page).search(text, self.searchLocation, Poppler.Page.NextResult, Poppler.Page.CaseInsensitive): if self.searchLocation != oldLocation: locations.append(self.searchLocation) else: break try: index = locations.index(oldLocation) except: index = -1 if index == -1 and len(locations): self.searchLocation = locations[-1] self.showPage(page + 1) return self.searchLocation if index > 0: self.searchLocation = locations[index - 1] self.showPage(page + 1) return self.searchLocation oldLocation = QRectF() page -= 1 if self.currentPage == self.doc.numPages() - 1: return QRectF() oldLocation = QRectF() page = self.doc.numPages() - 1 while page > self.currentPage: locations = [] self.searchLocation = QRectF() while self.doc.page(page).search(text, self.searchLocation, Poppler.Page.NextResult, Poppler.Page.CaseInsensitive): locations.append(self.searchLocation) if len(locations): self.searchLocation = locations[-1] self.showPage(page + 1) return self.searchLocation page -= 1 return QRectF() def searchForwards(self, text): page = self.currentPage while page < self.doc.numPages(): if self.doc.page(page).search(text, self.searchLocation, Poppler.Page.NextResult, Poppler.Page.CaseInsensitive): if not self.searchLocation.isNull(): self.showPage(page + 1) return self.searchLocation page += 1 self.searchLocation = QRectF() page = 0 while page < self.currentPage: self.searchLocation = QRectF() if self.doc.page(page).search(text, self.searchLocation, Poppler.Page.NextResult, Poppler.Page.CaseInsensitive): if not self.searchLocation.isNull(): self.showPage(page + 1) return self.searchLocation page += 1 return QRectF() def copyTextToClipboard(self): selectedRect = self.matrix().inverted()[0].mapRect( self.currentSelection) r = ( selectedRect.x(), selectedRect.y(), selectedRect.width(), selectedRect.height(), ) text = self.doc.page(self.currentPage).text(QRectF(*r)) #Remove space #hadSpace = False #center = QPointF() #text = QString() #for box in self.doc.page(self.currentPage).textList(): #bounding = box.boundingBox() #r = (bounding.x(), bounding.y(), bounding.width(), bounding.height(),) #if selectedRect.intersects(QRect(*r)): #if hadSpace: #text += " " #if not text.isEmpty() and box.boundingBox().top() > center.y(): #text += "\n"; #text += box.text(); #hadSpace = box.hasSpaceAfter(); #center = box.boundingBox().center(); if not text.isEmpty(): QApplication.clipboard().setText(text, QClipboard.Clipboard) QApplication.clipboard().setText(text, QClipboard.Selection) def copySelectionToClipboard(self): #pixmap = self.currentSelection QApplication.clipboard().setPixmap(self.pixmap().copy( self.currentSelection)) def copyPixmapToClipboard(self): QApplication.clipboard().setPixmap(self.pixmap()) def setDocument(self, data): self.doc = Poppler.Document.loadFromData(data) if self.doc: #self.setVisible #change default behavior not visible if no document is set self.doc.setRenderHint(Poppler.Document.Antialiasing) self.doc.setRenderHint(Poppler.Document.TextAntialiasing) self.searchLocation = QRectF() self.currentPage = -1 self.setPage(1) return True return False def setError(self, errorMessage): self.setText(errorMessage) def setPage(self, page=-1): if page != self.currentPage + 1: self.searchLocation = QRectF() self.showPage(page) def setScale(self, scale): if self.scaleFactor != scale: self.scaleFactor = scale self.showPage()
class ThumbnailVideoView(QWidget, Script): IconSize = 256 Frames = 10 def __init__(self): Script.__init__(self, "thumbnailvideo") self.icon = None self.vfs = vfs.vfs() def start(self, args): try: self.preview = args["preview"].value() except IndexError: self.preview = False try: self.node = args["file"].value() except KeyError: pass def g_display(self): QWidget.__init__(self) self.copyMenu = CopyMenu(self) self.copySelectionMenu = CopySelectionMenu(self) self.rubberBand = None self.hlayout = QVBoxLayout() self.setLayout(self.hlayout) self.menuLayout = QHBoxLayout() self.hlayout.addLayout(self.menuLayout) self.frameLayout = QFormLayout() self.menuLayout.addLayout(self.frameLayout) self.frameNumberEdit = QLineEdit(str(self.Frames)) self.frameNumberEdit.setFixedWidth(40) self.frameNumberEdit.setValidator(QIntValidator(0, 256)) self.frameLayout.addRow("Number of frame: ", self.frameNumberEdit) self.connect(self.frameNumberEdit, SIGNAL("textChanged(QString)"), self.setFrameNumber) self.iconLayout = QFormLayout() self.menuLayout.addLayout(self.iconLayout) self.iconSizeEdit = QLineEdit(str(self.IconSize)) self.iconSizeEdit.setFixedWidth(40) self.iconSizeEdit.setValidator(QIntValidator(0, 512)) self.iconLayout.addRow("Size: ", self.iconSizeEdit) self.connect(self.iconSizeEdit, SIGNAL("textChanged(QString)"), self.setIconSize) self.refreshButton = QPushButton("Refresh") self.menuLayout.addWidget(self.refreshButton) self.connect(self.refreshButton, SIGNAL("clicked()"), self.generateThumbnail) self.scrollArea = QScrollArea() self.hlayout.addWidget(self.scrollArea) self.generateThumbnail() def mousePressEvent(self, event): self.dragPosition = event.pos() if not self.rubberBand: self.rubberBand = QRubberBand(QRubberBand.Rectangle, self) self.rubberBand.setGeometry(QRect(self.dragPosition, QSize())) self.rubberBand.show() def mouseMoveEvent(self, event): self.rubberBand.setGeometry( QRect(self.dragPosition, event.pos()).normalized()) def mouseReleaseEvent(self, event): if not self.rubberBand.size().isEmpty(): rect = QRect(self.rubberBand.pos(), self.rubberBand.size()) rect.moveLeft(rect.left() - (self.width() - self.thumbLabel.pixmap().width()) / 2.0) rect.moveTop(rect.top() - (self.height() - self.thumbLabel.pixmap().height()) / 2.0) self.currentSelection = rect self.copySelectionMenu.popup(QCursor.pos()) else: self.copyMenu.popup(QCursor.pos()) self.rubberBand.hide() def copySelectionToClipboard(self): QApplication.clipboard().setPixmap(self.thumbLabel.pixmap().copy( self.currentSelection)) def copyPixmapToClipboard(self): QApplication.clipboard().setPixmap(self.thumbLabel.pixmap()) def setIconSize(self, size): ThumbnailVideoView.IconSize = int(size) def setFrameNumber(self, number): ThumbnailVideoView.Frames = int(number) def generateThumbnail(self): self.thumbnailer = Thumbnailer() self.connect(self.thumbnailer, SIGNAL("ThumbnailUpdate"), self.updateThumbnail) pixmap = self.thumbnailer.generate(self.node, iconSize=self.IconSize, frames=self.Frames) if pixmap: self.updateThumbnail(self.node, pixmap) def updateThumbnail(self, node, pixmap): if pixmap: self.thumbLabel = QLabel() self.thumbLabel.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.thumbLabel.setWordWrap(True) self.thumbLabel.setPixmap(pixmap) self.scrollArea.setWidget(self.thumbLabel) else: self.thumbLabel.setText("Can't render, video is corrupted.") self.thumbLabel.setAlignment(Qt.AlignCenter) self.thumbnailer.unregister() def updateWidget(self): pass
class PatternView(QGraphicsView): def __init__(self, parent = None): super(PatternView, self).__init__(parent) self.setRenderHint(QPainter.Antialiasing) self.setRenderHint(QPainter.TextAntialiasing) self.setCacheMode(QGraphicsView.CacheBackground) self.setResizeAnchor(QGraphicsView.AnchorViewCenter) # initialize the rubberBand self.rubberBand = QRubberBand(QRubberBand.Rectangle, self) self.rubberBand.hide() self.rubberBandOrigin = None def mousePressEvent(self, event): """ Handles mouse press events. We override this function to check if the user requested a rubberBand selection. NOTE: We only propagate the event if no rubberBand was selected to avoid selection of the pattern grid item where the click occured. """ if event.modifiers() & Qt.ShiftModifier: self.rubberBandOrigin = event.pos() self.rubberBand.setGeometry(QRect(self.rubberBandOrigin, QSize())) self.rubberBand.show() return QGraphicsView.mousePressEvent(self, event) def mouseMoveEvent(self, event): """ Handle mouse move events. If a rubberBand is active we adjust the size otherwise we just hand off the signal. """ if self.rubberBandOrigin: self.rubberBand.setGeometry(QRect(self.rubberBandOrigin, event.pos()).normalized()) return QGraphicsView.mouseMoveEvent(self, event) def mouseReleaseEvent(self, event): """ Handle mouse release events. If a rubberBand is active we tell our GraphicsScene what are was selected and then disable the rubberBand. """ if self.rubberBandOrigin: self.scene().select_region((self.mapToScene( self.rubberBand.geometry()))) self.rubberBandOrigin = None self.rubberBand.hide() return QGraphicsView.mouseReleaseEvent(self, event) def wheelEvent(self, event): """ Mouse wheel events cause zooming in and out. """ if event.modifiers() & Qt.ControlModifier: if event.delta() > 0: self.zoom_in() else: self.zoom_out() else: QGraphicsView.wheelEvent(self, event) def zoom_in(self): """ Zoom in by 10% """ self.scale(1.1, 1.1) def zoom_out(self): """ Zoom out by 10% """ self.scale(0.9, 0.9) def fit_scene(self): """ Fit scene into canvas. """ margin = 50.0 rawBoundary = visible_bounding_rect(self.scene().items()) rawBoundary.adjust(-margin, -margin, margin, margin) self.fitInView(rawBoundary, Qt.KeepAspectRatio) def normal_view(self): """ Resets scene to normal (initial) view. """ self.resetMatrix()
class LoadedImage(QLabel): def __init__(self, parent): QLabel.__init__(self) self.parent = parent self.copyMenu = CopyMenu(self) self.copySelectionMenu = CopySelectionMenu(self) self.baseImage = QImage() self.matrix = QMatrix() self.zoomer = 1 self.maxsize = 1024 * 10 * 10 * 10 * 25 self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) self.setAlignment(Qt.AlignCenter) self.rubberBand = None def setParent(self, parent): self.parent = parent def load(self, node): self.matrix.reset() self.zoomer = 1 if node.size() < self.maxsize: self.node = node file = self.node.open() buff = file.read() file.close() if self.baseImage.loadFromData(buff): self.emit(SIGNAL("available(bool)"), True) else: self.baseImage.load(":file_broken.png") self.emit(SIGNAL("available(bool)"), False) else: self.baseImage.loadFromData("") self.emit(SIGNAL("available(bool)"), False) self.adjust() def adjust(self): if self.zoomer == 1: if self.baseImage.width() < self.parent.width() - 10: self.curWidth = self.baseImage.width() else: self.curWidth = self.parent.width() - 10 if self.baseImage.height() < self.parent.height() - 10: self.curHeight = self.baseImage.height() else: self.curHeight = self.parent.height() - 10 self.updateTransforms() def updateTransforms(self): if not self.baseImage.isNull(): self.currentImage = self.baseImage.transformed(self.matrix).scaled( QSize(self.curWidth, self.curHeight), Qt.KeepAspectRatio, Qt.FastTransformation) self.setPixmap(QPixmap.fromImage(self.currentImage)) else: self.clear() self.setText("File is too big to be processed") self.adjustSize() def rotateLeft(self): self.matrix.rotate(-90) self.updateTransforms() def rotateRight(self): self.matrix.rotate(90) self.updateTransforms() def enlarge(self): self.zoomer *= 1.25 self.curWidth *= 1.25 self.curHeight *= 1.25 self.updateTransforms() def shrink(self): self.zoomer *= 0.8 self.curWidth *= 0.8 self.curHeight *= 0.8 self.updateTransforms() def fit(self): self.zoomer = 1 self.adjust() def normal(self): self.curWidth = self.baseImage.width() self.curHeight = self.baseImage.height() self.updateTransforms() def mousePressEvent(self, event): self.dragPosition = event.pos() if not self.rubberBand: self.rubberBand = QRubberBand(QRubberBand.Rectangle, self) self.rubberBand.setGeometry(QRect(self.dragPosition, QSize())) self.rubberBand.show() def mouseMoveEvent(self, event): self.rubberBand.setGeometry( QRect(self.dragPosition, event.pos()).normalized()) def mouseReleaseEvent(self, event): if not self.rubberBand.size().isEmpty(): rect = QRect(self.rubberBand.pos(), self.rubberBand.size()) rect.moveLeft(rect.left() - (self.width() - self.pixmap().width()) / 2.0) rect.moveTop(rect.top() - (self.height() - self.pixmap().height()) / 2.0) self.currentSelection = rect self.copySelectionMenu.popup(QCursor.pos()) else: self.copyMenu.popup(QCursor.pos()) self.rubberBand.hide() def copySelectionToClipboard(self): QApplication.clipboard().setPixmap(self.pixmap().copy( self.currentSelection)) def copyPixmapToClipboard(self): QApplication.clipboard().setPixmap(self.pixmap())
class SfGraphicsScene(QGraphicsScene): def __init__(self, parent): super(SfGraphicsScene, self).__init__(parent) self._newLine = None self._rubberHand = None self._rubberHandOrigin = None def isDrawMode(self): return self.parent().isDrawMode() def dragEnterEvent(self, ev): super(SfGraphicsScene, self).dragEnterEvent(ev) if ev.mimeData().hasFormat("application/x-sf-component"): ev.accept() else: ev.ignore() def dragMoveEvent(self, ev): super(SfGraphicsScene, self).dragMoveEvent(ev) if ev.mimeData().hasFormat("application/x-sf-component"): ev.setDropAction(Qt.MoveAction) ev.accept() else: ev.ignore() def dropEvent(self, ev): super(SfGraphicsScene, self).dropEvent(ev) if ev.mimeData().hasFormat("application/x-sf-component"): data = ev.mimeData().data("application/x-sf-component") stream = QDataStream(data, QIODevice.ReadOnly) icon = QString() stream >> icon compType = icon.split(".")[0] try: comp = ObjectFactory({"name": compType, "type": compType, "pixmap": icon}).create() except TypeError as e: ev.ignore() msgBox = QMessageBox(); msgBox.setText(str(e)); #msgBox.setIcon(QMessageBox.Warning) msgBox.setIconPixmap(QPixmap(":" + icon)) msgBox.exec_(); return comp.setPos(ev.scenePos() - comp.boundingRect().center()) self.addItem(comp) ev.setDropAction(Qt.CopyAction) ev.accept() else: ev.ignore() def mousePressEvent(self, ev): super(SfGraphicsScene, self).mousePressEvent(ev) onComponent = self.itemAt(ev.scenePos()) if self.isDrawMode() and ev.button() == Qt.LeftButton and onComponent is not None: newLine = SfLine(onComponent) self.addItem(newLine) self._newLine = newLine onComponent.addLine(newLine) elif onComponent is None: self._rubberHandOrigin = ev.scenePos().toPoint() self._rubberHand = QRubberBand(QRubberBand.Rectangle, self.views()[0]) self._rubberHand.setGeometry(QRect(self._rubberHandOrigin, QSize())) self._rubberHand.show() def mouseMoveEvent(self, ev): super(SfGraphicsScene, self).mouseMoveEvent(ev) #clicked on empty space and moving if self._rubberHand is not None: self._rubberHand.setGeometry(QRect(self._rubberHandOrigin, ev.scenePos().toPoint()).normalized()) selectionArea = QPainterPath() selectionArea.addRect(QRectF(self._rubberHand.geometry())) self.setSelectionArea(selectionArea) if self.isDrawMode() and ev.buttons() == Qt.LeftButton and self._newLine is not None: line = self._newLine.line() line.setP2(ev.scenePos()) self._newLine.setLine(line) self._newLine.setStartPoint() def mouseReleaseEvent(self, ev): super(SfGraphicsScene, self).mouseReleaseEvent(ev) if self._rubberHand is not None: self._rubberHand.hide() self._rubberHand = None if self.isDrawMode() and ev.button() == Qt.LeftButton: onComponent = self.itemAt(ev.scenePos()) if (onComponent is None or onComponent is self._newLine or #released on empty space onComponent is self._newLine.getStart() or #released on itself self._newLine is None): #Redraw. if self._newLine is not None: self._newLine.remove() else: self._newLine.setEndComponent(onComponent) onComponent.addLine(self._newLine) self._newLine = None def moveSelectedItems(self, moveBy): for item in self.selectedItems(): item.moveBy(moveBy)
class DSnapshot(QDialog): """ Snapshot dialog """ def __init__(self, parent=None): """ Constructor """ QDialog.__init__(self, parent) self.state = 0 self.posX = 0 self.posY = 0 self.posW = 0 self.posH = 0 self.setWindowFlags(Qt.Tool | Qt.FramelessWindowHint) self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint) # maximize window screen = QDesktopWidget().screenGeometry() self.setGeometry(screen) # set cross cursor self.setCursor(Qt.CursorShape(Qt.CrossCursor)) # display self.show() # create rubberband self.rb = QRubberBand(QRubberBand.Rectangle) self.rb.setWindowOpacity(0.4) # new in v18, to support pyqt5 properly self.snapshotResult = None layout = QVBoxLayout() self.backgroundLabel = QLabel() layout.addWidget(self.backgroundLabel) layout.setContentsMargins(0, 0, 0, 0) self.setLayout(layout) def setBackground(self, pixmap): """ Set background """ self.backgroundLabel.setPixmap(pixmap) def mousePressEvent(self, ev): """ On mouse press event """ if ev.button() != Qt.LeftButton: self.abort() if self.state == 0: self.state = 1 self.origin = ev.globalPos() self.rb.setGeometry( QRect(self.origin, ev.globalPos()).normalized()) self.rb.show() def mouseMoveEvent(self, ev): """ On mouse move event """ if self.state == 1: self.rb.setGeometry( QRect(self.origin, ev.globalPos()).normalized()) def mouseReleaseEvent(self, ev): """ On mouse release event """ if self.state == 1: self.state = 2 self.end = ev.globalPos() self.rb.hide() self.doSnip() def keyPressEvent(self, ev): """ On key press event """ if ev.key() == Qt.Key_Escape: self.abort() def doSnip(self): """ Do snip """ x = min(self.origin.x(), self.end.x()) y = min(self.origin.y(), self.end.y()) w = abs(self.origin.x() - self.end.x()) h = abs(self.origin.y() - self.end.y()) self.posX = x self.posY = y self.posW = w self.posH = h self.hide() if QtHelper.IS_QT5: pixmap = self.backgroundLabel.grab(QRect(x, y, w, h)) else: pixmap = QPixmap.grabWidget(self.backgroundLabel, x, y, w, h) self.snapshotResult = pixmap self.accept() def getSnapshot(self): """ Return snapshot as pixmap """ return self.snapshotResult def getLocation(self): """ Return snapshot as pixmap """ return (self.posX, self.posY, self.posW, self.posH) def abort(self): """ close both windows and exit program """ pass
class Surface(QWidget): rightClicked = pyqtSignal(QPoint) linkClicked = pyqtSignal(QEvent, page.Page, popplerqt4.Poppler.Link) linkHovered = pyqtSignal(page.Page, popplerqt4.Poppler.Link) linkLeft = pyqtSignal() linkHelpRequested = pyqtSignal(QPoint, page.Page, popplerqt4.Poppler.Link) selectionChanged = pyqtSignal(QRect) def __init__(self, view): super(Surface, self).__init__(view) self.setBackgroundRole(QPalette.Dark) self._view = weakref.ref(view) self._currentLinkId = None self._dragging = False self._selecting = False self._magnifying = False self._magnifier = None self.setMagnifier(magnifier.Magnifier()) self.setMagnifierModifiers(Qt.CTRL) self._selection = QRect() self._rubberBand = QRubberBand(QRubberBand.Rectangle, self) self._scrolling = False self._scrollTimer = QTimer(interval=100, timeout=self._scrollTimeout) self._pageLayout = None self._highlights = weakref.WeakKeyDictionary() self.setPageLayout(layout.Layout()) self.setMouseTracking(True) self.setContextMenuPolicy(Qt.PreventContextMenu) self.setLinksEnabled(True) self.setSelectionEnabled(True) self.setShowUrlTips(True) def pageLayout(self): return self._pageLayout def setPageLayout(self, layout): old, self._pageLayout = self._pageLayout, layout if old: old.redraw.disconnect(self.redraw) old.changed.disconnect(self.updateLayout) layout.redraw.connect(self.redraw) layout.changed.connect(self.updateLayout) def view(self): """Returns our associated View.""" return self._view() def viewportRect(self): """Returns the rectangle of us that is visible in the View.""" return self.view().viewport().rect().translated(-self.pos()) def setSelectionEnabled(self, enabled): """Enables or disables selecting rectangular regions.""" self._selectionEnabled = enabled if not enabled: self.clearSelection() self._rubberBand.hide() self._selecting = False def selectionEnabled(self): """Returns True if selecting rectangular regions is enabled.""" return self._selectionEnabled def setLinksEnabled(self, enabled): """Enables or disables the handling of Poppler.Links in the pages.""" self._linksEnabled = enabled def linksEnabled(self): """Returns True if the handling of Poppler.Links in the pages is enabled.""" return self._linksEnabled def setShowUrlTips(self, enabled): """Enables or disables showing the URL in a tooltip when hovering a link. (Of course also setLinksEnabled(True) if you want this.) """ self._showUrlTips = enabled def showUrlTips(self): """Returns True if URLs are shown in a tooltip when hovering a link.""" return self._showUrlTips def setMagnifier(self, magnifier): """Sets the Magnifier to use (or None to disable the magnifier). The Surface takes ownership of the Magnifier. """ if self._magnifier: self._magnifier.setParent(None) magnifier.setParent(self) self._magnifier = magnifier def magnifier(self): """Returns the currently set magnifier.""" return self._magnifier def setMagnifierModifiers(self, modifiers): """Sets the modifiers (e.g. Qt.CTRL) to show the magnifier. Use None to show the magnifier always (instead of dragging). """ self._magnifierModifiers = modifiers def magnifierModifiers(self): """Returns the currently set keyboard modifiers (e.g. Qt.CTRL) to show the magnifier.""" return self._magnifierModifiers def hasSelection(self): """Returns True if there is a selection.""" return bool(self._selection) def setSelection(self, rect): """Sets the selection rectangle.""" rect = rect.normalized() old, self._selection = self._selection, rect self._rubberBand.setGeometry(rect) self._rubberBand.setVisible(bool(rect)) if rect != old: self.selectionChanged.emit(rect) def selection(self): """Returns the selection rectangle (normalized) or an invalid QRect().""" return QRect(self._selection) def clearSelection(self): """Hides the selection rectangle.""" self.setSelection(QRect()) def redraw(self, rect): """Called when the Layout wants to redraw a rectangle.""" self.update(rect) def updateLayout(self): """Conforms ourselves to our layout (that must already be updated.)""" self.clearSelection() self.resize(self._pageLayout.size()) self.update() def highlight(self, highlighter, areas, msec=0): """Highlights the list of areas using the given highlighter. Every area is a two-tuple (page, rect), where rect is a rectangle inside (0, 0, 1, 1) like the linkArea attribute of a Poppler.Link. """ d = weakref.WeakKeyDictionary() for page, areas in itertools.groupby(sorted(areas), lambda a: a[0]): d[page] = list(area[1] for area in areas) if msec: def clear(selfref=weakref.ref(self)): self = selfref() if self: self.clearHighlight(highlighter) t = QTimer(singleShot = True, timeout = clear) t.start(msec) else: t = None self.clearHighlight(highlighter) self._highlights[highlighter] = (d, t) self.update(sum((page.rect() for page in d), QRegion())) def clearHighlight(self, highlighter): """Removes the highlighted areas of the given highlighter.""" try: (d, t) = self._highlights[highlighter] except KeyError: return del self._highlights[highlighter] self.update(sum((page.rect() for page in d), QRegion())) def paintEvent(self, ev): painter = QPainter(self) pages = list(self.pageLayout().pagesAt(ev.rect())) for page in pages: page.paint(painter, ev.rect()) for highlighter, (d, t) in self._highlights.items(): rects = [] for page in pages: try: rects.extend(map(page.linkRect, d[page])) except KeyError: continue if rects: highlighter.paintRects(painter, rects) def mousePressEvent(self, ev): # link? if self._linksEnabled: page, link = self.pageLayout().linkAt(ev.pos()) if link: self.linkClickEvent(ev, page, link) return # magnifier? if (self._magnifier and int(ev.modifiers()) & _SCAM == self._magnifierModifiers and ev.button() == Qt.LeftButton): self._magnifier.moveCenter(ev.pos()) self._magnifier.show() self._magnifier.raise_() self._magnifying = True self.setCursor(QCursor(Qt.BlankCursor)) return # selecting? if self._selectionEnabled: if self.hasSelection(): edge = selectionEdge(ev.pos(), self.selection()) if edge == _OUTSIDE: self.clearSelection() else: if ev.button() != Qt.RightButton or edge != _INSIDE: self._selecting = True self._selectionEdge = edge self._selectionRect = self.selection() self._selectionPos = ev.pos() if edge == _INSIDE: self.setCursor(Qt.SizeAllCursor) return if not self._selecting: if ev.button() == Qt.RightButton or int(ev.modifiers()) & _SCAM: self._selecting = True self._selectionEdge = _RIGHT | _BOTTOM self._selectionRect = QRect(ev.pos(), QSize(0, 0)) self._selectionPos = ev.pos() return if ev.button() == Qt.LeftButton: self._dragging = True self._dragPos = ev.globalPos() def mouseReleaseEvent(self, ev): if self._dragging: self._dragging = False elif self._magnifying: self._magnifier.hide() self._magnifying = False else: if self._selecting: self._selecting = False selection = self._selectionRect.normalized() if selection.width() < 8 and selection.height() < 8: self.clearSelection() else: self.setSelection(selection) if self._scrolling: self.stopScrolling() self.updateCursor(ev.pos()) if ev.button() == Qt.RightButton: self.rightClick(ev.pos()) def mouseMoveEvent(self, ev): if self._dragging: self.setCursor(Qt.SizeAllCursor) diff = self._dragPos - ev.globalPos() self._dragPos = ev.globalPos() self.view().scrollSurface(diff) elif self._magnifying: self._magnifier.moveCenter(ev.pos()) elif self._selecting: self._moveSelection(ev.pos()) self._rubberBand.show() # check if we are dragging close to the edge of the view, scroll if needed view = self.viewportRect() dx = ev.x() - view.left() - 12 if dx >= 0: dx = ev.x() - view.right() + 12 if dx < 0: dx = 0 dy = ev.y() - view.top() - 12 if dy >= 0: dy = ev.y() - view.bottom() + 12 if dy < 0: dy = 0 if dx or dy: self.startScrolling(dx, dy) elif self._scrolling: self.stopScrolling() else: self.updateCursor(ev.pos()) def moveEvent(self, ev): pos = self.mapFromGlobal(QCursor.pos()) if self._selecting: self._moveSelection(pos) elif self._magnifying: self._magnifier.moveCenter(pos) elif not self._dragging: self.updateCursor(pos) def event(self, ev): if isinstance(ev, QHelpEvent): if self._linksEnabled: page, link = self.pageLayout().linkAt(ev.pos()) if link: self.linkHelpEvent(ev.globalPos(), page, link) return True return super(Surface, self).event(ev) def updateCursor(self, pos): cursor = None if self._linksEnabled: page, link = self.pageLayout().linkAt(pos) if link: cursor = Qt.PointingHandCursor lid = id(link) else: lid = None if lid != self._currentLinkId: if self._currentLinkId is not None: self.linkHoverLeave() self._currentLinkId = lid if link: self.linkHoverEnter(page, link) if self._selectionEnabled and cursor is None and self.hasSelection(): edge = selectionEdge(pos, self.selection()) if edge in (_TOP, _BOTTOM): cursor = Qt.SizeVerCursor elif edge in (_LEFT, _RIGHT): cursor = Qt.SizeHorCursor elif edge in (_LEFT | _TOP, _RIGHT | _BOTTOM): cursor = Qt.SizeFDiagCursor elif edge in (_TOP | _RIGHT, _BOTTOM | _LEFT): cursor = Qt.SizeBDiagCursor self.setCursor(cursor) if cursor else self.unsetCursor() def linkHelpEvent(self, globalPos, page, link): """Called when a QHelpEvent occurs on a link. The default implementation shows a tooltip if showUrls() is True, and emits the linkHelpRequested() signal. """ if self._showUrlTips and isinstance(link, popplerqt4.Poppler.LinkBrowse): QToolTip.showText(globalPos, link.url(), self, page.linkRect(link.linkArea())) self.linkHelpRequested.emit(globalPos, page, link) def rightClick(self, pos): """Called when the right mouse button is released. (Use this instead of the contextMenuEvent as that one also fires when starting a right-button selection.) The default implementation emite the rightClicked(pos) signal and also sends a ContextMenu event to the View widget. """ self.rightClicked.emit(pos) QApplication.postEvent(self.view().viewport(), QContextMenuEvent(QContextMenuEvent.Mouse, pos + self.pos())) def linkClickEvent(self, ev, page, link): """Called when a link is clicked. The default implementation emits the linkClicked(event, page, link) signal. """ self.linkClicked.emit(ev, page, link) def linkHoverEnter(self, page, link): """Called when the mouse hovers over a link. The default implementation emits the linkHovered(page, link) signal. """ self.linkHovered.emit(page, link) def linkHoverLeave(self): """Called when the mouse does not hover a link anymore. The default implementation emits the linkLeft() signal. """ self.linkLeft.emit() def startScrolling(self, dx, dy): """Starts scrolling dx, dy about 10 times a second. Stops automatically when the end is reached. """ self._scrolling = QPoint(dx, dy) self._scrollTimer.isActive() or self._scrollTimer.start() def stopScrolling(self): """Stops scrolling.""" self._scrolling = False self._scrollTimer.stop() def _scrollTimeout(self): """(Internal) Called by the _scrollTimer.""" # change the scrollbars, but check how far they really moved. pos = self.pos() self.view().scrollSurface(self._scrolling) diff = pos - self.pos() if not diff: self.stopScrolling() def _moveSelection(self, pos): """(Internal) Moves the dragged selection edge or corner to the given pos (QPoint).""" diff = pos - self._selectionPos self._selectionPos = pos edge = self._selectionEdge self._selectionRect.adjust( diff.x() if edge & _LEFT else 0, diff.y() if edge & _TOP else 0, diff.x() if edge & _RIGHT else 0, diff.y() if edge & _BOTTOM else 0) self._rubberBand.setGeometry(self._selectionRect.normalized()) if self.cursor().shape() in (Qt.SizeBDiagCursor, Qt.SizeFDiagCursor): # we're dragging a corner, use correct diagonal cursor bdiag = (edge in (3, 12)) ^ (self._selectionRect.width() * self._selectionRect.height() >= 0) self.setCursor(Qt.SizeBDiagCursor if bdiag else Qt.SizeFDiagCursor)
class PatternView(QGraphicsView): def __init__(self, parent=None): super(PatternView, self).__init__(parent) self.setRenderHint(QPainter.Antialiasing) self.setRenderHint(QPainter.TextAntialiasing) self.setCacheMode(QGraphicsView.CacheBackground) self.setResizeAnchor(QGraphicsView.AnchorViewCenter) # initialize the rubberBand self.rubberBand = QRubberBand(QRubberBand.Rectangle, self) self.rubberBand.hide() self.rubberBandOrigin = None def mousePressEvent(self, event): """ Handles mouse press events. We override this function to check if the user requested a rubberBand selection. NOTE: We only propagate the event if no rubberBand was selected to avoid selection of the pattern grid item where the click occured. """ if event.modifiers() & Qt.ShiftModifier: self.rubberBandOrigin = event.pos() self.rubberBand.setGeometry(QRect(self.rubberBandOrigin, QSize())) self.rubberBand.show() return QGraphicsView.mousePressEvent(self, event) def mouseMoveEvent(self, event): """ Handle mouse move events. If a rubberBand is active we adjust the size otherwise we just hand off the signal. """ if self.rubberBandOrigin: self.rubberBand.setGeometry( QRect(self.rubberBandOrigin, event.pos()).normalized()) return QGraphicsView.mouseMoveEvent(self, event) def mouseReleaseEvent(self, event): """ Handle mouse release events. If a rubberBand is active we tell our GraphicsScene what are was selected and then disable the rubberBand. """ if self.rubberBandOrigin: self.scene().select_region( (self.mapToScene(self.rubberBand.geometry()))) self.rubberBandOrigin = None self.rubberBand.hide() return QGraphicsView.mouseReleaseEvent(self, event) def wheelEvent(self, event): """ Mouse wheel events cause zooming in and out. """ if event.modifiers() & Qt.ControlModifier: if event.delta() > 0: self.zoom_in() else: self.zoom_out() else: QGraphicsView.wheelEvent(self, event) def zoom_in(self): """ Zoom in by 10% """ self.scale(1.1, 1.1) def zoom_out(self): """ Zoom out by 10% """ self.scale(0.9, 0.9) def fit_scene(self): """ Fit scene into canvas. """ margin = 50.0 rawBoundary = visible_bounding_rect(self.scene().items()) rawBoundary.adjust(-margin, -margin, margin, margin) self.fitInView(rawBoundary, Qt.KeepAspectRatio) def normal_view(self): """ Resets scene to normal (initial) view. """ self.resetMatrix()