src/eric7/PdfViewer/PdfPageSelector.py

branch
pdf_viewer
changeset 9698
69e183e4db6f
child 9699
92dcd34d54e4
equal deleted inserted replaced
9697:cdaa3cc805f7 9698:69e183e4db6f
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2023 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a widget to select a PDF page to be shown.
8 """
9
10 import contextlib
11
12 from PyQt6.QtCore import Qt, pyqtSlot, pyqtSignal
13 from PyQt6.QtGui import QIntValidator
14 from PyQt6.QtPdf import QPdfDocument
15 from PyQt6.QtWidgets import (
16 QToolButton, QHBoxLayout, QWidget, QLabel, QLineEdit
17 )
18
19 from eric7.EricGui import EricPixmapCache
20
21
22 class PdfPageSelector(QWidget):
23 """
24 Class implementing a widget to select a PDF page to be shown.
25 """
26
27 valueChanged = pyqtSignal(int)
28 gotoPage = pyqtSignal()
29
30 def __init__(self, parent=None):
31 """
32 Constructor
33
34 @param parent reference to the parent widget (defaults to None)
35 @type QWidget (optional)
36 """
37 super().__init__(parent)
38
39 self.__document = None
40
41 self.__prevButton = QToolButton(self)
42 self.__prevButton.setIcon(EricPixmapCache.getIcon("1uparrow"))
43
44 self.__nextButton = QToolButton(self)
45 self.__nextButton.setIcon(EricPixmapCache.getIcon("1downarrow"))
46
47 self.__pageButton = QToolButton()
48 self.__pageButton.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextOnly)
49
50 self.__pageEntry = QLineEdit()
51 self.__pageEntry.setMaxLength(10)
52 self.__pageEntry.setAlignment(Qt.AlignmentFlag.AlignCenter)
53 self.__pageLabel = QLabel()
54
55 self.__layout = QHBoxLayout()
56 self.__layout.addWidget(self.__prevButton)
57 self.__layout.addWidget(self.__pageEntry)
58 self.__layout.addWidget(self.__pageLabel)
59 self.__layout.addWidget(QLabel(self.tr("of")))
60 self.__layout.addWidget(self.__pageButton)
61 self.__layout.addWidget(self.__nextButton)
62
63 self.setLayout(self.__layout)
64
65 # Setup signal/slot connections
66 self.__prevButton.clicked.connect(self.__decrement)
67 self.__nextButton.clicked.connect(self.__increment)
68 self.__pageButton.clicked.connect(self.__pageButtonTriggered)
69 self.__pageEntry.editingFinished.connect(self.__pageEntered)
70
71 self.__initialize()
72
73 def __initialize(self):
74 """
75 Private method to initialize some internal state.
76 """
77 self.__value = -1
78 self.__minimum = 0
79 self.__maximum = 0
80
81 self.__prevButton.setEnabled(False)
82 self.__nextButton.setEnabled(False)
83 self.__pageEntry.clear()
84 self.__pageLabel.clear()
85 self.__pageButton.setText(" ")
86
87 self.setEnabled(False)
88
89 def setDocument(self, document):
90 """
91 Public method to set a reference to the associated PDF document.
92
93 @param document reference to the associated PDF document
94 @type QPdfDocument
95 """
96 self.__document = document
97 self.__document.statusChanged.connect(self.__documentStatusChanged)
98
99 @pyqtSlot(int)
100 def setValue(self, value):
101 """
102 Public slot to set the value.
103
104 Note: value is 0 based.
105
106 @param value value to be set
107 @type int
108 """
109 if value != self.__value:
110 with contextlib.suppress(RuntimeError):
111 self.__pageEntry.setText(self.__document.pageLabel(value))
112 self.__pageLabel.setText(str(value + 1))
113
114 self.__value = value
115
116 self.__prevButton.setEnabled(value > self.__minimum)
117 self.__nextButton.setEnabled(value < self.__maximum)
118
119 self.valueChanged.emit(value)
120
121 def value(self):
122 """
123 Public method to get the current value.
124
125 @return current value
126 @rtype int
127 """
128 return self.__value
129
130 def setMaximum(self, max):
131 """
132 Public method to set the maximum value.
133
134 Note: max is 0 based.
135
136 @param max maximum value to be set
137 @type int
138 """
139 self.__maximum = max
140 self.__nextButton.setEnabled(self.__value < self.__maximum)
141 self.__pageButton.setText(str(max + 1))
142
143 @pyqtSlot()
144 def __pageEntered(self):
145 """
146 Private slot to handle the entering of a page value.
147 """
148 model = self.__document.pageModel()
149 start = model.index(0)
150 indices = model.match(
151 start, QPdfDocument.PageModelRole.Label.value, self.__pageEntry.text()
152 )
153 if indices:
154 self.setValue(indices[0].row())
155 else:
156 # reset
157 blocked = self.__pageEntry.blockSignals(True)
158 self.__pageEntry.setText(self.__document.pageLabel(self.__value))
159 self.__pageEntry.blockSignals(blocked)
160
161 @pyqtSlot()
162 def __decrement(self):
163 """
164 Private slot to decrement the current value.
165 """
166 if self.__value > self.__minimum:
167 self.setValue(self.__value - 1)
168
169 @pyqtSlot()
170 def __increment(self):
171 """
172 Private slot to increment the current value.
173 """
174 if self.__value < self.__maximum:
175 self.setValue(self.__value + 1)
176
177 @pyqtSlot()
178 def __pageButtonTriggered(self):
179 """
180 Private slot to handle the page button trigger.
181 """
182 self.gotoPage.emit()
183
184 @pyqtSlot(QPdfDocument.Status)
185 def __documentStatusChanged(self, status):
186 """
187 Private slot to handle a change of the document status.
188
189 @param status current document status
190 @type QPdfDocument.Status
191 """
192 self.setEnabled(status == QPdfDocument.Status.Ready)
193 if status == QPdfDocument.Status.Ready:
194 numericalEntry = True
195 # test the first page
196 try:
197 _ = int(self.__document.pageLabel(0))
198 except ValueError:
199 numericalEntry = False
200 # test the last page
201 try:
202 _ = int(self.__document.pageLabel(self.__document.pageCount() - 1))
203 except ValueError:
204 numericalEntry = False
205 self.__pageEntry.setValidator(
206 QIntValidator(1, 99999) if numericalEntry else None
207 )
208 self.__pageLabel.setVisible(not numericalEntry)
209 elif status == QPdfDocument.Status.Null:
210 self.__initialize()

eric ide

mercurial