src/eric7/PdfViewer/PdfView.py

Wed, 18 Jan 2023 14:31:55 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Wed, 18 Jan 2023 14:31:55 +0100
branch
pdf_viewer
changeset 9704
6e1650b9b3b5
child 9707
717f95e35ca8
permissions
-rw-r--r--

PDF Viewer
- created a specialized PDF view class to intercept and handle certain events
- added a 'Search' widget

# -*- coding: utf-8 -*-

# Copyright (c) 2023 Detlev Offenbach <detlev@die-offenbachs.de>
#

"""
Module implementing a specialized PDF view class.
"""

from PyQt6.QtCore import QSize, Qt, pyqtSlot, QEvent
from PyQt6.QtGui import QGuiApplication
from PyQt6.QtPdfWidgets import QPdfView

from .PdfZoomSelector import PdfZoomSelector


class PdfView(QPdfView):
    """
    Class implementing a specialized PDF view.
    """

    def __init__(self, parent):
        """
        Constructor

        @param parent reference to the parent widget
        @type QWidget
        """
        super().__init__(parent)

        self.__screenResolution = (
            QGuiApplication.primaryScreen().logicalDotsPerInch() / 72.0
        )

        self.grabGesture(Qt.GestureType.PinchGesture)

    def __zoomInOut(self, zoomIn):
        """
        Private method to zoom into or out of the view.

        @param zoomIn flag indicating to zoom into the view
        @type bool
        """
        zoomFactor = self.__zoomFactorForMode(self.zoomMode())

        factors = list(PdfZoomSelector.ZoomValues)
        factors.append(self.__zoomFactorForMode(QPdfView.ZoomMode.FitInView))
        factors.append(self.__zoomFactorForMode(QPdfView.ZoomMode.FitToWidth))
        if zoomIn:
            factors.sort()
            if zoomFactor >= factors[-1]:
                return
            newIndex = next(x for x, val in enumerate(factors) if val > zoomFactor)
        else:
            factors.sort(reverse=True)
            if zoomFactor <= factors[-1]:
                return
            newIndex = next(x for x, val in enumerate(factors) if val < zoomFactor)
        newFactor = factors[newIndex]
        if newFactor == self.__zoomFactorForMode(QPdfView.ZoomMode.FitInView):
            self.setZoomMode(QPdfView.ZoomMode.FitInView)
            self.zoomModeChanged.emit(QPdfView.ZoomMode.FitInView)
        elif newFactor == self.__zoomFactorForMode(QPdfView.ZoomMode.FitToWidth):
            self.setZoomMode(QPdfView.ZoomMode.FitToWidth)
            self.zoomModeChanged.emit(QPdfView.ZoomMode.FitToWidth)
        else:
            self.setZoomFactor(newFactor)
            self.zoomFactorChanged.emit(newFactor)
            self.setZoomMode(QPdfView.ZoomMode.Custom)
            self.zoomModeChanged.emit(QPdfView.ZoomMode.Custom)

    def __zoomFactorForMode(self, zoomMode):
        """
        Private method to calculate the zoom factor iaw. the current zoom mode.

        @param zoomMode zoom mode to get the zoom factor for
        @type QPdfView.ZoomMode
        @return zoom factor
        @rtype float
        """
        if zoomMode == QPdfView.ZoomMode.Custom:
            return self.zoomFactor()
        else:
            viewport = self.viewport()
            curPage = self.pageNavigator().currentPage()
            margins = self.documentMargins()
            if zoomMode == QPdfView.ZoomMode.FitToWidth:
                pageSize = (
                    self.document().pagePointSize(curPage) * self.__screenResolution
                ).toSize()
                factor = (
                    viewport.width() - margins.left() - margins.right()
                ) / pageSize.width()
                pageSize *= factor
            else:
                # QPdfView.ZoomMode.FitInView
                viewportSize = viewport.size() + QSize(
                    -margins.left() - margins.right(), -self.pageSpacing()
                )
                pageSize = (
                    self.document().pagePointSize(curPage) * self.__screenResolution
                ).toSize()
                pageSize = pageSize.scaled(
                    viewportSize, Qt.AspectRatioMode.KeepAspectRatio
                )
            zoomFactor = pageSize.width() / (
                self.document().pagePointSize(curPage) * self.__screenResolution
            ).width()
            return zoomFactor

    @pyqtSlot()
    def zoomIn(self):
        """
        Public slot to zoom into the view.
        """
        self.__zoomInOut(True)

    @pyqtSlot()
    def zoomOut(self):
        """
        Public slot to zoom out of the view.
        """
        self.__zoomInOut(False)

    @pyqtSlot()
    def zoomReset(self):
        """
        Public slot to reset the zoom factor of the view.
        """
        if self.zoomMode() != QPdfView.ZoomMode.Custom or self.zoomFactor() != 1.0:
            self.setZoomFactor(1.0)
            self.zoomFactorChanged.emit(1.0)
            self.setZoomMode(QPdfView.ZoomMode.Custom)
            self.zoomModeChanged.emit(QPdfView.ZoomMode.Custom)

    def wheelEvent(self, evt):
        """
        Protected method to handle wheel events.

        @param evt reference to the wheel event
        @type QWheelEvent
        """
        delta = evt.angleDelta().y()
        if evt.modifiers() & Qt.KeyboardModifier.ControlModifier:
            if delta < 0:
                self.zoomOut()
            elif delta > 0:
                self.zoomIn()
            evt.accept()
            return

        elif evt.modifiers() & Qt.KeyboardModifier.ShiftModifier:
            if delta < 0:
                self.pageNavigator().back()
            elif delta > 0:
                self.pageNavigator().forward()
            evt.accept()
            return

        super().wheelEvent(evt)

    def event(self, evt):
        """
        Public method handling events.

        @param evt reference to the event
        @type QEvent
        @return flag indicating, if the event was handled
        @rtype bool
        """
        if evt.type() == QEvent.Type.Gesture:
            self.gestureEvent(evt)
            return True

        return super().event(evt)

    def gestureEvent(self, evt):
        """
        Protected method handling gesture events.

        @param evt reference to the gesture event
        @type QGestureEvent
        """
        pinch = evt.gesture(Qt.GestureType.PinchGesture)
        if pinch:
            if pinch.state() == Qt.GestureState.GestureStarted:
                pinch.setTotalScaleFactor(self.__zoomFactorForMode(self.zoomMode()))
            elif pinch.state() == Qt.GestureState.GestureUpdated:
                if self.zoomMode() != QPdfView.ZoomMode.Custom:
                    self.setZoomMode(QPdfView.ZoomMode.Custom)
                    self.zoomModeChanged.emit(QPdfView.ZoomMode.Custom)
                zoomFactor = pinch.totalScaleFactor()
                self.setZoomFactor(zoomFactor)
                self.zoomFactorChanged.emit(zoomFactor)
            evt.accept()

eric ide

mercurial