11 import enum |
11 import enum |
12 |
12 |
13 from dataclasses import dataclass |
13 from dataclasses import dataclass |
14 |
14 |
15 from PyQt6.QtCore import ( |
15 from PyQt6.QtCore import ( |
16 QSize, Qt, pyqtSlot, QEvent, QSizeF, QRect, QPoint, QPointF, QRectF, |
16 QEvent, |
17 pyqtSignal |
17 QPoint, |
|
18 QPointF, |
|
19 QRect, |
|
20 QRectF, |
|
21 QSize, |
|
22 QSizeF, |
|
23 Qt, |
|
24 pyqtSignal, |
|
25 pyqtSlot, |
18 ) |
26 ) |
19 from PyQt6.QtGui import QGuiApplication, QPainter, QColor, QPen |
27 from PyQt6.QtGui import QColor, QGuiApplication, QPainter, QPen |
20 from PyQt6.QtPdf import QPdfDocument, QPdfLink |
28 from PyQt6.QtPdf import QPdfDocument, QPdfLink |
21 from PyQt6.QtPdfWidgets import QPdfView |
29 from PyQt6.QtPdfWidgets import QPdfView |
22 from PyQt6.QtWidgets import QRubberBand |
30 from PyQt6.QtWidgets import QRubberBand |
23 |
31 |
24 from .PdfZoomSelector import PdfZoomSelector |
32 from .PdfZoomSelector import PdfZoomSelector |
54 |
62 |
55 |
63 |
56 class PdfView(QPdfView): |
64 class PdfView(QPdfView): |
57 """ |
65 """ |
58 Class implementing a specialized PDF view. |
66 Class implementing a specialized PDF view. |
|
67 |
|
68 @signal selectionAvailable(bool) emitted to indicate the availability of a selection |
59 """ |
69 """ |
60 |
70 |
61 MarkerColors = { |
71 MarkerColors = { |
62 # merker type: (pen color, brush color) |
72 # merker type: (pen color, brush color) |
63 PdfMarkerType.SEARCHRESULT: (QColor(255, 200, 0, 255), QColor(255, 200, 0, 64)), |
73 PdfMarkerType.SEARCHRESULT: (QColor(255, 200, 0, 255), QColor(255, 200, 0, 64)), |
175 self.document().pagePointSize(curPage) * self.__screenResolution |
185 self.document().pagePointSize(curPage) * self.__screenResolution |
176 ).toSize() |
186 ).toSize() |
177 pageSize = pageSize.scaled( |
187 pageSize = pageSize.scaled( |
178 viewportSize, Qt.AspectRatioMode.KeepAspectRatio |
188 viewportSize, Qt.AspectRatioMode.KeepAspectRatio |
179 ) |
189 ) |
180 zoomFactor = pageSize.width() / ( |
190 zoomFactor = ( |
181 self.document().pagePointSize(curPage) * self.__screenResolution |
191 pageSize.width() |
182 ).width() |
192 / ( |
|
193 self.document().pagePointSize(curPage) * self.__screenResolution |
|
194 ).width() |
|
195 ) |
183 return zoomFactor |
196 return zoomFactor |
184 |
197 |
185 @pyqtSlot() |
198 @pyqtSlot() |
186 def zoomIn(self): |
199 def zoomIn(self): |
187 """ |
200 """ |
295 translatedRubber = translatedRubber.translated( |
308 translatedRubber = translatedRubber.translated( |
296 -self.__pageGeometries[page].topLeft() |
309 -self.__pageGeometries[page].topLeft() |
297 ) |
310 ) |
298 factor = self.__zoomFactorForMode(self.zoomMode()) |
311 factor = self.__zoomFactorForMode(self.zoomMode()) |
299 selectionSize = ( |
312 selectionSize = ( |
300 QSizeF(translatedRubber.size()) / factor |
313 QSizeF(translatedRubber.size()) |
|
314 / factor |
301 / self.__screenResolution |
315 / self.__screenResolution |
302 ) |
316 ) |
303 selectionTopLeft = ( |
317 selectionTopLeft = ( |
304 QPointF(translatedRubber.topLeft()) / factor |
318 QPointF(translatedRubber.topLeft()) |
|
319 / factor |
305 / self.__screenResolution |
320 / self.__screenResolution |
306 ) |
321 ) |
307 selectionRect = QRectF(selectionTopLeft, selectionSize) |
322 selectionRect = QRectF(selectionTopLeft, selectionSize) |
308 selection = self.document().getSelection( |
323 selection = self.document().getSelection( |
309 page, selectionRect.topLeft(), selectionRect.bottomRight() |
324 page, selectionRect.topLeft(), selectionRect.bottomRight() |
378 painter = QPainter(self.viewport()) |
393 painter = QPainter(self.viewport()) |
379 painter.translate(-self.__documentViewport.x(), -self.__documentViewport.y()) |
394 painter.translate(-self.__documentViewport.x(), -self.__documentViewport.y()) |
380 for page in self.__markerGeometries: |
395 for page in self.__markerGeometries: |
381 for markerGeom in self.__markerGeometries[page]: |
396 for markerGeom in self.__markerGeometries[page]: |
382 if markerGeom.rectangle.intersects(self.__documentViewport): |
397 if markerGeom.rectangle.intersects(self.__documentViewport): |
383 painter.setPen(QPen( |
398 painter.setPen( |
384 PdfView.MarkerColors[markerGeom.markerType][0], 2 |
399 QPen(PdfView.MarkerColors[markerGeom.markerType][0], 2) |
385 )) |
400 ) |
386 painter.setBrush(PdfView.MarkerColors[markerGeom.markerType][1]) |
401 painter.setBrush(PdfView.MarkerColors[markerGeom.markerType][1]) |
387 painter.drawRect(markerGeom.rectangle) |
402 painter.drawRect(markerGeom.rectangle) |
388 painter.end() |
403 painter.end() |
389 |
404 |
390 def __calculateDocumentViewport(self): |
405 def __calculateDocumentViewport(self): |
396 """ |
411 """ |
397 x = self.horizontalScrollBar().value() |
412 x = self.horizontalScrollBar().value() |
398 y = self.verticalScrollBar().value() |
413 y = self.verticalScrollBar().value() |
399 width = self.viewport().width() |
414 width = self.viewport().width() |
400 height = self.viewport().height() |
415 height = self.viewport().height() |
401 |
416 |
402 docViewport = QRect(x, y, width, height) |
417 docViewport = QRect(x, y, width, height) |
403 if self.__documentViewport == docViewport: |
418 if self.__documentViewport == docViewport: |
404 return |
419 return |
405 |
420 |
406 oldSize = self.__documentViewport.size() |
421 oldSize = self.__documentViewport.size() |
422 self.__pageGeometries.clear() |
437 self.__pageGeometries.clear() |
423 self.__markerGeometries.clear() |
438 self.__markerGeometries.clear() |
424 |
439 |
425 document = self.document() |
440 document = self.document() |
426 margins = self.documentMargins() |
441 margins = self.documentMargins() |
427 |
442 |
428 if document is None or document.status() != QPdfDocument.Status.Ready: |
443 if document is None or document.status() != QPdfDocument.Status.Ready: |
429 return |
444 return |
430 |
445 |
431 pageCount = document.pageCount() |
446 pageCount = document.pageCount() |
432 |
447 |
433 totalWidth = 0 |
448 totalWidth = 0 |
434 |
449 |
435 startPage = ( |
450 startPage = ( |
436 self.pageNavigator().currentPage() |
451 self.pageNavigator().currentPage() |
437 if self.pageMode() == QPdfView.PageMode.SinglePage |
452 if self.pageMode() == QPdfView.PageMode.SinglePage |
438 else 0 |
453 else 0 |
439 ) |
454 ) |
445 |
460 |
446 # calculate pageSizes |
461 # calculate pageSizes |
447 for page in range(startPage, endPage): |
462 for page in range(startPage, endPage): |
448 if self.zoomMode() == QPdfView.ZoomMode.Custom: |
463 if self.zoomMode() == QPdfView.ZoomMode.Custom: |
449 pageSize = QSizeF( |
464 pageSize = QSizeF( |
450 document.pagePointSize(page) * self.__screenResolution |
465 document.pagePointSize(page) |
|
466 * self.__screenResolution |
451 * self.zoomFactor() |
467 * self.zoomFactor() |
452 ).toSize() |
468 ).toSize() |
453 elif self.zoomMode() == QPdfView.ZoomMode.FitToWidth: |
469 elif self.zoomMode() == QPdfView.ZoomMode.FitToWidth: |
454 pageSize = QSizeF( |
470 pageSize = QSizeF( |
455 document.pagePointSize(page) * self.__screenResolution |
471 document.pagePointSize(page) * self.__screenResolution |
457 factor = ( |
473 factor = ( |
458 self.__documentViewport.width() - margins.left() - margins.right() |
474 self.__documentViewport.width() - margins.left() - margins.right() |
459 ) / pageSize.width() |
475 ) / pageSize.width() |
460 pageSize *= factor |
476 pageSize *= factor |
461 elif self.zoomMode() == QPdfView.ZoomMode.FitInView: |
477 elif self.zoomMode() == QPdfView.ZoomMode.FitInView: |
462 viewportSize = ( |
478 viewportSize = self.__documentViewport.size() + QSize( |
463 self.__documentViewport.size() |
479 -margins.left() - margins.right(), -self.pageSpacing() |
464 + QSize(-margins.left() - margins.right(), -self.pageSpacing()) |
|
465 ) |
480 ) |
466 pageSize = QSizeF( |
481 pageSize = QSizeF( |
467 document.pagePointSize(page) * self.__screenResolution |
482 document.pagePointSize(page) * self.__screenResolution |
468 ).toSize() |
483 ).toSize() |
469 pageSize = pageSize.scaled( |
484 pageSize = pageSize.scaled( |
520 for marker in self.__markers[page]: |
535 for marker in self.__markers[page]: |
521 markerSize = ( |
536 markerSize = ( |
522 QSizeF(marker.rectangle.size()) * factor * self.__screenResolution |
537 QSizeF(marker.rectangle.size()) * factor * self.__screenResolution |
523 ).toSize() |
538 ).toSize() |
524 markerTopLeft = ( |
539 markerTopLeft = ( |
525 QPointF(marker.rectangle.topLeft()) * factor |
540 QPointF(marker.rectangle.topLeft()) |
|
541 * factor |
526 * self.__screenResolution |
542 * self.__screenResolution |
527 ).toPoint() |
543 ).toPoint() |
528 |
544 |
529 markerGeometry = QRect(markerTopLeft, markerSize) |
545 markerGeometry = QRect(markerTopLeft, markerSize) |
530 self.__markerGeometries[page].append( |
546 self.__markerGeometries[page].append( |
531 PdfMarkerGeometry( |
547 PdfMarkerGeometry( |
532 rectangle=markerGeometry.translated(offset), |
548 rectangle=markerGeometry.translated(offset), |
533 markerType=marker.markerType |
549 markerType=marker.markerType, |
534 ) |
550 ) |
535 ) |
551 ) |
536 |
552 |
537 def scrollContentsBy(self, dx, dy): |
553 def scrollContentsBy(self, dx, dy): |
538 """ |
554 """ |
637 @return reference to the PDF selection object |
653 @return reference to the PDF selection object |
638 @rtype QPdfSelection |
654 @rtype QPdfSelection |
639 """ |
655 """ |
640 for page in self.__markers: |
656 for page in self.__markers: |
641 markersList = [ |
657 markersList = [ |
642 m for m in self.__markers[page] |
658 m |
|
659 for m in self.__markers[page] |
643 if m.markerType == PdfMarkerType.SELECTION |
660 if m.markerType == PdfMarkerType.SELECTION |
644 ] |
661 ] |
645 if markersList: |
662 if markersList: |
646 selection = self.document().getSelection( |
663 selection = self.document().getSelection( |
647 page, |
664 page, |