5 |
5 |
6 """ |
6 """ |
7 Module implementing a widget showing the list of open pages. |
7 Module implementing a widget showing the list of open pages. |
8 """ |
8 """ |
9 |
9 |
10 from PyQt6.QtCore import pyqtSlot, pyqtSignal |
10 from PyQt6.QtCore import pyqtSlot, pyqtSignal, Qt, QPoint |
|
11 from PyQt6.QtGui import QGuiApplication, QClipboard |
11 from PyQt6.QtWidgets import ( |
12 from PyQt6.QtWidgets import ( |
12 QWidget, QLabel, QListWidget, QListWidgetItem, QVBoxLayout, |
13 QWidget, QLabel, QListWidget, QVBoxLayout, QAbstractItemView, QMenu |
13 QAbstractItemView |
|
14 ) |
14 ) |
|
15 |
|
16 import UI.PixmapCache |
15 |
17 |
16 |
18 |
17 class OpenPagesWidget(QWidget): |
19 class OpenPagesWidget(QWidget): |
18 """ |
20 """ |
19 Class implementing a widget showing the list of open pages. |
21 Class implementing a widget showing the list of open pages. |
31 @type QWidget (optional) |
33 @type QWidget (optional) |
32 """ |
34 """ |
33 super().__init__(parent) |
35 super().__init__(parent) |
34 self.setObjectName("OpenPagesWidget") |
36 self.setObjectName("OpenPagesWidget") |
35 |
37 |
|
38 self.__helpViewer = parent |
|
39 |
36 self.__layout = QVBoxLayout() |
40 self.__layout = QVBoxLayout() |
37 self.__layout.setContentsMargins(0, 0, 0, 0) |
41 self.__layout.setContentsMargins(0, 0, 0, 0) |
38 |
42 |
39 self.__title = QLabel(self.tr("Open Pages"), self) |
43 self.__title = QLabel(self.tr("Open Pages"), self) |
40 self.__layout.addWidget(self.__title) |
44 self.__layout.addWidget(self.__title) |
41 |
45 |
42 self.__openPagesList = QListWidget(self) |
46 self.__openPagesList = QListWidget(self) |
43 self.__openPagesList.setAlternatingRowColors(True) |
47 self.__openPagesList.setAlternatingRowColors(True) |
44 self.__openPagesList.setSelectionMode( |
48 self.__openPagesList.setSelectionMode( |
45 QAbstractItemView.SelectionMode.ExtendedSelection) |
49 QAbstractItemView.SelectionMode.SingleSelection) |
|
50 self.__openPagesList.setContextMenuPolicy( |
|
51 Qt.ContextMenuPolicy.CustomContextMenu) |
46 self.__openPagesList.currentRowChanged.connect( |
52 self.__openPagesList.currentRowChanged.connect( |
47 self.__currentRowChanged) |
53 self.__currentRowChanged) |
|
54 self.__openPagesList.customContextMenuRequested.connect( |
|
55 self.__showContextMenu) |
48 self.__layout.addWidget(self.__openPagesList) |
56 self.__layout.addWidget(self.__openPagesList) |
49 |
57 |
50 self.setLayout(self.__layout) |
58 self.setLayout(self.__layout) |
51 |
59 |
52 self.__stack = stack |
60 self.__stack = stack |
53 self.__stack.currentChanged.connect(self.__currentPageChanged) |
61 self.__stack.currentChanged.connect(self.__currentPageChanged) |
|
62 |
|
63 self.__initContextMenu() |
54 |
64 |
55 self.__defaultFont = self.__openPagesList.font() |
65 self.__defaultFont = self.__openPagesList.font() |
56 self.__boldFont = self.__openPagesList.font() |
66 self.__boldFont = self.__openPagesList.font() |
57 self.__boldFont.setBold(True) |
67 self.__boldFont.setBold(True) |
58 |
68 |
|
69 def __initContextMenu(self): |
|
70 """ |
|
71 Private method to initialize the context menu. |
|
72 """ |
|
73 self.__menu = QMenu(self) |
|
74 self.__menu.addAction( |
|
75 UI.PixmapCache.getIcon("tabClose"), |
|
76 self.tr('Close'), self.__contextMenuClose) |
|
77 self.closeOthersMenuAct = self.__menu.addAction( |
|
78 UI.PixmapCache.getIcon("tabCloseOther"), |
|
79 self.tr("Close Others"), |
|
80 self.__contextMenuCloseOthers) |
|
81 self.__menu.addAction( |
|
82 self.tr('Close All'), self.__contextMenuCloseAll) |
|
83 self.__menu.addSeparator() |
|
84 self.__copyUrlAct = self.__menu.addAction( |
|
85 self.tr("Copy URL to Clipboard"), |
|
86 self.__contextMenuCopyUrlToClipboard) |
|
87 |
|
88 @pyqtSlot(QPoint) |
|
89 def __showContextMenu(self, point): |
|
90 """ |
|
91 Private slot to handle the customContextMenuRequested signal of |
|
92 the viewlist. |
|
93 |
|
94 @param point position to open the menu at |
|
95 @type QPoint |
|
96 """ |
|
97 itm = self.__openPagesList.itemAt(point) |
|
98 self.__copyUrlAct.setEnabled(itm and itm.text() != "about:blank") |
|
99 self.__menu.popup(self.__openPagesList.mapToGlobal(point)) |
|
100 |
59 @pyqtSlot(int) |
101 @pyqtSlot(int) |
60 def __currentPageChanged(self, index): |
102 def __currentPageChanged(self, index): |
61 """ |
103 """ |
62 Private slot to handle a change of the shown page. |
104 Private slot to handle a change of the shown page. |
63 |
105 |
64 @param index index of the current page |
106 @param index index of the current page |
65 @type int |
107 @type int |
66 """ |
108 """ |
67 for row in range(self.__openPagesList.count()): |
109 for row in range(self.__openPagesList.count()): |
68 itm = self.__openPagesList.item(index) |
110 itm = self.__openPagesList.item(row) |
69 itm.setFont( |
111 itm.setFont( |
70 self.__boldFont if row == index else self.__defaultFont |
112 self.__boldFont if row == index else self.__defaultFont |
71 ) |
113 ) |
72 |
114 |
73 @pyqtSlot(int) |
115 @pyqtSlot(int) |
79 @type int |
121 @type int |
80 """ |
122 """ |
81 self.__stack.setCurrentIndex(row) |
123 self.__stack.setCurrentIndex(row) |
82 self.currentChanged.emit(row) |
124 self.currentChanged.emit(row) |
83 |
125 |
84 def addPage(self, viewer): |
126 def addPage(self, viewer, background=False): |
85 """ |
127 """ |
86 Public method to add a viewer page to our list. |
128 Public method to add a viewer page to our list. |
87 |
129 |
88 @param viewer reference to the viewer object |
130 @param viewer reference to the viewer object |
89 @type HelpViewerImpl |
131 @type HelpViewerImpl |
90 """ |
132 @param background flag indicating to not change the current page |
91 QListWidgetItem(viewer.title(), self.__openPagesList) |
133 (defaults to False) |
|
134 @type bool (optional) |
|
135 """ |
|
136 self.__openPagesList.addItem(viewer.title()) |
92 viewer.titleChanged.connect( |
137 viewer.titleChanged.connect( |
93 lambda: self.__viewerTitleChanged(viewer)) |
138 lambda: self.__viewerTitleChanged(viewer)) |
94 |
139 |
95 self.__currentPageChanged(self.__openPagesList.count() - 1) |
140 if not background: |
|
141 self.__openPagesList.setCurrentRow( |
|
142 self.__openPagesList.count() - 1) |
|
143 if self.__openPagesList.count() == 1: |
|
144 self.__currentPageChanged(0) |
|
145 |
|
146 def insertPage(self, index, viewer, background=False): |
|
147 """ |
|
148 Public method to insert a viewer page into our list. |
|
149 |
|
150 @param index index to insert at |
|
151 @type int |
|
152 @param viewer reference to the viewer object |
|
153 @type HelpViewerImpl |
|
154 @param background flag indicating to not change the current page |
|
155 (defaults to False) |
|
156 @type bool (optional) |
|
157 """ |
|
158 currentRow = self.__openPagesList.currentRow() |
|
159 self.__openPagesList.insertItem(index, viewer.title()) |
|
160 viewer.titleChanged.connect( |
|
161 lambda: self.__viewerTitleChanged(viewer)) |
|
162 |
|
163 if not background: |
|
164 self.__openPagesList.setCurrentRow(index) |
|
165 else: |
|
166 self.__openPagesList.setCurrentRow(currentRow) |
96 |
167 |
97 def __viewerTitleChanged(self, viewer): |
168 def __viewerTitleChanged(self, viewer): |
98 """ |
169 """ |
99 Private method to handle the change of a viewer title. |
170 Private method to handle the change of a viewer title. |
100 |
171 |
103 """ |
174 """ |
104 index = self.__stack.indexOf(viewer) |
175 index = self.__stack.indexOf(viewer) |
105 itm = self.__openPagesList.item(index) |
176 itm = self.__openPagesList.item(index) |
106 itm.setText(viewer.title()) |
177 itm.setText(viewer.title()) |
107 self.currentChanged.emit(index) |
178 self.currentChanged.emit(index) |
|
179 |
|
180 ####################################################################### |
|
181 ## Context menu action methods |
|
182 ####################################################################### |
|
183 |
|
184 @pyqtSlot() |
|
185 def __contextMenuClose(self): |
|
186 """ |
|
187 Private slot to close a page. |
|
188 """ |
|
189 row = self.__openPagesList.currentRow() |
|
190 self.__removeViewer(row) |
|
191 |
|
192 if self.__openPagesList.count() == 0: |
|
193 self.__helpViewer.addPage() |
|
194 |
|
195 @pyqtSlot() |
|
196 def __contextMenuCloseOthers(self): |
|
197 """ |
|
198 Private slot to close all other pages. |
|
199 """ |
|
200 currentRow = self.__openPagesList.currentRow() |
|
201 for row in range(self.__openPagesList.count() - 1, -1, -1): |
|
202 if row != currentRow: |
|
203 self.__removeViewer(row) |
|
204 |
|
205 @pyqtSlot() |
|
206 def __contextMenuCloseAll(self): |
|
207 """ |
|
208 Private slot to close all pages. |
|
209 """ |
|
210 while self.__openPagesList.count() != 0: |
|
211 self.__removeViewer(0) |
|
212 self.__helpViewer.addPage() |
|
213 |
|
214 @pyqtSlot() |
|
215 def __contextMenuCopyUrlToClipboard(self): |
|
216 """ |
|
217 Private slot to copy the URL to the clipboard. |
|
218 """ |
|
219 row = self.__openPagesList.currentRow() |
|
220 viewer = self.__stack.widget(row) |
|
221 url = viewer.url() |
|
222 if url.isValid(): |
|
223 urlStr = url.toString() |
|
224 |
|
225 # copy the URL to both clipboard areas |
|
226 QGuiApplication.clipboard().setText( |
|
227 urlStr, QClipboard.Mode.Clipboard) |
|
228 QGuiApplication.clipboard().setText( |
|
229 urlStr, QClipboard.Mode.Selection) |
|
230 |
|
231 def __removeViewer(self, row): |
|
232 """ |
|
233 Private method to remove a viewer page. |
|
234 |
|
235 @param row row associated with the viewer |
|
236 @type int |
|
237 """ |
|
238 viewer = self.__stack.widget(row) |
|
239 self.__stack.removeWidget(viewer) |
|
240 viewer.deleteLater() |
|
241 |
|
242 itm = self.__openPagesList.takeItem(row) |
|
243 del itm |