Closes: #4 After consideration, we don't want to change the size of the dialog which is the only way to make it fit the PDF. But the geometry is saved, so the user can resize and place it. We did set the splitter to give more space to the PDF.
215 lines
6.9 KiB
Python
215 lines
6.9 KiB
Python
import math
|
|
|
|
from PySide6.QtCore import QFile, QModelIndex, QPoint, QSize, Signal, Slot
|
|
from PySide6.QtGui import QCloseEvent, QGuiApplication
|
|
from PySide6.QtPdf import QPdfBookmarkModel, QPdfDocument
|
|
from PySide6.QtPdfWidgets import QPdfView
|
|
from PySide6.QtWidgets import QComboBox, QDialog, QMenuBar, QSpinBox, QWidget
|
|
|
|
from lib.utils import readGeometry, writeGeometry
|
|
from ui.pdfViewer import Ui_pdfViewer
|
|
|
|
ZOOM_MULTIPLIER = math.sqrt(2.0)
|
|
|
|
|
|
class ZoomSelector(QComboBox):
|
|
zoom_mode_changed = Signal(QPdfView.ZoomMode)
|
|
zoom_factor_changed = Signal(float)
|
|
|
|
def __init__(self, parent: QWidget | None = None) -> None:
|
|
super(ZoomSelector, self).__init__(parent)
|
|
self.setEditable(True)
|
|
|
|
for text in [
|
|
"Fit Width",
|
|
"Fit Page",
|
|
"12%",
|
|
"25%",
|
|
"33%",
|
|
"50%",
|
|
"66%",
|
|
"75%",
|
|
"100%",
|
|
"125%",
|
|
"150%",
|
|
"200%",
|
|
"400%",
|
|
]:
|
|
self.addItem(text)
|
|
self.currentTextChanged.connect(self.on_current_text_changed)
|
|
lineEdit = self.lineEdit()
|
|
assert lineEdit is not None
|
|
lineEdit.editingFinished.connect(self._editing_finished)
|
|
return
|
|
|
|
@Slot(float) # type: ignore
|
|
def set_zoom_factor(self, zoomFactor: float) -> None:
|
|
percent = int(zoomFactor * 100)
|
|
self.setCurrentText(f"{percent}%")
|
|
return
|
|
|
|
@Slot()
|
|
def reset(self) -> None:
|
|
self.setCurrentIndex(8) # 100%
|
|
return
|
|
|
|
@Slot(str) # type: ignore
|
|
def on_current_text_changed(self, text: str) -> None:
|
|
if text == "Fit Width":
|
|
self.zoom_mode_changed.emit(QPdfView.ZoomMode.FitToWidth)
|
|
elif text == "Fit Page":
|
|
self.zoom_mode_changed.emit(QPdfView.ZoomMode.FitInView)
|
|
elif text.endswith("%"):
|
|
zoom_level = int(text[:-1])
|
|
factor = zoom_level / 100.0
|
|
self.zoom_mode_changed.emit(QPdfView.ZoomMode.Custom)
|
|
self.zoom_factor_changed.emit(factor)
|
|
return
|
|
|
|
@Slot()
|
|
def _editing_finished(self) -> None:
|
|
lineEdit = self.lineEdit()
|
|
assert lineEdit is not None
|
|
self.on_current_text_changed(lineEdit.text())
|
|
return
|
|
|
|
|
|
class PDFViewer(QDialog, Ui_pdfViewer):
|
|
menubar: QMenuBar
|
|
zoomSelector: ZoomSelector
|
|
pageSelector: QSpinBox
|
|
document: QPdfDocument
|
|
|
|
def __init__(self, parent: QWidget | None) -> None:
|
|
super(PDFViewer, self).__init__(parent)
|
|
self.setupUi(self)
|
|
self.setObjectName("PDFViewer")
|
|
readGeometry(self)
|
|
print(self.objectName())
|
|
self.zoomSelector = ZoomSelector(self)
|
|
self.pageSelector = QSpinBox(self)
|
|
self.document = QPdfDocument(self)
|
|
|
|
self.zoomSelector.setMaximumWidth(150)
|
|
self.mainToolBar.insertWidget(self.actionZoom_In, self.zoomSelector)
|
|
self.mainToolBar.insertWidget(self.actionNext_Page, self.pageSelector)
|
|
self.pageSelector.valueChanged.connect(self.page_selected)
|
|
nav = self.pdfView.pageNavigator()
|
|
nav.currentPageChanged.connect(self.pageSelector.setValue)
|
|
nav.backAvailableChanged.connect(self.actionBack.setEnabled)
|
|
nav.forwardAvailableChanged.connect(self.actionForward.setEnabled)
|
|
self.zoomSelector.zoom_mode_changed.connect(self.pdfView.setZoomMode)
|
|
self.zoomSelector.zoom_factor_changed.connect(
|
|
self.pdfView.setZoomFactor
|
|
)
|
|
self.zoomSelector.reset()
|
|
|
|
bookmark_model = QPdfBookmarkModel(self)
|
|
bookmark_model.setDocument(self.document)
|
|
|
|
self.bookmarkView.setModel(bookmark_model)
|
|
self.bookmarkView.activated.connect(self.bookmark_selected)
|
|
|
|
self.tabWidget.setTabEnabled(1, False) # disable pages tabwidget
|
|
self.pdfView.setDocument(self.document)
|
|
self.pdfView.zoomFactorChanged.connect(
|
|
self.zoomSelector.set_zoom_factor
|
|
)
|
|
return
|
|
|
|
def closeEvent(self, event: QCloseEvent) -> None:
|
|
print("closeEvent")
|
|
writeGeometry(self)
|
|
super().closeEvent(event)
|
|
return
|
|
|
|
@Slot(QFile) # type: ignore
|
|
def open(self, file: QFile) -> None:
|
|
self.document.load(file.fileName())
|
|
document_title = self.document.metaData(
|
|
QPdfDocument.MetaDataField.Title
|
|
)
|
|
self.setWindowTitle(document_title if document_title else "PDF Viewer")
|
|
self.page_selected(0)
|
|
self.pageSelector.setMaximum(self.document.pageCount() - 1)
|
|
if self.zoomSelector.currentIndex() == 8:
|
|
pageSize = self.document.pagePointSize(0)
|
|
dpi = QGuiApplication.primaryScreen().physicalDotsPerInch()
|
|
size = QSize(int(pageSize.width()/72*dpi),self.pdfView.height())
|
|
self.pdfView.resize(size)
|
|
self.splitter.setSizes([100, size.width()])
|
|
return
|
|
|
|
@Slot(QModelIndex) # type: ignore
|
|
def bookmark_selected(self, index: QModelIndex) -> None:
|
|
if not index.isValid():
|
|
return
|
|
|
|
page = index.data(int(QPdfBookmarkModel.Role.Page))
|
|
zoom_level = index.data(int(QPdfBookmarkModel.Role.Level))
|
|
nav = self.pdfView.pageNavigator()
|
|
assert nav is not None
|
|
nav.jump(page, QPoint(), zoom_level)
|
|
return
|
|
|
|
@Slot(int) # type: ignore
|
|
def page_selected(self, page: int) -> None:
|
|
nav = self.pdfView.pageNavigator()
|
|
nav.jump(page, QPoint(), nav.currentZoom())
|
|
return
|
|
|
|
@Slot()
|
|
def on_actionOpen_triggered(self) -> None:
|
|
print("What are you doing in actionOpen_triggered?")
|
|
return
|
|
|
|
@Slot()
|
|
def on_actionQuit_triggered(self) -> None:
|
|
self.close()
|
|
return
|
|
|
|
@Slot()
|
|
def on_actionZoom_In_triggered(self) -> None:
|
|
factor = self.pdfView.zoomFactor() * ZOOM_MULTIPLIER
|
|
self.pdfView.setZoomFactor(factor)
|
|
return
|
|
|
|
@Slot()
|
|
def on_actionZoom_Out_triggered(self) -> None:
|
|
factor = self.pdfView.zoomFactor() / ZOOM_MULTIPLIER
|
|
self.pdfView.setZoomFactor(factor)
|
|
return
|
|
|
|
@Slot()
|
|
def on_actionPrevious_Page_triggered(self) -> None:
|
|
nav = self.pdfView.pageNavigator()
|
|
nav.jump(nav.currentPage() - 1, QPoint(), nav.currentZoom())
|
|
return
|
|
|
|
@Slot()
|
|
def on_actionNext_Page_triggered(self) -> None:
|
|
nav = self.pdfView.pageNavigator()
|
|
nav.jump(nav.currentPage() + 1, QPoint(), nav.currentZoom())
|
|
return
|
|
|
|
@Slot()
|
|
def on_actionContinuous_triggered(self) -> None:
|
|
cont_checked = self.actionContinuous.isChecked()
|
|
mode = (
|
|
QPdfView.PageMode.MultiPage
|
|
if cont_checked
|
|
else QPdfView.PageMode.SinglePage
|
|
)
|
|
self.pdfView.setPageMode(mode)
|
|
return
|
|
|
|
@Slot()
|
|
def on_actionBack_triggered(self) -> None:
|
|
self.pdfView.pageNavigator().back()
|
|
return
|
|
|
|
@Slot()
|
|
def on_actionForward_triggered(self) -> None:
|
|
self.pdfView.pageNavigator().forward()
|
|
return
|