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()