You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

96 lines
3.7 KiB

  1. from PyQt5.QtWidgets import QScrollArea, QLabel, QVBoxLayout, QWidget, QSizePolicy
  2. from PyQt5.QtCore import Qt, QPoint, QSize
  3. from PyQt5.QtGui import QPixmap, QImage, QResizeEvent, QPainter
  4. import fitz
  5. class PDFLabel(QLabel):
  6. def __init__(self, parent):
  7. super().__init__(parent)
  8. self.parent = parent
  9. self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Preferred)
  10. def paintEvent(self, event):
  11. self.adjustSize()
  12. if self.pixmap() is not None:
  13. painter = QPainter(self)
  14. # painter.setRenderHint(QPainter.Antialiasing)
  15. parentLayoutMargins = self.parent.scrollAreaLayout.getContentsMargins()
  16. parentMargins = self.parent.getContentsMargins()
  17. if self.parent.verticalScrollBar().isVisible():
  18. scrollBarWidth = self.parent.verticalScrollBar().sizeHint().width()
  19. else:
  20. scrollBarWidth = 0
  21. totalMargin = parentLayoutMargins[0] + parentLayoutMargins[2] + \
  22. parentMargins[0]*2 + scrollBarWidth
  23. idealWidth = self.parent.width() - totalMargin
  24. # print(idealWidth)
  25. pixSize = self.pixmap().size()
  26. # print(pixSize)
  27. # print((self.parent.scrollAreaContents.size()))
  28. pixSize.scale(idealWidth, 1000000, Qt.KeepAspectRatio)
  29. scaledPix = self.pixmap().scaled(pixSize, Qt.KeepAspectRatio, Qt.SmoothTransformation)
  30. painter.drawPixmap(QPoint(), scaledPix)
  31. self.setMaximumSize(pixSize)
  32. class PDFViewer(QScrollArea):
  33. def __init__(self, parent):
  34. super().__init__(parent)
  35. self.scrollAreaContents = QWidget()
  36. self.scrollAreaLayout = QVBoxLayout()
  37. self.setWidget(self.scrollAreaContents)
  38. self.setWidgetResizable(True)
  39. self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
  40. # set a fixed background colour
  41. # on some OSes (Mac, Haiku) it is grey automatically but not on KDE
  42. self.setStyleSheet('PDFViewer {background-color: #D8D8D8}')
  43. self.scrollAreaContents.setLayout(self.scrollAreaLayout)
  44. self.pixmapList = []
  45. self.lastVScrollPosition = None
  46. def update_pdf(self, pdf):
  47. self.render(pdf)
  48. self.clear()
  49. self.show()
  50. def render(self, pdf):
  51. """
  52. Update the preview shown by rendering a new PDF and drawing it to the scroll area.
  53. """
  54. self.pixmapList = []
  55. pdfView = fitz.Document(stream=pdf, filetype='pdf')
  56. for page in pdfView:
  57. # needs to be high enough for big monitors. 300 should do it...
  58. self.pixmapList.append(page.get_pixmap(dpi=300, alpha=False))
  59. def clear(self):
  60. self.lastVScrollPosition = self.verticalScrollBar().value()
  61. while self.scrollAreaLayout.count():
  62. item = self.scrollAreaLayout.takeAt(0)
  63. w = item.widget()
  64. if w:
  65. w.deleteLater()
  66. def show(self):
  67. for p in self.pixmapList:
  68. label = PDFLabel(parent=self)
  69. label.setAlignment(Qt.AlignHCenter)
  70. qtimg = QImage(p.samples, p.width, p.height, p.stride, QImage.Format_RGB888)
  71. label.setPixmap(QPixmap.fromImage(qtimg))
  72. self.scrollAreaLayout.addWidget(label)
  73. self.scrollAreaLayout.addStretch(1)
  74. # Somewhat of a hack. Should really replace pixmaps in place
  75. # rather than removing labels elsewhere in code.
  76. if self.lastVScrollPosition:
  77. self.verticalScrollBar().setValue(self.lastVScrollPosition)