src/eric7/PdfViewer/PdfPageSelector.py

branch
pdf_viewer
changeset 9698
69e183e4db6f
child 9699
92dcd34d54e4
diff -r cdaa3cc805f7 -r 69e183e4db6f src/eric7/PdfViewer/PdfPageSelector.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/PdfViewer/PdfPageSelector.py	Fri Jan 13 18:20:54 2023 +0100
@@ -0,0 +1,210 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2023 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a widget to select a PDF page to be shown.
+"""
+
+import contextlib
+
+from PyQt6.QtCore import Qt, pyqtSlot, pyqtSignal
+from PyQt6.QtGui import QIntValidator
+from PyQt6.QtPdf import QPdfDocument
+from PyQt6.QtWidgets import (
+    QToolButton, QHBoxLayout, QWidget, QLabel, QLineEdit
+)
+
+from eric7.EricGui import EricPixmapCache
+
+
+class PdfPageSelector(QWidget):
+    """
+    Class implementing a widget to select a PDF page to be shown.
+    """
+
+    valueChanged = pyqtSignal(int)
+    gotoPage = pyqtSignal()
+
+    def __init__(self, parent=None):
+        """
+        Constructor
+
+        @param parent reference to the parent widget (defaults to None)
+        @type QWidget (optional)
+        """
+        super().__init__(parent)
+
+        self.__document = None
+
+        self.__prevButton = QToolButton(self)
+        self.__prevButton.setIcon(EricPixmapCache.getIcon("1uparrow"))
+
+        self.__nextButton = QToolButton(self)
+        self.__nextButton.setIcon(EricPixmapCache.getIcon("1downarrow"))
+
+        self.__pageButton = QToolButton()
+        self.__pageButton.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextOnly)
+
+        self.__pageEntry = QLineEdit()
+        self.__pageEntry.setMaxLength(10)
+        self.__pageEntry.setAlignment(Qt.AlignmentFlag.AlignCenter)
+        self.__pageLabel = QLabel()
+        
+        self.__layout = QHBoxLayout()
+        self.__layout.addWidget(self.__prevButton)
+        self.__layout.addWidget(self.__pageEntry)
+        self.__layout.addWidget(self.__pageLabel)
+        self.__layout.addWidget(QLabel(self.tr("of")))
+        self.__layout.addWidget(self.__pageButton)
+        self.__layout.addWidget(self.__nextButton)
+
+        self.setLayout(self.__layout)
+
+        # Setup signal/slot connections
+        self.__prevButton.clicked.connect(self.__decrement)
+        self.__nextButton.clicked.connect(self.__increment)
+        self.__pageButton.clicked.connect(self.__pageButtonTriggered)
+        self.__pageEntry.editingFinished.connect(self.__pageEntered)
+
+        self.__initialize()
+
+    def __initialize(self):
+        """
+        Private method to initialize some internal state.
+        """
+        self.__value = -1
+        self.__minimum = 0
+        self.__maximum = 0
+
+        self.__prevButton.setEnabled(False)
+        self.__nextButton.setEnabled(False)
+        self.__pageEntry.clear()
+        self.__pageLabel.clear()
+        self.__pageButton.setText(" ")
+
+        self.setEnabled(False)
+
+    def setDocument(self, document):
+        """
+        Public method to set a reference to the associated PDF document.
+
+        @param document reference to the associated PDF document
+        @type QPdfDocument
+        """
+        self.__document = document
+        self.__document.statusChanged.connect(self.__documentStatusChanged)
+
+    @pyqtSlot(int)
+    def setValue(self, value):
+        """
+        Public slot to set the value.
+
+        Note: value is 0 based.
+
+        @param value value to be set
+        @type int
+        """
+        if value != self.__value:
+            with contextlib.suppress(RuntimeError):
+                self.__pageEntry.setText(self.__document.pageLabel(value))
+            self.__pageLabel.setText(str(value + 1))
+
+            self.__value = value
+
+            self.__prevButton.setEnabled(value > self.__minimum)
+            self.__nextButton.setEnabled(value < self.__maximum)
+
+            self.valueChanged.emit(value)
+
+    def value(self):
+        """
+        Public method to get the current value.
+
+        @return current value
+        @rtype int
+        """
+        return self.__value
+
+    def setMaximum(self, max):
+        """
+        Public method to set the maximum value.
+
+        Note: max is 0 based.
+
+        @param max maximum value to be set
+        @type int
+        """
+        self.__maximum = max
+        self.__nextButton.setEnabled(self.__value < self.__maximum)
+        self.__pageButton.setText(str(max + 1))
+
+    @pyqtSlot()
+    def __pageEntered(self):
+        """
+        Private slot to handle the entering of a page value.
+        """
+        model = self.__document.pageModel()
+        start = model.index(0)
+        indices = model.match(
+            start, QPdfDocument.PageModelRole.Label.value, self.__pageEntry.text()
+        )
+        if indices:
+            self.setValue(indices[0].row())
+        else:
+            # reset
+            blocked = self.__pageEntry.blockSignals(True)
+            self.__pageEntry.setText(self.__document.pageLabel(self.__value))
+            self.__pageEntry.blockSignals(blocked)
+
+    @pyqtSlot()
+    def __decrement(self):
+        """
+        Private slot to decrement the current value.
+        """
+        if self.__value > self.__minimum:
+            self.setValue(self.__value - 1)
+
+    @pyqtSlot()
+    def __increment(self):
+        """
+        Private slot to increment the current value.
+        """
+        if self.__value < self.__maximum:
+            self.setValue(self.__value + 1)
+
+    @pyqtSlot()
+    def __pageButtonTriggered(self):
+        """
+        Private slot to handle the page button trigger.
+        """
+        self.gotoPage.emit()
+
+    @pyqtSlot(QPdfDocument.Status)
+    def __documentStatusChanged(self, status):
+        """
+        Private slot to handle a change of the document status.
+
+        @param status current document status
+        @type QPdfDocument.Status
+        """
+        self.setEnabled(status == QPdfDocument.Status.Ready)
+        if status == QPdfDocument.Status.Ready:
+            numericalEntry = True
+            # test the first page
+            try:
+                _ = int(self.__document.pageLabel(0))
+            except ValueError:
+                numericalEntry = False
+            # test the last page
+            try:
+                _ = int(self.__document.pageLabel(self.__document.pageCount() - 1))
+            except ValueError:
+                numericalEntry = False
+            self.__pageEntry.setValidator(
+                QIntValidator(1, 99999) if numericalEntry else None
+            )
+            self.__pageLabel.setVisible(not numericalEntry)
+        elif status == QPdfDocument.Status.Null:
+            self.__initialize()

eric ide

mercurial