|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2009 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing a dialog to manage bookmarks. |
|
8 """ |
|
9 |
|
10 from PyQt4.QtCore import * |
|
11 from PyQt4.QtGui import * |
|
12 |
|
13 from E4Gui.E4TreeSortFilterProxyModel import E4TreeSortFilterProxyModel |
|
14 |
|
15 import Helpviewer.HelpWindow |
|
16 from BookmarkNode import BookmarkNode |
|
17 from BookmarksModel import BookmarksModel |
|
18 |
|
19 from Ui_BookmarksDialog import Ui_BookmarksDialog |
|
20 |
|
21 import UI.PixmapCache |
|
22 |
|
23 class BookmarksDialog(QDialog, Ui_BookmarksDialog): |
|
24 """ |
|
25 Class implementing a dialog to manage bookmarks. |
|
26 |
|
27 @signal openUrl(const QUrl&, const QString&) emitted to open a URL in the current |
|
28 tab |
|
29 @signal newUrl(const QUrl&, const QString&) emitted to open a URL in a new tab |
|
30 """ |
|
31 def __init__(self, parent = None, manager = None): |
|
32 """ |
|
33 Constructor |
|
34 |
|
35 @param parent reference to the parent widget (QWidget |
|
36 @param manager reference to the bookmarks manager object (BookmarksManager) |
|
37 """ |
|
38 QDialog.__init__(self, parent) |
|
39 self.setupUi(self) |
|
40 |
|
41 self.clearButton.setIcon(UI.PixmapCache.getIcon("clearLeft.png")) |
|
42 |
|
43 self.__bookmarksManager = manager |
|
44 if self.__bookmarksManager is None: |
|
45 self.__bookmarksManager = Helpviewer.HelpWindow.HelpWindow.bookmarksManager() |
|
46 |
|
47 self.__bookmarksModel = self.__bookmarksManager.bookmarksModel() |
|
48 self.__proxyModel = E4TreeSortFilterProxyModel(self) |
|
49 self.__proxyModel.setFilterKeyColumn(-1) |
|
50 self.__proxyModel.setSourceModel(self.__bookmarksModel) |
|
51 |
|
52 self.connect(self.searchEdit, SIGNAL("textChanged(QString)"), |
|
53 self.__proxyModel.setFilterFixedString) |
|
54 |
|
55 self.bookmarksTree.setModel(self.__proxyModel) |
|
56 self.bookmarksTree.setExpanded(self.__proxyModel.index(0, 0), True) |
|
57 fm = QFontMetrics(self.font()) |
|
58 header = fm.width("m") * 40 |
|
59 self.bookmarksTree.header().resizeSection(0, header) |
|
60 self.bookmarksTree.header().setStretchLastSection(True) |
|
61 self.bookmarksTree.setContextMenuPolicy(Qt.CustomContextMenu) |
|
62 |
|
63 self.connect(self.bookmarksTree, SIGNAL("activated(const QModelIndex&)"), |
|
64 self.__activated) |
|
65 self.connect(self.bookmarksTree, |
|
66 SIGNAL("customContextMenuRequested(const QPoint &)"), |
|
67 self.__customContextMenuRequested) |
|
68 |
|
69 self.connect(self.removeButton, SIGNAL("clicked()"), |
|
70 self.bookmarksTree.removeSelected) |
|
71 self.connect(self.addFolderButton, SIGNAL("clicked()"), |
|
72 self.__newFolder) |
|
73 |
|
74 self.__expandNodes(self.__bookmarksManager.bookmarks()) |
|
75 |
|
76 def closeEvent(self, evt): |
|
77 """ |
|
78 Protected method to handle the closing of the dialog. |
|
79 |
|
80 @param evt reference to the event object (QCloseEvent) (ignored) |
|
81 """ |
|
82 self.__shutdown() |
|
83 |
|
84 def reject(self): |
|
85 """ |
|
86 Protected method called when the dialog is rejected. |
|
87 """ |
|
88 self.__shutdown() |
|
89 QDialog.reject(self) |
|
90 |
|
91 def __shutdown(self): |
|
92 """ |
|
93 Private method to perform shutdown actions for the dialog. |
|
94 """ |
|
95 if self.__saveExpandedNodes(self.bookmarksTree.rootIndex()): |
|
96 self.__bookmarksManager.changeExpanded() |
|
97 |
|
98 def __saveExpandedNodes(self, parent): |
|
99 """ |
|
100 Private method to save the child nodes of an expanded node. |
|
101 |
|
102 @param parent index of the parent node (QModelIndex) |
|
103 @return flag indicating a change (boolean) |
|
104 """ |
|
105 changed = False |
|
106 for row in range(self.__proxyModel.rowCount(parent)): |
|
107 child = self.__proxyModel.index(row, 0, parent) |
|
108 sourceIndex = self.__proxyModel.mapToSource(child) |
|
109 childNode = self.__bookmarksModel.node(sourceIndex) |
|
110 wasExpanded = childNode.expanded |
|
111 if self.bookmarksTree.isExpanded(child): |
|
112 childNode.expanded = True |
|
113 changed |= self.__saveExpandedNodes(child) |
|
114 else: |
|
115 childNode.expanded = False |
|
116 changed |= (wasExpanded != childNode.expanded) |
|
117 |
|
118 return changed |
|
119 |
|
120 def __expandNodes(self, node): |
|
121 """ |
|
122 Private method to expand all child nodes of a node. |
|
123 |
|
124 @param node reference to the bookmark node to expand (BookmarkNode) |
|
125 """ |
|
126 for childNode in node.children(): |
|
127 if childNode.expanded: |
|
128 idx = self.__bookmarksModel.nodeIndex(childNode) |
|
129 idx = self.__proxyModel.mapFromSource(idx) |
|
130 self.bookmarksTree.setExpanded(idx, True) |
|
131 self.__expandNodes(childNode) |
|
132 |
|
133 def __customContextMenuRequested(self, pos): |
|
134 """ |
|
135 Private slot to handle the context menu request for the bookmarks tree. |
|
136 |
|
137 @param pos position the context menu was requested (QPoint) |
|
138 """ |
|
139 menu = QMenu() |
|
140 idx = self.bookmarksTree.indexAt(pos) |
|
141 idx = idx.sibling(idx.row(), 0) |
|
142 sourceIndex = self.__proxyModel.mapToSource(idx) |
|
143 node = self.__bookmarksModel.node(sourceIndex) |
|
144 if idx.isValid() and node.type() != BookmarkNode.Folder: |
|
145 menu.addAction(self.trUtf8("&Open"), self.__openBookmarkInCurrentTab) |
|
146 menu.addAction(self.trUtf8("Open in New &Tab"), self.__openBookmarkInNewTab) |
|
147 menu.addSeparator() |
|
148 act = menu.addAction(self.trUtf8("Edit &Name"), self.__editName) |
|
149 act.setEnabled(idx.flags() & Qt.ItemIsEditable) |
|
150 if idx.isValid() and node.type() != BookmarkNode.Folder: |
|
151 menu.addAction(self.trUtf8("Edit &Address"), self.__editAddress) |
|
152 menu.addSeparator() |
|
153 act = menu.addAction(self.trUtf8("&Delete"), self.bookmarksTree.removeSelected) |
|
154 act.setEnabled(idx.flags() & Qt.ItemIsDragEnabled) |
|
155 menu.exec_(QCursor.pos()) |
|
156 |
|
157 def __activated(self, idx): |
|
158 """ |
|
159 Private slot to handle the activation of an entry. |
|
160 |
|
161 @param idx reference to the entry index (QModelIndex) |
|
162 """ |
|
163 self.__openBookmark(QApplication.keyboardModifiers() & Qt.ControlModifier) |
|
164 |
|
165 def __openBookmarkInCurrentTab(self): |
|
166 """ |
|
167 Private slot to open a bookmark in the current browser tab. |
|
168 """ |
|
169 self.__openBookmark(False) |
|
170 |
|
171 def __openBookmarkInNewTab(self): |
|
172 """ |
|
173 Private slot to open a bookmark in a new browser tab. |
|
174 """ |
|
175 self.__openBookmark(True) |
|
176 |
|
177 def __openBookmark(self, newTab): |
|
178 """ |
|
179 Private method to open a bookmark. |
|
180 |
|
181 @param newTab flag indicating to open the bookmark in a new tab (boolean) |
|
182 """ |
|
183 idx = self.bookmarksTree.currentIndex() |
|
184 sourceIndex = self.__proxyModel.mapToSource(idx) |
|
185 node = self.__bookmarksModel.node(sourceIndex) |
|
186 if not idx.parent().isValid() or \ |
|
187 node is None or \ |
|
188 node.type() == BookmarkNode.Folder: |
|
189 return |
|
190 if newTab: |
|
191 self.emit(SIGNAL("newUrl(const QUrl&, const QString&)"), |
|
192 idx.sibling(idx.row(), 1).data(BookmarksModel.UrlRole).toUrl(), |
|
193 idx.sibling(idx.row(), 0).data(Qt.DisplayRole).toString()) |
|
194 else: |
|
195 self.emit(SIGNAL("openUrl(const QUrl&, const QString&)"), |
|
196 idx.sibling(idx.row(), 1).data(BookmarksModel.UrlRole).toUrl(), |
|
197 idx.sibling(idx.row(), 0).data(Qt.DisplayRole).toString()) |
|
198 |
|
199 def __editName(self): |
|
200 """ |
|
201 Private slot to edit the name part of a bookmark. |
|
202 """ |
|
203 idx = self.bookmarksTree.currentIndex() |
|
204 idx = idx.sibling(idx.row(), 0) |
|
205 self.bookmarksTree.edit(idx) |
|
206 |
|
207 def __editAddress(self): |
|
208 """ |
|
209 Private slot to edit the address part of a bookmark. |
|
210 """ |
|
211 idx = self.bookmarksTree.currentIndex() |
|
212 idx = idx.sibling(idx.row(), 1) |
|
213 self.bookmarksTree.edit(idx) |
|
214 |
|
215 def __newFolder(self): |
|
216 """ |
|
217 Private slot to add a new bookmarks folder. |
|
218 """ |
|
219 currentIndex = self.bookmarksTree.currentIndex() |
|
220 idx = QModelIndex(currentIndex) |
|
221 sourceIndex = self.__proxyModel.mapToSource(idx) |
|
222 sourceNode = self.__bookmarksModel.node(sourceIndex) |
|
223 row = -1 # append new folder as the last item per default |
|
224 |
|
225 if sourceNode is not None and \ |
|
226 sourceNode.type() != BookmarkNode.Folder: |
|
227 # If the selected item is not a folder, add a new folder to the |
|
228 # parent folder, but directly below the selected item. |
|
229 idx = idx.parent() |
|
230 row = currentIndex.row() + 1 |
|
231 |
|
232 if not idx.isValid(): |
|
233 # Select bookmarks menu as default. |
|
234 idx = self.__proxyModel.index(1, 0) |
|
235 |
|
236 idx = self.__proxyModel.mapToSource(idx) |
|
237 parent = self.__bookmarksModel.node(idx) |
|
238 node = BookmarkNode(BookmarkNode.Folder) |
|
239 node.title = self.trUtf8("New Folder") |
|
240 self.__bookmarksManager.addBookmark(parent, node, row) |