src/eric7/PdfViewer/PdfView.py

branch
pdf_viewer
changeset 9704
6e1650b9b3b5
child 9707
717f95e35ca8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/PdfViewer/PdfView.py	Wed Jan 18 14:31:55 2023 +0100
@@ -0,0 +1,195 @@
+# -*- 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