|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2009 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing the bookmarks menu. |
|
8 """ |
|
9 |
|
10 from __future__ import unicode_literals |
|
11 |
|
12 from PyQt5.QtCore import pyqtSignal, Qt, QUrl |
|
13 from PyQt5.QtGui import QCursor |
|
14 from PyQt5.QtWidgets import QMenu |
|
15 |
|
16 from E5Gui.E5ModelMenu import E5ModelMenu |
|
17 |
|
18 from .BookmarksModel import BookmarksModel |
|
19 from .BookmarkNode import BookmarkNode |
|
20 |
|
21 |
|
22 class BookmarksMenu(E5ModelMenu): |
|
23 """ |
|
24 Class implementing the bookmarks menu base class. |
|
25 |
|
26 @signal openUrl(QUrl, str) emitted to open a URL with the given title in |
|
27 the current tab |
|
28 @signal newTab(QUrl, str) emitted to open a URL with the given title in a |
|
29 new tab |
|
30 @signal newWindow(QUrl, str) emitted to open a URL with the given title in |
|
31 a new window |
|
32 """ |
|
33 openUrl = pyqtSignal(QUrl, str) |
|
34 newTab = pyqtSignal(QUrl, str) |
|
35 newWindow = pyqtSignal(QUrl, str) |
|
36 |
|
37 def __init__(self, parent=None): |
|
38 """ |
|
39 Constructor |
|
40 |
|
41 @param parent reference to the parent widget (QWidget) |
|
42 """ |
|
43 E5ModelMenu.__init__(self, parent) |
|
44 |
|
45 self.activated.connect(self.__activated) |
|
46 self.setStatusBarTextRole(BookmarksModel.UrlStringRole) |
|
47 self.setSeparatorRole(BookmarksModel.SeparatorRole) |
|
48 |
|
49 self.setContextMenuPolicy(Qt.CustomContextMenu) |
|
50 self.customContextMenuRequested.connect(self.__contextMenuRequested) |
|
51 |
|
52 def createBaseMenu(self): |
|
53 """ |
|
54 Public method to get the menu that is used to populate sub menu's. |
|
55 |
|
56 @return reference to the menu (BookmarksMenu) |
|
57 """ |
|
58 menu = BookmarksMenu(self) |
|
59 menu.openUrl.connect(self.openUrl) |
|
60 menu.newTab.connect(self.newTab) |
|
61 menu.newWindow.connect(self.newWindow) |
|
62 return menu |
|
63 |
|
64 def __updateVisitCount(self, idx): |
|
65 """ |
|
66 Private method to update the visit count of a bookmark. |
|
67 |
|
68 @param idx index of the bookmark item (QModelIndex) |
|
69 """ |
|
70 from WebBrowser.WebBrowserWindow import WebBrowserWindow |
|
71 |
|
72 bookmarkNode = self.model().node(idx) |
|
73 manager = WebBrowserWindow.bookmarksManager() |
|
74 manager.incVisitCount(bookmarkNode) |
|
75 |
|
76 def __activated(self, idx): |
|
77 """ |
|
78 Private slot handling the activated signal. |
|
79 |
|
80 @param idx index of the activated item (QModelIndex) |
|
81 """ |
|
82 if self._keyboardModifiers & Qt.ControlModifier: |
|
83 self.newTab.emit( |
|
84 idx.data(BookmarksModel.UrlRole), |
|
85 idx.data(Qt.DisplayRole)) |
|
86 elif self._keyboardModifiers & Qt.ShiftModifier: |
|
87 self.newWindow.emit( |
|
88 idx.data(BookmarksModel.UrlRole), |
|
89 idx.data(Qt.DisplayRole)) |
|
90 else: |
|
91 self.openUrl.emit( |
|
92 idx.data(BookmarksModel.UrlRole), |
|
93 idx.data(Qt.DisplayRole)) |
|
94 self.__updateVisitCount(idx) |
|
95 |
|
96 def postPopulated(self): |
|
97 """ |
|
98 Public method to add any actions after the tree. |
|
99 """ |
|
100 if self.isEmpty(): |
|
101 return |
|
102 |
|
103 parent = self.rootIndex() |
|
104 |
|
105 hasBookmarks = False |
|
106 |
|
107 for i in range(parent.model().rowCount(parent)): |
|
108 child = parent.model().index(i, 0, parent) |
|
109 |
|
110 if child.data(BookmarksModel.TypeRole) == BookmarkNode.Bookmark: |
|
111 hasBookmarks = True |
|
112 break |
|
113 |
|
114 if not hasBookmarks: |
|
115 return |
|
116 |
|
117 self.addSeparator() |
|
118 act = self.addAction(self.tr("Open all in Tabs")) |
|
119 act.triggered.connect(lambda: self.openAll(act)) |
|
120 |
|
121 def openAll(self, act): |
|
122 """ |
|
123 Public slot to open all the menu's items. |
|
124 |
|
125 @param act reference to the action object |
|
126 @type QAction |
|
127 """ |
|
128 menu = act.parent() |
|
129 if menu is None: |
|
130 return |
|
131 |
|
132 parent = menu.rootIndex() |
|
133 if not parent.isValid(): |
|
134 return |
|
135 |
|
136 for i in range(parent.model().rowCount(parent)): |
|
137 child = parent.model().index(i, 0, parent) |
|
138 |
|
139 if child.data(BookmarksModel.TypeRole) != BookmarkNode.Bookmark: |
|
140 continue |
|
141 |
|
142 if i == 0: |
|
143 self.openUrl.emit( |
|
144 child.data(BookmarksModel.UrlRole), |
|
145 child.data(Qt.DisplayRole)) |
|
146 else: |
|
147 self.newTab.emit( |
|
148 child.data(BookmarksModel.UrlRole), |
|
149 child.data(Qt.DisplayRole)) |
|
150 self.__updateVisitCount(child) |
|
151 |
|
152 def __contextMenuRequested(self, pos): |
|
153 """ |
|
154 Private slot to handle the context menu request. |
|
155 |
|
156 @param pos position the context menu shall be shown (QPoint) |
|
157 """ |
|
158 act = self.actionAt(pos) |
|
159 |
|
160 if act is not None and \ |
|
161 act.menu() is None and \ |
|
162 self.index(act).isValid(): |
|
163 menu = QMenu() |
|
164 v = act.data() |
|
165 |
|
166 act2 = menu.addAction(self.tr("Open")) |
|
167 act2.setData(v) |
|
168 act2.triggered.connect( |
|
169 lambda: self.__openBookmark(act2)) |
|
170 act2 = menu.addAction(self.tr("Open in New Tab\tCtrl+LMB")) |
|
171 act2.setData(v) |
|
172 act2.triggered.connect( |
|
173 lambda: self.__openBookmarkInNewTab(act2)) |
|
174 act2 = menu.addAction(self.tr("Open in New Window")) |
|
175 act2.setData(v) |
|
176 act2.triggered.connect( |
|
177 lambda: self.__openBookmarkInNewWindow(act2)) |
|
178 act2 = menu.addAction(self.tr("Open in New Private Window")) |
|
179 act2.setData(v) |
|
180 act2.triggered.connect( |
|
181 lambda: self.__openBookmarkInPrivateWindow(act2)) |
|
182 menu.addSeparator() |
|
183 |
|
184 act2 = menu.addAction(self.tr("Remove")) |
|
185 act2.setData(v) |
|
186 act2.triggered.connect(lambda: self.__removeBookmark(act2)) |
|
187 menu.addSeparator() |
|
188 |
|
189 act2 = menu.addAction(self.tr("Properties...")) |
|
190 act2.setData(v) |
|
191 act2.triggered.connect(lambda: self.__edit(act2)) |
|
192 |
|
193 execAct = menu.exec_(QCursor.pos()) |
|
194 if execAct is not None: |
|
195 self.close() |
|
196 parent = self.parent() |
|
197 while parent is not None and isinstance(parent, QMenu): |
|
198 parent.close() |
|
199 parent = parent.parent() |
|
200 |
|
201 def __openBookmark(self, act): |
|
202 """ |
|
203 Private slot to open a bookmark in the current browser tab. |
|
204 |
|
205 @param act reference to the triggering action |
|
206 @type QAction |
|
207 """ |
|
208 idx = self.index(act) |
|
209 |
|
210 self.openUrl.emit( |
|
211 idx.data(BookmarksModel.UrlRole), |
|
212 idx.data(Qt.DisplayRole)) |
|
213 self.__updateVisitCount(idx) |
|
214 |
|
215 def __openBookmarkInNewTab(self, act): |
|
216 """ |
|
217 Private slot to open a bookmark in a new browser tab. |
|
218 |
|
219 @param act reference to the triggering action |
|
220 @type QAction |
|
221 """ |
|
222 idx = self.index(act) |
|
223 |
|
224 self.newTab.emit( |
|
225 idx.data(BookmarksModel.UrlRole), |
|
226 idx.data(Qt.DisplayRole)) |
|
227 self.__updateVisitCount(idx) |
|
228 |
|
229 def __openBookmarkInNewWindow(self, act): |
|
230 """ |
|
231 Private slot to open a bookmark in a new window. |
|
232 |
|
233 @param act reference to the triggering action |
|
234 @type QAction |
|
235 """ |
|
236 idx = self.index(act) |
|
237 url = idx.data(BookmarksModel.UrlRole) |
|
238 |
|
239 from WebBrowser.WebBrowserWindow import WebBrowserWindow |
|
240 WebBrowserWindow.mainWindow().newWindow(url) |
|
241 self.__updateVisitCount(idx) |
|
242 |
|
243 def __openBookmarkInPrivateWindow(self, act): |
|
244 """ |
|
245 Private slot to open a bookmark in a new private window. |
|
246 |
|
247 @param act reference to the triggering action |
|
248 @type QAction |
|
249 """ |
|
250 idx = self.index(act) |
|
251 url = idx.data(BookmarksModel.UrlRole) |
|
252 |
|
253 from WebBrowser.WebBrowserWindow import WebBrowserWindow |
|
254 WebBrowserWindow.mainWindow().newPrivateWindow(url) |
|
255 self.__updateVisitCount(idx) |
|
256 |
|
257 def __removeBookmark(self, act): |
|
258 """ |
|
259 Private slot to remove a bookmark. |
|
260 |
|
261 @param act reference to the triggering action |
|
262 @type QAction |
|
263 """ |
|
264 idx = self.index(act) |
|
265 self.removeEntry(idx) |
|
266 |
|
267 def __edit(self, act): |
|
268 """ |
|
269 Private slot to edit a bookmarks properties. |
|
270 |
|
271 @param act reference to the triggering action |
|
272 @type QAction |
|
273 """ |
|
274 from .BookmarkPropertiesDialog import BookmarkPropertiesDialog |
|
275 |
|
276 idx = self.index(act) |
|
277 node = self.model().node(idx) |
|
278 dlg = BookmarkPropertiesDialog(node) |
|
279 dlg.exec_() |
|
280 |
|
281 ############################################################################## |
|
282 |
|
283 |
|
284 class BookmarksMenuBarMenu(BookmarksMenu): |
|
285 """ |
|
286 Class implementing a dynamically populated menu for bookmarks. |
|
287 |
|
288 @signal openUrl(QUrl, str) emitted to open a URL with the given title in |
|
289 the current tab |
|
290 """ |
|
291 openUrl = pyqtSignal(QUrl, str) |
|
292 |
|
293 def __init__(self, parent=None): |
|
294 """ |
|
295 Constructor |
|
296 |
|
297 @param parent reference to the parent widget (QWidget) |
|
298 """ |
|
299 BookmarksMenu.__init__(self, parent) |
|
300 |
|
301 self.__initialActions = [] |
|
302 |
|
303 def prePopulated(self): |
|
304 """ |
|
305 Public method to add any actions before the tree. |
|
306 |
|
307 @return flag indicating if any actions were added (boolean) |
|
308 """ |
|
309 from WebBrowser.WebBrowserWindow import WebBrowserWindow |
|
310 |
|
311 manager = WebBrowserWindow.bookmarksManager() |
|
312 self.setModel(manager.bookmarksModel()) |
|
313 self.setRootIndex(manager.bookmarksModel().nodeIndex(manager.menu())) |
|
314 |
|
315 # initial actions |
|
316 for act in self.__initialActions: |
|
317 if act == "--SEPARATOR--": |
|
318 self.addSeparator() |
|
319 else: |
|
320 self.addAction(act) |
|
321 if len(self.__initialActions) != 0: |
|
322 self.addSeparator() |
|
323 |
|
324 self.createMenu( |
|
325 manager.bookmarksModel().nodeIndex(manager.toolbar()), |
|
326 1, self) |
|
327 return True |
|
328 |
|
329 def postPopulated(self): |
|
330 """ |
|
331 Public method to add any actions after the tree. |
|
332 """ |
|
333 if self.isEmpty(): |
|
334 return |
|
335 |
|
336 parent = self.rootIndex() |
|
337 |
|
338 hasBookmarks = False |
|
339 |
|
340 for i in range(parent.model().rowCount(parent)): |
|
341 child = parent.model().index(i, 0, parent) |
|
342 |
|
343 if child.data(BookmarksModel.TypeRole) == BookmarkNode.Bookmark: |
|
344 hasBookmarks = True |
|
345 break |
|
346 |
|
347 if not hasBookmarks: |
|
348 return |
|
349 |
|
350 self.addSeparator() |
|
351 act = self.addAction(self.tr("Default Home Page")) |
|
352 act.setData("eric:home") |
|
353 act.triggered.connect( |
|
354 lambda: self.__defaultBookmarkTriggered(act)) |
|
355 act = self.addAction(self.tr("Speed Dial")) |
|
356 act.setData("eric:speeddial") |
|
357 act.triggered.connect( |
|
358 lambda: self.__defaultBookmarkTriggered(act)) |
|
359 self.addSeparator() |
|
360 act = self.addAction(self.tr("Open all in Tabs")) |
|
361 act.triggered.connect(lambda: self.openAll(act)) |
|
362 |
|
363 def setInitialActions(self, actions): |
|
364 """ |
|
365 Public method to set the list of actions that should appear first in |
|
366 the menu. |
|
367 |
|
368 @param actions list of initial actions (list of QAction) |
|
369 """ |
|
370 self.__initialActions = actions[:] |
|
371 for act in self.__initialActions: |
|
372 self.addAction(act) |
|
373 |
|
374 def __defaultBookmarkTriggered(self, act): |
|
375 """ |
|
376 Private slot handling the default bookmark menu entries. |
|
377 |
|
378 @param act reference to the action object |
|
379 @type QAction |
|
380 """ |
|
381 urlStr = act.data() |
|
382 if urlStr.startswith("eric:"): |
|
383 self.openUrl.emit(QUrl(urlStr), "") |