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
96 lines
3.7 KiB
from PyQt5.QtWidgets import QScrollArea, QLabel, QVBoxLayout, QWidget, QSizePolicy
|
|
from PyQt5.QtCore import Qt, QPoint, QSize
|
|
from PyQt5.QtGui import QPixmap, QImage, QResizeEvent, QPainter
|
|
|
|
import fitz
|
|
|
|
class PDFLabel(QLabel):
|
|
def __init__(self, parent):
|
|
super().__init__(parent)
|
|
self.parent = parent
|
|
self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Preferred)
|
|
|
|
def paintEvent(self, event):
|
|
self.adjustSize()
|
|
if self.pixmap() is not None:
|
|
painter = QPainter(self)
|
|
# painter.setRenderHint(QPainter.Antialiasing)
|
|
|
|
parentLayoutMargins = self.parent.scrollAreaLayout.getContentsMargins()
|
|
parentMargins = self.parent.getContentsMargins()
|
|
|
|
if self.parent.verticalScrollBar().isVisible():
|
|
scrollBarWidth = self.parent.verticalScrollBar().sizeHint().width()
|
|
else:
|
|
scrollBarWidth = 0
|
|
|
|
totalMargin = parentLayoutMargins[0] + parentLayoutMargins[2] + \
|
|
parentMargins[0]*2 + scrollBarWidth
|
|
|
|
idealWidth = self.parent.width() - totalMargin
|
|
# print(idealWidth)
|
|
pixSize = self.pixmap().size()
|
|
# print(pixSize)
|
|
# print((self.parent.scrollAreaContents.size()))
|
|
|
|
pixSize.scale(idealWidth, 1000000, Qt.KeepAspectRatio)
|
|
|
|
scaledPix = self.pixmap().scaled(pixSize, Qt.KeepAspectRatio, Qt.SmoothTransformation)
|
|
painter.drawPixmap(QPoint(), scaledPix)
|
|
self.setMaximumSize(pixSize)
|
|
|
|
class PDFViewer(QScrollArea):
|
|
def __init__(self, parent):
|
|
super().__init__(parent)
|
|
self.scrollAreaContents = QWidget()
|
|
self.scrollAreaLayout = QVBoxLayout()
|
|
|
|
self.setWidget(self.scrollAreaContents)
|
|
self.setWidgetResizable(True)
|
|
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
|
# set a fixed background colour
|
|
# on some OSes (Mac, Haiku) it is grey automatically but not on KDE
|
|
self.setStyleSheet('PDFViewer {background-color: #D8D8D8}')
|
|
|
|
self.scrollAreaContents.setLayout(self.scrollAreaLayout)
|
|
self.pixmapList = []
|
|
self.lastVScrollPosition = None
|
|
|
|
def update_pdf(self, pdf):
|
|
self.render(pdf)
|
|
self.clear()
|
|
self.show()
|
|
|
|
def render(self, pdf):
|
|
"""
|
|
Update the preview shown by rendering a new PDF and drawing it to the scroll area.
|
|
"""
|
|
|
|
self.pixmapList = []
|
|
pdfView = fitz.Document(stream=pdf, filetype='pdf')
|
|
for page in pdfView:
|
|
# needs to be high enough for big monitors. 300 should do it...
|
|
self.pixmapList.append(page.get_pixmap(dpi=300, alpha=False))
|
|
|
|
def clear(self):
|
|
self.lastVScrollPosition = self.verticalScrollBar().value()
|
|
while self.scrollAreaLayout.count():
|
|
item = self.scrollAreaLayout.takeAt(0)
|
|
w = item.widget()
|
|
if w:
|
|
w.deleteLater()
|
|
|
|
def show(self):
|
|
for p in self.pixmapList:
|
|
label = PDFLabel(parent=self)
|
|
label.setAlignment(Qt.AlignHCenter)
|
|
qtimg = QImage(p.samples, p.width, p.height, p.stride, QImage.Format_RGB888)
|
|
label.setPixmap(QPixmap.fromImage(qtimg))
|
|
self.scrollAreaLayout.addWidget(label)
|
|
|
|
self.scrollAreaLayout.addStretch(1)
|
|
|
|
# Somewhat of a hack. Should really replace pixmaps in place
|
|
# rather than removing labels elsewhere in code.
|
|
if self.lastVScrollPosition:
|
|
self.verticalScrollBar().setValue(self.lastVScrollPosition)
|