|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2023 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing a specialized PDF view class. |
|
8 """ |
|
9 |
|
10 from PyQt6.QtCore import QSize, Qt, pyqtSlot, QEvent |
|
11 from PyQt6.QtGui import QGuiApplication |
|
12 from PyQt6.QtPdfWidgets import QPdfView |
|
13 |
|
14 from .PdfZoomSelector import PdfZoomSelector |
|
15 |
|
16 |
|
17 class PdfView(QPdfView): |
|
18 """ |
|
19 Class implementing a specialized PDF view. |
|
20 """ |
|
21 |
|
22 def __init__(self, parent): |
|
23 """ |
|
24 Constructor |
|
25 |
|
26 @param parent reference to the parent widget |
|
27 @type QWidget |
|
28 """ |
|
29 super().__init__(parent) |
|
30 |
|
31 self.__screenResolution = ( |
|
32 QGuiApplication.primaryScreen().logicalDotsPerInch() / 72.0 |
|
33 ) |
|
34 |
|
35 self.grabGesture(Qt.GestureType.PinchGesture) |
|
36 |
|
37 def __zoomInOut(self, zoomIn): |
|
38 """ |
|
39 Private method to zoom into or out of the view. |
|
40 |
|
41 @param zoomIn flag indicating to zoom into the view |
|
42 @type bool |
|
43 """ |
|
44 zoomFactor = self.__zoomFactorForMode(self.zoomMode()) |
|
45 |
|
46 factors = list(PdfZoomSelector.ZoomValues) |
|
47 factors.append(self.__zoomFactorForMode(QPdfView.ZoomMode.FitInView)) |
|
48 factors.append(self.__zoomFactorForMode(QPdfView.ZoomMode.FitToWidth)) |
|
49 if zoomIn: |
|
50 factors.sort() |
|
51 if zoomFactor >= factors[-1]: |
|
52 return |
|
53 newIndex = next(x for x, val in enumerate(factors) if val > zoomFactor) |
|
54 else: |
|
55 factors.sort(reverse=True) |
|
56 if zoomFactor <= factors[-1]: |
|
57 return |
|
58 newIndex = next(x for x, val in enumerate(factors) if val < zoomFactor) |
|
59 newFactor = factors[newIndex] |
|
60 if newFactor == self.__zoomFactorForMode(QPdfView.ZoomMode.FitInView): |
|
61 self.setZoomMode(QPdfView.ZoomMode.FitInView) |
|
62 self.zoomModeChanged.emit(QPdfView.ZoomMode.FitInView) |
|
63 elif newFactor == self.__zoomFactorForMode(QPdfView.ZoomMode.FitToWidth): |
|
64 self.setZoomMode(QPdfView.ZoomMode.FitToWidth) |
|
65 self.zoomModeChanged.emit(QPdfView.ZoomMode.FitToWidth) |
|
66 else: |
|
67 self.setZoomFactor(newFactor) |
|
68 self.zoomFactorChanged.emit(newFactor) |
|
69 self.setZoomMode(QPdfView.ZoomMode.Custom) |
|
70 self.zoomModeChanged.emit(QPdfView.ZoomMode.Custom) |
|
71 |
|
72 def __zoomFactorForMode(self, zoomMode): |
|
73 """ |
|
74 Private method to calculate the zoom factor iaw. the current zoom mode. |
|
75 |
|
76 @param zoomMode zoom mode to get the zoom factor for |
|
77 @type QPdfView.ZoomMode |
|
78 @return zoom factor |
|
79 @rtype float |
|
80 """ |
|
81 if zoomMode == QPdfView.ZoomMode.Custom: |
|
82 return self.zoomFactor() |
|
83 else: |
|
84 viewport = self.viewport() |
|
85 curPage = self.pageNavigator().currentPage() |
|
86 margins = self.documentMargins() |
|
87 if zoomMode == QPdfView.ZoomMode.FitToWidth: |
|
88 pageSize = ( |
|
89 self.document().pagePointSize(curPage) * self.__screenResolution |
|
90 ).toSize() |
|
91 factor = ( |
|
92 viewport.width() - margins.left() - margins.right() |
|
93 ) / pageSize.width() |
|
94 pageSize *= factor |
|
95 else: |
|
96 # QPdfView.ZoomMode.FitInView |
|
97 viewportSize = viewport.size() + QSize( |
|
98 -margins.left() - margins.right(), -self.pageSpacing() |
|
99 ) |
|
100 pageSize = ( |
|
101 self.document().pagePointSize(curPage) * self.__screenResolution |
|
102 ).toSize() |
|
103 pageSize = pageSize.scaled( |
|
104 viewportSize, Qt.AspectRatioMode.KeepAspectRatio |
|
105 ) |
|
106 zoomFactor = pageSize.width() / ( |
|
107 self.document().pagePointSize(curPage) * self.__screenResolution |
|
108 ).width() |
|
109 return zoomFactor |
|
110 |
|
111 @pyqtSlot() |
|
112 def zoomIn(self): |
|
113 """ |
|
114 Public slot to zoom into the view. |
|
115 """ |
|
116 self.__zoomInOut(True) |
|
117 |
|
118 @pyqtSlot() |
|
119 def zoomOut(self): |
|
120 """ |
|
121 Public slot to zoom out of the view. |
|
122 """ |
|
123 self.__zoomInOut(False) |
|
124 |
|
125 @pyqtSlot() |
|
126 def zoomReset(self): |
|
127 """ |
|
128 Public slot to reset the zoom factor of the view. |
|
129 """ |
|
130 if self.zoomMode() != QPdfView.ZoomMode.Custom or self.zoomFactor() != 1.0: |
|
131 self.setZoomFactor(1.0) |
|
132 self.zoomFactorChanged.emit(1.0) |
|
133 self.setZoomMode(QPdfView.ZoomMode.Custom) |
|
134 self.zoomModeChanged.emit(QPdfView.ZoomMode.Custom) |
|
135 |
|
136 def wheelEvent(self, evt): |
|
137 """ |
|
138 Protected method to handle wheel events. |
|
139 |
|
140 @param evt reference to the wheel event |
|
141 @type QWheelEvent |
|
142 """ |
|
143 delta = evt.angleDelta().y() |
|
144 if evt.modifiers() & Qt.KeyboardModifier.ControlModifier: |
|
145 if delta < 0: |
|
146 self.zoomOut() |
|
147 elif delta > 0: |
|
148 self.zoomIn() |
|
149 evt.accept() |
|
150 return |
|
151 |
|
152 elif evt.modifiers() & Qt.KeyboardModifier.ShiftModifier: |
|
153 if delta < 0: |
|
154 self.pageNavigator().back() |
|
155 elif delta > 0: |
|
156 self.pageNavigator().forward() |
|
157 evt.accept() |
|
158 return |
|
159 |
|
160 super().wheelEvent(evt) |
|
161 |
|
162 def event(self, evt): |
|
163 """ |
|
164 Public method handling events. |
|
165 |
|
166 @param evt reference to the event |
|
167 @type QEvent |
|
168 @return flag indicating, if the event was handled |
|
169 @rtype bool |
|
170 """ |
|
171 if evt.type() == QEvent.Type.Gesture: |
|
172 self.gestureEvent(evt) |
|
173 return True |
|
174 |
|
175 return super().event(evt) |
|
176 |
|
177 def gestureEvent(self, evt): |
|
178 """ |
|
179 Protected method handling gesture events. |
|
180 |
|
181 @param evt reference to the gesture event |
|
182 @type QGestureEvent |
|
183 """ |
|
184 pinch = evt.gesture(Qt.GestureType.PinchGesture) |
|
185 if pinch: |
|
186 if pinch.state() == Qt.GestureState.GestureStarted: |
|
187 pinch.setTotalScaleFactor(self.__zoomFactorForMode(self.zoomMode())) |
|
188 elif pinch.state() == Qt.GestureState.GestureUpdated: |
|
189 if self.zoomMode() != QPdfView.ZoomMode.Custom: |
|
190 self.setZoomMode(QPdfView.ZoomMode.Custom) |
|
191 self.zoomModeChanged.emit(QPdfView.ZoomMode.Custom) |
|
192 zoomFactor = pinch.totalScaleFactor() |
|
193 self.setZoomFactor(zoomFactor) |
|
194 self.zoomFactorChanged.emit(zoomFactor) |
|
195 evt.accept() |