eric7/WebBrowser/Bookmarks/BookmarksDialog.py

branch
eric7
changeset 8312
800c432b34c8
parent 8218
7c09585bd960
child 8318
962bce857696
equal deleted inserted replaced
8311:4e8b98454baa 8312:800c432b34c8
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2009 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a dialog to manage bookmarks.
8 """
9
10 from PyQt5.QtCore import pyqtSignal, Qt, QUrl, QModelIndex
11 from PyQt5.QtGui import QFontMetrics, QCursor
12 from PyQt5.QtWidgets import (
13 QDialog, QMenu, QApplication, QInputDialog, QLineEdit
14 )
15
16 from E5Gui.E5TreeSortFilterProxyModel import E5TreeSortFilterProxyModel
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 = E5TreeSortFilterProxyModel(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 if idx.isValid() and node.type() != BookmarkNode.Folder:
172 menu.addAction(self.tr("Edit &Address"), self.__editAddress)
173 menu.addSeparator()
174 act = menu.addAction(
175 self.tr("&Delete"), self.bookmarksTree.removeSelected)
176 act.setEnabled(idx.flags() & Qt.ItemFlag.ItemIsDragEnabled)
177 menu.addSeparator()
178 act = menu.addAction(self.tr("&Properties..."), self.__edit)
179 act.setEnabled(idx.flags() & Qt.ItemFlag.ItemIsEditable)
180 if idx.isValid() and node.type() == BookmarkNode.Folder:
181 menu.addSeparator()
182 menu.addAction(self.tr("New &Folder..."), self.__newFolder)
183 menu.exec(QCursor.pos())
184
185 def __activated(self, idx):
186 """
187 Private slot to handle the activation of an entry.
188
189 @param idx reference to the entry index (QModelIndex)
190 """
191 if (
192 QApplication.keyboardModifiers() &
193 Qt.KeyboardModifier.ControlModifier
194 ):
195 self.__openBookmarkInNewTab()
196 elif (
197 QApplication.keyboardModifiers() &
198 Qt.KeyboardModifier.ShiftModifier
199 ):
200 self.__openBookmarkInNewWindow()
201 else:
202 self.__openBookmarkInCurrentTab()
203
204 def __openBookmarkInCurrentTab(self):
205 """
206 Private slot to open a bookmark in the current browser tab.
207 """
208 self.__openBookmark()
209
210 def __openBookmarkInNewTab(self):
211 """
212 Private slot to open a bookmark in a new browser tab.
213 """
214 self.__openBookmark(newTab=True)
215
216 def __openBookmarkInNewBackgroundTab(self):
217 """
218 Private slot to open a bookmark in a new browser tab.
219 """
220 self.__openBookmark(newTab=True, background=True)
221
222 def __openBookmarkInNewWindow(self):
223 """
224 Private slot to open a bookmark in a new browser window.
225 """
226 self.__openBookmark(newWindow=True)
227
228 def __openBookmarkInPrivateWindow(self):
229 """
230 Private slot to open a bookmark in a new private browser window.
231 """
232 self.__openBookmark(newWindow=True, privateWindow=True)
233
234 def __openBookmark(self, newTab=False, newWindow=False,
235 privateWindow=False, background=False):
236 """
237 Private method to open a bookmark.
238
239 @param newTab flag indicating to open the bookmark in a new tab
240 @type bool
241 @param newWindow flag indicating to open the bookmark in a new window
242 @type bool
243 @param privateWindow flag indicating to open the bookmark in a new
244 private window
245 @type bool
246 @param background flag indicating to open the bookmark in a new
247 background tab
248 @type bool
249 """
250 from .BookmarkNode import BookmarkNode
251 from .BookmarksModel import BookmarksModel
252
253 idx = self.bookmarksTree.currentIndex()
254 sourceIndex = self.__proxyModel.mapToSource(idx)
255 node = self.__bookmarksModel.node(sourceIndex)
256 if (
257 not idx.parent().isValid() or
258 node is None or
259 node.type() == BookmarkNode.Folder
260 ):
261 return
262
263 if newWindow:
264 from WebBrowser.WebBrowserWindow import WebBrowserWindow
265 url = idx.sibling(idx.row(), 1).data(BookmarksModel.UrlRole)
266 if privateWindow:
267 WebBrowserWindow.mainWindow().newPrivateWindow(url)
268 else:
269 WebBrowserWindow.mainWindow().newWindow(url)
270 else:
271 if newTab:
272 if background:
273 self.newBackgroundTab.emit(
274 idx.sibling(idx.row(), 1).data(
275 BookmarksModel.UrlRole),
276 idx.sibling(idx.row(), 0).data(
277 Qt.ItemDataRole.DisplayRole))
278 else:
279 self.newTab.emit(
280 idx.sibling(idx.row(), 1).data(
281 BookmarksModel.UrlRole),
282 idx.sibling(idx.row(), 0).data(
283 Qt.ItemDataRole.DisplayRole))
284 else:
285 self.openUrl.emit(
286 idx.sibling(idx.row(), 1).data(
287 BookmarksModel.UrlRole),
288 idx.sibling(idx.row(), 0).data(
289 Qt.ItemDataRole.DisplayRole))
290 self.__bookmarksManager.incVisitCount(node)
291
292 def __editName(self):
293 """
294 Private slot to edit the name part of a bookmark.
295 """
296 idx = self.bookmarksTree.currentIndex()
297 idx = idx.sibling(idx.row(), 0)
298 self.bookmarksTree.edit(idx)
299
300 def __editAddress(self):
301 """
302 Private slot to edit the address part of a bookmark.
303 """
304 idx = self.bookmarksTree.currentIndex()
305 idx = idx.sibling(idx.row(), 1)
306 self.bookmarksTree.edit(idx)
307
308 def __edit(self):
309 """
310 Private slot to edit a bookmarks properties.
311 """
312 from .BookmarkPropertiesDialog import BookmarkPropertiesDialog
313
314 idx = self.bookmarksTree.currentIndex()
315 sourceIndex = self.__proxyModel.mapToSource(idx)
316 node = self.__bookmarksModel.node(sourceIndex)
317 dlg = BookmarkPropertiesDialog(node)
318 dlg.exec()
319
320 def __newFolder(self):
321 """
322 Private slot to add a new bookmarks folder.
323 """
324 from .BookmarkNode import BookmarkNode
325
326 currentIndex = self.bookmarksTree.currentIndex()
327 idx = QModelIndex(currentIndex)
328 sourceIndex = self.__proxyModel.mapToSource(idx)
329 sourceNode = self.__bookmarksModel.node(sourceIndex)
330 row = -1 # append new folder as the last item per default
331
332 if (
333 sourceNode is not None and
334 sourceNode.type() != BookmarkNode.Folder
335 ):
336 # If the selected item is not a folder, add a new folder to the
337 # parent folder, but directly below the selected item.
338 idx = idx.parent()
339 row = currentIndex.row() + 1
340
341 if not idx.isValid():
342 # Select bookmarks menu as default.
343 idx = self.__proxyModel.index(1, 0)
344
345 idx = self.__proxyModel.mapToSource(idx)
346 parent = self.__bookmarksModel.node(idx)
347 title, ok = QInputDialog.getText(
348 self,
349 self.tr("New Bookmark Folder"),
350 self.tr("Enter title for new bookmark folder:"),
351 QLineEdit.EchoMode.Normal)
352
353 if ok:
354 if not title:
355 title = self.tr("New Folder")
356 node = BookmarkNode(BookmarkNode.Folder)
357 node.title = title
358 self.__bookmarksManager.addBookmark(parent, node, row)

eric ide

mercurial