src/eric7/PdfViewer/PdfPageSelector.py

Sun, 15 Jan 2023 17:41:35 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sun, 15 Jan 2023 17:41:35 +0100
branch
pdf_viewer
changeset 9700
b74a13a382a8
parent 9699
92dcd34d54e4
child 9722
63135ab601e7
permissions
-rw-r--r--

PDF Viewer
- finished 'Zoom' functions

# -*- 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, QSizePolicy
)

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.setMaximumWidth(50)
        self.__pageEntry.setMaxLength(10)
        self.__pageEntry.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.__pageEntry.setSizePolicy(
            QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Fixed
        )
        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