src/eric7/PdfViewer/PdfToCWidget.py

branch
pdf_viewer
changeset 9702
7c973954919d
child 9704
6e1650b9b3b5
equal deleted inserted replaced
9700:b74a13a382a8 9702:7c973954919d
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2023 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a Table of Contents viewer widget.
8 """
9
10 from PyQt6.QtCore import pyqtSignal, pyqtSlot, Qt, QModelIndex, QSortFilterProxyModel
11 from PyQt6.QtPdf import QPdfBookmarkModel, QPdfDocument
12 from PyQt6.QtWidgets import QWidget, QVBoxLayout, QLabel, QTreeView, QLineEdit
13
14
15 class PdfToCModel(QPdfBookmarkModel):
16 """
17 Class implementing a TOC model with page numbers.
18 """
19
20 def __init__(self, parent):
21 """
22 Constructor
23
24 @param parent DESCRIPTION
25 @type TYPE
26 """
27 super().__init__(parent)
28
29 def columnCount(self, index):
30 """
31 Public method to define the number of columns to be shown.
32
33 @param index index of the element
34 @type QModelIndex
35 @return column count (always 2)
36 @rtype int
37 """
38 return 2
39
40 def data(self, index, role):
41 """
42 Public method to return the requested data.
43
44 @param index index of the element
45 @type QModelIndex
46 @param role data role
47 @type Qt.ItemDataRole
48 @return requested data
49 @rtype Any
50 """
51 if not index.isValid():
52 return
53
54 if index.column() == 1:
55 if role == Qt.ItemDataRole.DisplayRole:
56 page = index.data(QPdfBookmarkModel.Role.Page.value)
57 return self.document().pageLabel(page)
58 elif role == Qt.ItemDataRole.TextAlignmentRole:
59 return Qt.AlignmentFlag.AlignRight
60
61 return super().data(index, role)
62
63
64 class PdfToCWidget(QWidget):
65 """
66 Class implementing a Table of Contents viewer widget.
67
68 @signal topicActivated(page, zoomFactor) emitted to navigate to the selected topic
69 """
70
71 topicActivated = pyqtSignal(int, float)
72
73 def __init__(self, document, parent=None):
74 """
75 Constructor
76
77 @param document reference to the PDF document object
78 @type QPdfDocument
79 @param parent reference to the parent widget (defaults to None)
80 @type QWidget (optional)
81 """
82 super().__init__(parent)
83
84 self.__layout = QVBoxLayout(self)
85
86 self.__header = QLabel("<h2>{0}</h2>".format(self.tr("Contents")))
87 self.__header.setAlignment(Qt.AlignmentFlag.AlignCenter)
88 self.__layout.addWidget(self.__header)
89
90 self.__searchEdit = QLineEdit(self)
91 self.__searchEdit.setPlaceholderText(self.tr("Search ..."))
92 self.__searchEdit.setClearButtonEnabled(True)
93 self.__layout.addWidget(self.__searchEdit)
94
95 self.__tocWidget = QTreeView(self)
96 self.__tocWidget.setHeaderHidden(True)
97 self.__tocWidget.setExpandsOnDoubleClick(False)
98 self.__tocModel = PdfToCModel(self)
99 self.__tocModel.setDocument(document)
100 self.__tocFilterModel = QSortFilterProxyModel(self)
101 self.__tocFilterModel.setRecursiveFilteringEnabled(True)
102 self.__tocFilterModel.setSourceModel(self.__tocModel)
103 self.__tocWidget.setModel(self.__tocFilterModel)
104 self.__layout.addWidget(self.__tocWidget)
105
106 self.setLayout(self.__layout)
107
108 self.__tocWidget.activated.connect(self.__topicSelected)
109 document.statusChanged.connect(self.__handleDocumentStatus)
110 self.__searchEdit.textEdited.connect(self.__searchTextChanged)
111
112 @pyqtSlot(QModelIndex)
113 def __topicSelected(self, index):
114 """
115 Private slot to handle the selection of a ToC entry.
116
117 @param index index of the activated entry
118 @type QModelIndex
119 """
120 if not index.isValid():
121 return
122
123 page = index.data(QPdfBookmarkModel.Role.Page.value)
124 zoomFactor = index.data(QPdfBookmarkModel.Role.Zoom.value)
125
126 self.topicActivated.emit(page, zoomFactor)
127
128 @pyqtSlot(QPdfDocument.Status)
129 def __handleDocumentStatus(self, status):
130 """
131 Private slot to handle a change of the document status.
132
133 @param status document status
134 @type QPdfDocument.Status
135 """
136 if status == QPdfDocument.Status.Ready:
137 self.__tocWidget.expandAll()
138 for column in range(self.__tocModel.columnCount(QModelIndex())):
139 self.__tocWidget.resizeColumnToContents(column)
140
141 @pyqtSlot(str)
142 def __searchTextChanged(self, text):
143 """
144 Private slot to handle a change of the search text.
145
146 @param text search text
147 @type str
148 """
149 self.__tocFilterModel.setFilterWildcard("*{0}*".format(text))
150 self.__tocWidget.expandAll()

eric ide

mercurial