Files
scotus-watch/pdfView.py
Christopher T. Johnson eaaa00890e Lint
2025-02-20 10:14:42 -05:00

203 lines
6.3 KiB
Python

import math
from PySide6.QtCore import QFile, QModelIndex, QPoint, Signal, Slot
from PySide6.QtPdf import QPdfBookmarkModel, QPdfDocument
from PySide6.QtPdfWidgets import QPdfView
from PySide6.QtWidgets import QComboBox, QDialog, QMenuBar, QSpinBox, QWidget
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.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.actionForward, 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
@Slot(QFile) # type: ignore
def open(self, file: QFile) -> None:
# assert file.exists()
# if not file.isOpen():
# file.open(QFile.OpenModeFlag.ReadOnly)
# self.document.load(file)
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)
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