|
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 newUrl(QUrl, str) emitted to open a URL with the given title in a |
|
29 new tab |
|
30 """ |
|
31 openUrl = pyqtSignal(QUrl, str) |
|
32 newUrl = pyqtSignal(QUrl, str) |
|
33 |
|
34 def __init__(self, parent=None): |
|
35 """ |
|
36 Constructor |
|
37 |
|
38 @param parent reference to the parent widget (QWidget) |
|
39 """ |
|
40 E5ModelMenu.__init__(self, parent) |
|
41 |
|
42 self.activated.connect(self.__activated) |
|
43 self.setStatusBarTextRole(BookmarksModel.UrlStringRole) |
|
44 self.setSeparatorRole(BookmarksModel.SeparatorRole) |
|
45 |
|
46 self.setContextMenuPolicy(Qt.CustomContextMenu) |
|
47 self.customContextMenuRequested.connect(self.__contextMenuRequested) |
|
48 |
|
49 def createBaseMenu(self): |
|
50 """ |
|
51 Public method to get the menu that is used to populate sub menu's. |
|
52 |
|
53 @return reference to the menu (BookmarksMenu) |
|
54 """ |
|
55 menu = BookmarksMenu(self) |
|
56 menu.openUrl.connect(self.openUrl) |
|
57 menu.newUrl.connect(self.newUrl) |
|
58 return menu |
|
59 |
|
60 def __activated(self, idx): |
|
61 """ |
|
62 Private slot handling the activated signal. |
|
63 |
|
64 @param idx index of the activated item (QModelIndex) |
|
65 """ |
|
66 if self._keyboardModifiers & Qt.ControlModifier: |
|
67 self.newUrl.emit( |
|
68 idx.data(BookmarksModel.UrlRole), |
|
69 idx.data(Qt.DisplayRole)) |
|
70 else: |
|
71 self.openUrl.emit( |
|
72 idx.data(BookmarksModel.UrlRole), |
|
73 idx.data(Qt.DisplayRole)) |
|
74 self.resetFlags() |
|
75 |
|
76 def postPopulated(self): |
|
77 """ |
|
78 Public method to add any actions after the tree. |
|
79 """ |
|
80 if self.isEmpty(): |
|
81 return |
|
82 |
|
83 parent = self.rootIndex() |
|
84 |
|
85 hasBookmarks = False |
|
86 |
|
87 for i in range(parent.model().rowCount(parent)): |
|
88 child = parent.model().index(i, 0, parent) |
|
89 |
|
90 if child.data(BookmarksModel.TypeRole) == BookmarkNode.Bookmark: |
|
91 hasBookmarks = True |
|
92 break |
|
93 |
|
94 if not hasBookmarks: |
|
95 return |
|
96 |
|
97 self.addSeparator() |
|
98 act = self.addAction(self.tr("Open all in Tabs")) |
|
99 act.triggered.connect(lambda: self.openAll(act)) |
|
100 |
|
101 def openAll(self, act): |
|
102 """ |
|
103 Public slot to open all the menu's items. |
|
104 |
|
105 @param act reference to the action object |
|
106 @type QAction |
|
107 """ |
|
108 menu = act.parent() |
|
109 if menu is None: |
|
110 return |
|
111 |
|
112 parent = menu.rootIndex() |
|
113 if not parent.isValid(): |
|
114 return |
|
115 |
|
116 for i in range(parent.model().rowCount(parent)): |
|
117 child = parent.model().index(i, 0, parent) |
|
118 |
|
119 if child.data(BookmarksModel.TypeRole) != BookmarkNode.Bookmark: |
|
120 continue |
|
121 |
|
122 if i == 0: |
|
123 self.openUrl.emit( |
|
124 child.data(BookmarksModel.UrlRole), |
|
125 child.data(Qt.DisplayRole)) |
|
126 else: |
|
127 self.newUrl.emit( |
|
128 child.data(BookmarksModel.UrlRole), |
|
129 child.data(Qt.DisplayRole)) |
|
130 |
|
131 def __contextMenuRequested(self, pos): |
|
132 """ |
|
133 Private slot to handle the context menu request. |
|
134 |
|
135 @param pos position the context menu shall be shown (QPoint) |
|
136 """ |
|
137 act = self.actionAt(pos) |
|
138 |
|
139 if act is not None and \ |
|
140 act.menu() is None and \ |
|
141 self.index(act).isValid(): |
|
142 menu = QMenu() |
|
143 v = act.data() |
|
144 |
|
145 act2 = menu.addAction(self.tr("Open")) |
|
146 act2.setData(v) |
|
147 act2.triggered.connect( |
|
148 lambda: self.__openBookmark(act2)) |
|
149 act2 = menu.addAction(self.tr("Open in New Tab\tCtrl+LMB")) |
|
150 act2.setData(v) |
|
151 act2.triggered.connect( |
|
152 lambda: self.__openBookmarkInNewTab(act2)) |
|
153 menu.addSeparator() |
|
154 |
|
155 act2 = menu.addAction(self.tr("Remove")) |
|
156 act2.setData(v) |
|
157 act2.triggered.connect(lambda: self.__removeBookmark(act2)) |
|
158 menu.addSeparator() |
|
159 |
|
160 act2 = menu.addAction(self.tr("Properties...")) |
|
161 act2.setData(v) |
|
162 act2.triggered.connect(lambda: self.__edit(act2)) |
|
163 |
|
164 execAct = menu.exec_(QCursor.pos()) |
|
165 if execAct is not None: |
|
166 self.close() |
|
167 parent = self.parent() |
|
168 while parent is not None and isinstance(parent, QMenu): |
|
169 parent.close() |
|
170 parent = parent.parent() |
|
171 |
|
172 def __openBookmark(self, act): |
|
173 """ |
|
174 Private slot to open a bookmark in the current browser tab. |
|
175 |
|
176 @param act reference to the triggering action |
|
177 @type QAction |
|
178 """ |
|
179 idx = self.index(act) |
|
180 |
|
181 self.openUrl.emit( |
|
182 idx.data(BookmarksModel.UrlRole), |
|
183 idx.data(Qt.DisplayRole)) |
|
184 |
|
185 def __openBookmarkInNewTab(self, act): |
|
186 """ |
|
187 Private slot to open a bookmark in a new browser tab. |
|
188 |
|
189 @param act reference to the triggering action |
|
190 @type QAction |
|
191 """ |
|
192 idx = self.index(act) |
|
193 |
|
194 self.newUrl.emit( |
|
195 idx.data(BookmarksModel.UrlRole), |
|
196 idx.data(Qt.DisplayRole)) |
|
197 |
|
198 def __removeBookmark(self, act): |
|
199 """ |
|
200 Private slot to remove a bookmark. |
|
201 |
|
202 @param act reference to the triggering action |
|
203 @type QAction |
|
204 """ |
|
205 idx = self.index(act) |
|
206 self.removeEntry(idx) |
|
207 |
|
208 def __edit(self, act): |
|
209 """ |
|
210 Private slot to edit a bookmarks properties. |
|
211 |
|
212 @param act reference to the triggering action |
|
213 @type QAction |
|
214 """ |
|
215 from .BookmarkPropertiesDialog import BookmarkPropertiesDialog |
|
216 |
|
217 idx = self.index(act) |
|
218 node = self.model().node(idx) |
|
219 dlg = BookmarkPropertiesDialog(node) |
|
220 dlg.exec_() |
|
221 |
|
222 ############################################################################## |
|
223 |
|
224 |
|
225 class BookmarksMenuBarMenu(BookmarksMenu): |
|
226 """ |
|
227 Class implementing a dynamically populated menu for bookmarks. |
|
228 |
|
229 @signal openUrl(QUrl, str) emitted to open a URL with the given title in |
|
230 the current tab |
|
231 """ |
|
232 openUrl = pyqtSignal(QUrl, str) |
|
233 |
|
234 def __init__(self, parent=None): |
|
235 """ |
|
236 Constructor |
|
237 |
|
238 @param parent reference to the parent widget (QWidget) |
|
239 """ |
|
240 BookmarksMenu.__init__(self, parent) |
|
241 |
|
242 self.__bookmarksManager = None |
|
243 self.__initialActions = [] |
|
244 |
|
245 def prePopulated(self): |
|
246 """ |
|
247 Public method to add any actions before the tree. |
|
248 |
|
249 @return flag indicating if any actions were added (boolean) |
|
250 """ |
|
251 import Helpviewer.HelpWindow |
|
252 |
|
253 self.__bookmarksManager = Helpviewer.HelpWindow.HelpWindow\ |
|
254 .bookmarksManager() |
|
255 self.setModel(self.__bookmarksManager.bookmarksModel()) |
|
256 self.setRootIndex(self.__bookmarksManager.bookmarksModel() |
|
257 .nodeIndex(self.__bookmarksManager.menu())) |
|
258 |
|
259 # initial actions |
|
260 for act in self.__initialActions: |
|
261 if act == "--SEPARATOR--": |
|
262 self.addSeparator() |
|
263 else: |
|
264 self.addAction(act) |
|
265 if len(self.__initialActions) != 0: |
|
266 self.addSeparator() |
|
267 |
|
268 self.createMenu( |
|
269 self.__bookmarksManager.bookmarksModel() |
|
270 .nodeIndex(self.__bookmarksManager.toolbar()), |
|
271 1, self) |
|
272 return True |
|
273 |
|
274 def postPopulated(self): |
|
275 """ |
|
276 Public method to add any actions after the tree. |
|
277 """ |
|
278 if self.isEmpty(): |
|
279 return |
|
280 |
|
281 parent = self.rootIndex() |
|
282 |
|
283 hasBookmarks = False |
|
284 |
|
285 for i in range(parent.model().rowCount(parent)): |
|
286 child = parent.model().index(i, 0, parent) |
|
287 |
|
288 if child.data(BookmarksModel.TypeRole) == BookmarkNode.Bookmark: |
|
289 hasBookmarks = True |
|
290 break |
|
291 |
|
292 if not hasBookmarks: |
|
293 return |
|
294 |
|
295 self.addSeparator() |
|
296 act = self.addAction(self.tr("Default Home Page")) |
|
297 act.setData("eric:home") |
|
298 act.triggered.connect( |
|
299 lambda: self.__defaultBookmarkTriggered(act)) |
|
300 act = self.addAction(self.tr("Speed Dial")) |
|
301 act.setData("eric:speeddial") |
|
302 act.triggered.connect( |
|
303 lambda: self.__defaultBookmarkTriggered(act)) |
|
304 self.addSeparator() |
|
305 act = self.addAction(self.tr("Open all in Tabs")) |
|
306 act.triggered.connect(lambda: self.openAll(act)) |
|
307 |
|
308 def setInitialActions(self, actions): |
|
309 """ |
|
310 Public method to set the list of actions that should appear first in |
|
311 the menu. |
|
312 |
|
313 @param actions list of initial actions (list of QAction) |
|
314 """ |
|
315 self.__initialActions = actions[:] |
|
316 for act in self.__initialActions: |
|
317 self.addAction(act) |
|
318 |
|
319 def __defaultBookmarkTriggered(self, act): |
|
320 """ |
|
321 Private slot handling the default bookmark menu entries. |
|
322 |
|
323 @param act reference to the action object |
|
324 @type QAction |
|
325 """ |
|
326 urlStr = act.data() |
|
327 if urlStr.startswith("eric:"): |
|
328 self.openUrl.emit(QUrl(urlStr), "") |