src/eric7/WebBrowser/Bookmarks/BookmarksDialog.py

branch
eric7
changeset 9209
b99e7fd55fd3
parent 8881
54e42bc2437a
child 9221
bf71ee032bb4
equal deleted inserted replaced
9208:3fc8dfeb6ebe 9209:b99e7fd55fd3
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2009 - 2022 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a dialog to manage bookmarks.
8 """
9
10 from PyQt6.QtCore import pyqtSignal, Qt, QUrl, QModelIndex
11 from PyQt6.QtGui import QFontMetrics, QCursor
12 from PyQt6.QtWidgets import (
13 QDialog, QMenu, QApplication, QInputDialog, QLineEdit
14 )
15
16 from EricCore.EricTreeSortFilterProxyModel import EricTreeSortFilterProxyModel
17
18 from .Ui_BookmarksDialog import Ui_BookmarksDialog
19
20
21 class BookmarksDialog(QDialog, Ui_BookmarksDialog):
22 """
23 Class implementing a dialog to manage bookmarks.
24
25 @signal openUrl(QUrl, str) emitted to open a URL in the current tab
26 @signal newTab(QUrl, str) emitted to open a URL in a new tab
27 @signal newBackgroundTab(QUrl, str) emitted to open a URL in a new
28 background tab
29 @signal newWindow(QUrl, str) emitted to open a URL in a new window
30 """
31 openUrl = pyqtSignal(QUrl, str)
32 newTab = pyqtSignal(QUrl, str)
33 newBackgroundTab = pyqtSignal(QUrl, str)
34 newWindow = pyqtSignal(QUrl, str)
35
36 def __init__(self, parent=None, manager=None):
37 """
38 Constructor
39
40 @param parent reference to the parent widget (QWidget
41 @param manager reference to the bookmarks manager object
42 (BookmarksManager)
43 """
44 super().__init__(parent)
45 self.setupUi(self)
46 self.setWindowFlags(Qt.WindowType.Window)
47
48 self.__bookmarksManager = manager
49 if self.__bookmarksManager is None:
50 import WebBrowser.WebBrowserWindow
51 self.__bookmarksManager = (
52 WebBrowser.WebBrowserWindow.WebBrowserWindow.bookmarksManager()
53 )
54
55 self.__bookmarksModel = self.__bookmarksManager.bookmarksModel()
56 self.__proxyModel = EricTreeSortFilterProxyModel(self)
57 self.__proxyModel.setFilterKeyColumn(-1)
58 self.__proxyModel.setSourceModel(self.__bookmarksModel)
59
60 self.searchEdit.textChanged.connect(
61 self.__proxyModel.setFilterFixedString)
62
63 self.bookmarksTree.setModel(self.__proxyModel)
64 self.bookmarksTree.setExpanded(self.__proxyModel.index(0, 0), True)
65 fm = QFontMetrics(self.font())
66 try:
67 header = fm.horizontalAdvance("m") * 40
68 except AttributeError:
69 header = fm.width("m") * 40
70 self.bookmarksTree.header().resizeSection(0, header)
71 self.bookmarksTree.header().setStretchLastSection(True)
72 self.bookmarksTree.setContextMenuPolicy(
73 Qt.ContextMenuPolicy.CustomContextMenu)
74
75 self.bookmarksTree.activated.connect(self.__activated)
76 self.bookmarksTree.customContextMenuRequested.connect(
77 self.__customContextMenuRequested)
78
79 self.removeButton.clicked.connect(
80 self.bookmarksTree.removeSelected)
81 self.addFolderButton.clicked.connect(self.__newFolder)
82
83 self.__expandNodes(self.__bookmarksManager.bookmarks())
84
85 def closeEvent(self, evt):
86 """
87 Protected method to handle the closing of the dialog.
88
89 @param evt reference to the event object (QCloseEvent) (ignored)
90 """
91 self.__shutdown()
92
93 def reject(self):
94 """
95 Public method called when the dialog is rejected.
96 """
97 self.__shutdown()
98 super().reject()
99
100 def __shutdown(self):
101 """
102 Private method to perform shutdown actions for the dialog.
103 """
104 if self.__saveExpandedNodes(self.bookmarksTree.rootIndex()):
105 self.__bookmarksManager.changeExpanded()
106
107 def __saveExpandedNodes(self, parent):
108 """
109 Private method to save the child nodes of an expanded node.
110
111 @param parent index of the parent node (QModelIndex)
112 @return flag indicating a change (boolean)
113 """
114 changed = False
115 for row in range(self.__proxyModel.rowCount(parent)):
116 child = self.__proxyModel.index(row, 0, parent)
117 sourceIndex = self.__proxyModel.mapToSource(child)
118 childNode = self.__bookmarksModel.node(sourceIndex)
119 wasExpanded = childNode.expanded
120 if self.bookmarksTree.isExpanded(child):
121 childNode.expanded = True
122 changed |= self.__saveExpandedNodes(child)
123 else:
124 childNode.expanded = False
125 changed |= (wasExpanded != childNode.expanded)
126
127 return changed
128
129 def __expandNodes(self, node):
130 """
131 Private method to expand all child nodes of a node.
132
133 @param node reference to the bookmark node to expand (BookmarkNode)
134 """
135 for childNode in node.children():
136 if childNode.expanded:
137 idx = self.__bookmarksModel.nodeIndex(childNode)
138 idx = self.__proxyModel.mapFromSource(idx)
139 self.bookmarksTree.setExpanded(idx, True)
140 self.__expandNodes(childNode)
141
142 def __customContextMenuRequested(self, pos):
143 """
144 Private slot to handle the context menu request for the bookmarks tree.
145
146 @param pos position the context menu was requested (QPoint)
147 """
148 from .BookmarkNode import BookmarkNode
149
150 menu = QMenu()
151 idx = self.bookmarksTree.indexAt(pos)
152 idx = idx.sibling(idx.row(), 0)
153 sourceIndex = self.__proxyModel.mapToSource(idx)
154 node = self.__bookmarksModel.node(sourceIndex)
155 if idx.isValid() and node.type() != BookmarkNode.Folder:
156 menu.addAction(
157 self.tr("&Open"), self.__openBookmarkInCurrentTab)
158 menu.addAction(
159 self.tr("Open in New &Tab"), self.__openBookmarkInNewTab)
160 menu.addAction(
161 self.tr("Open in New &Background Tab"),
162 self.__openBookmarkInNewBackgroundTab)
163 menu.addAction(
164 self.tr("Open in New &Window"), self.__openBookmarkInNewWindow)
165 menu.addAction(
166 self.tr("Open in New Pri&vate Window"),
167 self.__openBookmarkInPrivateWindow)
168 menu.addSeparator()
169 act = menu.addAction(self.tr("Edit &Name"), self.__editName)
170 act.setEnabled(idx.flags() & Qt.ItemFlag.ItemIsEditable ==
171 Qt.ItemFlag.ItemIsEditable)
172 if idx.isValid() and node.type() != BookmarkNode.Folder:
173 menu.addAction(self.tr("Edit &Address"), self.__editAddress)
174 menu.addSeparator()
175 act = menu.addAction(
176 self.tr("&Delete"), self.bookmarksTree.removeSelected)
177 act.setEnabled(idx.flags() & Qt.ItemFlag.ItemIsDragEnabled ==
178 Qt.ItemFlag.ItemIsDragEnabled)
179 menu.addSeparator()
180 act = menu.addAction(self.tr("&Properties..."), self.__edit)
181 act.setEnabled(idx.flags() & Qt.ItemFlag.ItemIsEditable ==
182 Qt.ItemFlag.ItemIsEditable)
183 if idx.isValid() and node.type() == BookmarkNode.Folder:
184 menu.addSeparator()
185 menu.addAction(self.tr("New &Folder..."), self.__newFolder)
186 menu.exec(QCursor.pos())
187
188 def __activated(self, idx):
189 """
190 Private slot to handle the activation of an entry.
191
192 @param idx reference to the entry index (QModelIndex)
193 """
194 if (
195 QApplication.keyboardModifiers() &
196 Qt.KeyboardModifier.ControlModifier
197 ):
198 self.__openBookmarkInNewTab()
199 elif (
200 QApplication.keyboardModifiers() &
201 Qt.KeyboardModifier.ShiftModifier
202 ):
203 self.__openBookmarkInNewWindow()
204 else:
205 self.__openBookmarkInCurrentTab()
206
207 def __openBookmarkInCurrentTab(self):
208 """
209 Private slot to open a bookmark in the current browser tab.
210 """
211 self.__openBookmark()
212
213 def __openBookmarkInNewTab(self):
214 """
215 Private slot to open a bookmark in a new browser tab.
216 """
217 self.__openBookmark(newTab=True)
218
219 def __openBookmarkInNewBackgroundTab(self):
220 """
221 Private slot to open a bookmark in a new browser tab.
222 """
223 self.__openBookmark(newTab=True, background=True)
224
225 def __openBookmarkInNewWindow(self):
226 """
227 Private slot to open a bookmark in a new browser window.
228 """
229 self.__openBookmark(newWindow=True)
230
231 def __openBookmarkInPrivateWindow(self):
232 """
233 Private slot to open a bookmark in a new private browser window.
234 """
235 self.__openBookmark(newWindow=True, privateWindow=True)
236
237 def __openBookmark(self, newTab=False, newWindow=False,
238 privateWindow=False, background=False):
239 """
240 Private method to open a bookmark.
241
242 @param newTab flag indicating to open the bookmark in a new tab
243 @type bool
244 @param newWindow flag indicating to open the bookmark in a new window
245 @type bool
246 @param privateWindow flag indicating to open the bookmark in a new
247 private window
248 @type bool
249 @param background flag indicating to open the bookmark in a new
250 background tab
251 @type bool
252 """
253 from .BookmarkNode import BookmarkNode
254 from .BookmarksModel import BookmarksModel
255
256 idx = self.bookmarksTree.currentIndex()
257 sourceIndex = self.__proxyModel.mapToSource(idx)
258 node = self.__bookmarksModel.node(sourceIndex)
259 if (
260 not idx.parent().isValid() or
261 node is None or
262 node.type() == BookmarkNode.Folder
263 ):
264 return
265
266 if newWindow:
267 from WebBrowser.WebBrowserWindow import WebBrowserWindow
268 url = idx.sibling(idx.row(), 1).data(BookmarksModel.UrlRole)
269 if privateWindow:
270 WebBrowserWindow.mainWindow().newPrivateWindow(url)
271 else:
272 WebBrowserWindow.mainWindow().newWindow(url)
273 else:
274 if newTab:
275 if background:
276 self.newBackgroundTab.emit(
277 idx.sibling(idx.row(), 1).data(
278 BookmarksModel.UrlRole),
279 idx.sibling(idx.row(), 0).data(
280 Qt.ItemDataRole.DisplayRole))
281 else:
282 self.newTab.emit(
283 idx.sibling(idx.row(), 1).data(
284 BookmarksModel.UrlRole),
285 idx.sibling(idx.row(), 0).data(
286 Qt.ItemDataRole.DisplayRole))
287 else:
288 self.openUrl.emit(
289 idx.sibling(idx.row(), 1).data(
290 BookmarksModel.UrlRole),
291 idx.sibling(idx.row(), 0).data(
292 Qt.ItemDataRole.DisplayRole))
293 self.__bookmarksManager.incVisitCount(node)
294
295 def __editName(self):
296 """
297 Private slot to edit the name part of a bookmark.
298 """
299 idx = self.bookmarksTree.currentIndex()
300 idx = idx.sibling(idx.row(), 0)
301 self.bookmarksTree.edit(idx)
302
303 def __editAddress(self):
304 """
305 Private slot to edit the address part of a bookmark.
306 """
307 idx = self.bookmarksTree.currentIndex()
308 idx = idx.sibling(idx.row(), 1)
309 self.bookmarksTree.edit(idx)
310
311 def __edit(self):
312 """
313 Private slot to edit a bookmarks properties.
314 """
315 from .BookmarkPropertiesDialog import BookmarkPropertiesDialog
316
317 idx = self.bookmarksTree.currentIndex()
318 sourceIndex = self.__proxyModel.mapToSource(idx)
319 node = self.__bookmarksModel.node(sourceIndex)
320 dlg = BookmarkPropertiesDialog(node)
321 dlg.exec()
322
323 def __newFolder(self):
324 """
325 Private slot to add a new bookmarks folder.
326 """
327 from .BookmarkNode import BookmarkNode
328
329 currentIndex = self.bookmarksTree.currentIndex()
330 idx = QModelIndex(currentIndex)
331 sourceIndex = self.__proxyModel.mapToSource(idx)
332 sourceNode = self.__bookmarksModel.node(sourceIndex)
333 row = -1 # append new folder as the last item per default
334
335 if (
336 sourceNode is not None and
337 sourceNode.type() != BookmarkNode.Folder
338 ):
339 # If the selected item is not a folder, add a new folder to the
340 # parent folder, but directly below the selected item.
341 idx = idx.parent()
342 row = currentIndex.row() + 1
343
344 if not idx.isValid():
345 # Select bookmarks menu as default.
346 idx = self.__proxyModel.index(1, 0)
347
348 idx = self.__proxyModel.mapToSource(idx)
349 parent = self.__bookmarksModel.node(idx)
350 title, ok = QInputDialog.getText(
351 self,
352 self.tr("New Bookmark Folder"),
353 self.tr("Enter title for new bookmark folder:"),
354 QLineEdit.EchoMode.Normal)
355
356 if ok:
357 if not title:
358 title = self.tr("New Folder")
359 node = BookmarkNode(BookmarkNode.Folder)
360 node.title = title
361 self.__bookmarksManager.addBookmark(parent, node, row)

eric ide

mercurial