8 """ |
8 """ |
9 |
9 |
10 import contextlib |
10 import contextlib |
11 |
11 |
12 from PyQt6.QtCore import ( |
12 from PyQt6.QtCore import ( |
13 Qt, QAbstractItemModel, QModelIndex, QUrl, QByteArray, QDataStream, |
13 Qt, |
14 QIODevice, QBuffer, QMimeData |
14 QAbstractItemModel, |
|
15 QModelIndex, |
|
16 QUrl, |
|
17 QByteArray, |
|
18 QDataStream, |
|
19 QIODevice, |
|
20 QBuffer, |
|
21 QMimeData, |
15 ) |
22 ) |
16 |
23 |
17 import UI.PixmapCache |
24 import UI.PixmapCache |
18 |
25 |
19 |
26 |
20 class BookmarksModel(QAbstractItemModel): |
27 class BookmarksModel(QAbstractItemModel): |
21 """ |
28 """ |
22 Class implementing the bookmark model. |
29 Class implementing the bookmark model. |
23 """ |
30 """ |
|
31 |
24 TypeRole = Qt.ItemDataRole.UserRole + 1 |
32 TypeRole = Qt.ItemDataRole.UserRole + 1 |
25 UrlRole = Qt.ItemDataRole.UserRole + 2 |
33 UrlRole = Qt.ItemDataRole.UserRole + 2 |
26 UrlStringRole = Qt.ItemDataRole.UserRole + 3 |
34 UrlStringRole = Qt.ItemDataRole.UserRole + 3 |
27 VisitCountRole = Qt.ItemDataRole.UserRole + 4 |
35 VisitCountRole = Qt.ItemDataRole.UserRole + 4 |
28 SeparatorRole = Qt.ItemDataRole.UserRole + 5 |
36 SeparatorRole = Qt.ItemDataRole.UserRole + 5 |
29 |
37 |
30 MIMETYPE = "application/bookmarks.xbel" |
38 MIMETYPE = "application/bookmarks.xbel" |
31 |
39 |
32 def __init__(self, manager, parent=None): |
40 def __init__(self, manager, parent=None): |
33 """ |
41 """ |
34 Constructor |
42 Constructor |
35 |
43 |
36 @param manager reference to the bookmark manager object |
44 @param manager reference to the bookmark manager object |
37 (BookmarksManager) |
45 (BookmarksManager) |
38 @param parent reference to the parent object (QObject) |
46 @param parent reference to the parent object (QObject) |
39 """ |
47 """ |
40 super().__init__(parent) |
48 super().__init__(parent) |
41 |
49 |
42 self.__endMacro = False |
50 self.__endMacro = False |
43 self.__bookmarksManager = manager |
51 self.__bookmarksManager = manager |
44 |
52 |
45 manager.entryAdded.connect(self.entryAdded) |
53 manager.entryAdded.connect(self.entryAdded) |
46 manager.entryRemoved.connect(self.entryRemoved) |
54 manager.entryRemoved.connect(self.entryRemoved) |
47 manager.entryChanged.connect(self.entryChanged) |
55 manager.entryChanged.connect(self.entryChanged) |
48 |
56 |
49 self.__headers = [ |
57 self.__headers = [ |
50 self.tr("Title"), |
58 self.tr("Title"), |
51 self.tr("Address"), |
59 self.tr("Address"), |
52 ] |
60 ] |
53 |
61 |
54 def bookmarksManager(self): |
62 def bookmarksManager(self): |
55 """ |
63 """ |
56 Public method to get a reference to the bookmarks manager. |
64 Public method to get a reference to the bookmarks manager. |
57 |
65 |
58 @return reference to the bookmarks manager object (BookmarksManager) |
66 @return reference to the bookmarks manager object (BookmarksManager) |
59 """ |
67 """ |
60 return self.__bookmarksManager |
68 return self.__bookmarksManager |
61 |
69 |
62 def nodeIndex(self, node): |
70 def nodeIndex(self, node): |
63 """ |
71 """ |
64 Public method to get a model index. |
72 Public method to get a model index. |
65 |
73 |
66 @param node reference to the node to get the index for (BookmarkNode) |
74 @param node reference to the node to get the index for (BookmarkNode) |
67 @return model index (QModelIndex) |
75 @return model index (QModelIndex) |
68 """ |
76 """ |
69 parent = node.parent() |
77 parent = node.parent() |
70 if parent is None: |
78 if parent is None: |
71 return QModelIndex() |
79 return QModelIndex() |
72 return self.createIndex(parent.children().index(node), 0, node) |
80 return self.createIndex(parent.children().index(node), 0, node) |
73 |
81 |
74 def entryAdded(self, node): |
82 def entryAdded(self, node): |
75 """ |
83 """ |
76 Public slot to add a bookmark node. |
84 Public slot to add a bookmark node. |
77 |
85 |
78 @param node reference to the bookmark node to add (BookmarkNode) |
86 @param node reference to the bookmark node to add (BookmarkNode) |
79 """ |
87 """ |
80 if node is None or node.parent() is None: |
88 if node is None or node.parent() is None: |
81 return |
89 return |
82 |
90 |
83 parent = node.parent() |
91 parent = node.parent() |
84 row = parent.children().index(node) |
92 row = parent.children().index(node) |
85 # node was already added so remove before beginInsertRows is called |
93 # node was already added so remove before beginInsertRows is called |
86 parent.remove(node) |
94 parent.remove(node) |
87 self.beginInsertRows(self.nodeIndex(parent), row, row) |
95 self.beginInsertRows(self.nodeIndex(parent), row, row) |
88 parent.add(node, row) |
96 parent.add(node, row) |
89 self.endInsertRows() |
97 self.endInsertRows() |
90 |
98 |
91 def entryRemoved(self, parent, row, node): |
99 def entryRemoved(self, parent, row, node): |
92 """ |
100 """ |
93 Public slot to remove a bookmark node. |
101 Public slot to remove a bookmark node. |
94 |
102 |
95 @param parent reference to the parent bookmark node (BookmarkNode) |
103 @param parent reference to the parent bookmark node (BookmarkNode) |
96 @param row row number of the node (integer) |
104 @param row row number of the node (integer) |
97 @param node reference to the bookmark node to remove (BookmarkNode) |
105 @param node reference to the bookmark node to remove (BookmarkNode) |
98 """ |
106 """ |
99 # node was already removed, re-add so beginRemoveRows works |
107 # node was already removed, re-add so beginRemoveRows works |
100 parent.add(node, row) |
108 parent.add(node, row) |
101 self.beginRemoveRows(self.nodeIndex(parent), row, row) |
109 self.beginRemoveRows(self.nodeIndex(parent), row, row) |
102 parent.remove(node) |
110 parent.remove(node) |
103 self.endRemoveRows() |
111 self.endRemoveRows() |
104 |
112 |
105 def entryChanged(self, node): |
113 def entryChanged(self, node): |
106 """ |
114 """ |
107 Public method to change a node. |
115 Public method to change a node. |
108 |
116 |
109 @param node reference to the bookmark node to change (BookmarkNode) |
117 @param node reference to the bookmark node to change (BookmarkNode) |
110 """ |
118 """ |
111 idx = self.nodeIndex(node) |
119 idx = self.nodeIndex(node) |
112 self.dataChanged.emit(idx, idx) |
120 self.dataChanged.emit(idx, idx) |
113 |
121 |
114 def removeRows(self, row, count, parent=None): |
122 def removeRows(self, row, count, parent=None): |
115 """ |
123 """ |
116 Public method to remove bookmarks from the model. |
124 Public method to remove bookmarks from the model. |
117 |
125 |
118 @param row row of the first bookmark to remove (integer) |
126 @param row row of the first bookmark to remove (integer) |
119 @param count number of bookmarks to remove (integer) |
127 @param count number of bookmarks to remove (integer) |
120 @param parent index of the parent bookmark node (QModelIndex) |
128 @param parent index of the parent bookmark node (QModelIndex) |
121 @return flag indicating successful removal (boolean) |
129 @return flag indicating successful removal (boolean) |
122 """ |
130 """ |
123 if parent is None: |
131 if parent is None: |
124 parent = QModelIndex() |
132 parent = QModelIndex() |
125 |
133 |
126 if row < 0 or count <= 0 or row + count > self.rowCount(parent): |
134 if row < 0 or count <= 0 or row + count > self.rowCount(parent): |
127 return False |
135 return False |
128 |
136 |
129 bookmarkNode = self.node(parent) |
137 bookmarkNode = self.node(parent) |
130 children = bookmarkNode.children()[row:(row + count)] |
138 children = bookmarkNode.children()[row : (row + count)] |
131 for node in children: |
139 for node in children: |
132 if node in ( |
140 if node in ( |
133 self.__bookmarksManager.menu(), |
141 self.__bookmarksManager.menu(), |
134 self.__bookmarksManager.toolbar() |
142 self.__bookmarksManager.toolbar(), |
135 ): |
143 ): |
136 continue |
144 continue |
137 self.__bookmarksManager.removeBookmark(node) |
145 self.__bookmarksManager.removeBookmark(node) |
138 |
146 |
139 if self.__endMacro: |
147 if self.__endMacro: |
140 self.__bookmarksManager.undoRedoStack().endMacro() |
148 self.__bookmarksManager.undoRedoStack().endMacro() |
141 self.__endMacro = False |
149 self.__endMacro = False |
142 |
150 |
143 return True |
151 return True |
144 |
152 |
145 def headerData(self, section, orientation, |
153 def headerData(self, section, orientation, role=Qt.ItemDataRole.DisplayRole): |
146 role=Qt.ItemDataRole.DisplayRole): |
|
147 """ |
154 """ |
148 Public method to get the header data. |
155 Public method to get the header data. |
149 |
156 |
150 @param section section number (integer) |
157 @param section section number (integer) |
151 @param orientation header orientation (Qt.Orientation) |
158 @param orientation header orientation (Qt.Orientation) |
152 @param role data role (Qt.ItemDataRole) |
159 @param role data role (Qt.ItemDataRole) |
153 @return header data |
160 @return header data |
154 """ |
161 """ |
155 if ( |
162 if ( |
156 orientation == Qt.Orientation.Horizontal and |
163 orientation == Qt.Orientation.Horizontal |
157 role == Qt.ItemDataRole.DisplayRole |
164 and role == Qt.ItemDataRole.DisplayRole |
158 ): |
165 ): |
159 with contextlib.suppress(IndexError): |
166 with contextlib.suppress(IndexError): |
160 return self.__headers[section] |
167 return self.__headers[section] |
161 return QAbstractItemModel.headerData(self, section, orientation, role) |
168 return QAbstractItemModel.headerData(self, section, orientation, role) |
162 |
169 |
163 def data(self, index, role=Qt.ItemDataRole.DisplayRole): |
170 def data(self, index, role=Qt.ItemDataRole.DisplayRole): |
164 """ |
171 """ |
165 Public method to get data from the model. |
172 Public method to get data from the model. |
166 |
173 |
167 @param index index of bookmark to get data for (QModelIndex) |
174 @param index index of bookmark to get data for (QModelIndex) |
168 @param role data role (integer) |
175 @param role data role (integer) |
169 @return bookmark data |
176 @return bookmark data |
170 """ |
177 """ |
171 if not index.isValid() or index.model() != self: |
178 if not index.isValid() or index.model() != self: |
172 return None |
179 return None |
173 |
180 |
174 from .BookmarkNode import BookmarkNode |
181 from .BookmarkNode import BookmarkNode |
175 |
182 |
176 bookmarkNode = self.node(index) |
183 bookmarkNode = self.node(index) |
177 if role in [Qt.ItemDataRole.EditRole, Qt.ItemDataRole.DisplayRole]: |
184 if role in [Qt.ItemDataRole.EditRole, Qt.ItemDataRole.DisplayRole]: |
178 if bookmarkNode.type() == BookmarkNode.Separator: |
185 if bookmarkNode.type() == BookmarkNode.Separator: |
179 if index.column() == 0: |
186 if index.column() == 0: |
180 return 50 * '\xB7' |
187 return 50 * "\xB7" |
181 elif index.column() == 1: |
188 elif index.column() == 1: |
182 return "" |
189 return "" |
183 |
190 |
184 if index.column() == 0: |
191 if index.column() == 0: |
185 return bookmarkNode.title |
192 return bookmarkNode.title |
186 elif index.column() == 1: |
193 elif index.column() == 1: |
187 return bookmarkNode.url |
194 return bookmarkNode.url |
188 |
195 |
189 elif role == BookmarksModel.UrlRole: |
196 elif role == BookmarksModel.UrlRole: |
190 return QUrl(bookmarkNode.url) |
197 return QUrl(bookmarkNode.url) |
191 |
198 |
192 elif role == BookmarksModel.UrlStringRole: |
199 elif role == BookmarksModel.UrlStringRole: |
193 return bookmarkNode.url |
200 return bookmarkNode.url |
194 |
201 |
195 elif role == BookmarksModel.VisitCountRole: |
202 elif role == BookmarksModel.VisitCountRole: |
196 return bookmarkNode.visitCount |
203 return bookmarkNode.visitCount |
197 |
204 |
198 elif role == BookmarksModel.TypeRole: |
205 elif role == BookmarksModel.TypeRole: |
199 return bookmarkNode.type() |
206 return bookmarkNode.type() |
200 |
207 |
201 elif role == BookmarksModel.SeparatorRole: |
208 elif role == BookmarksModel.SeparatorRole: |
202 return bookmarkNode.type() == BookmarkNode.Separator |
209 return bookmarkNode.type() == BookmarkNode.Separator |
203 |
210 |
204 elif ( |
211 elif role == Qt.ItemDataRole.DecorationRole and index.column() == 0: |
205 role == Qt.ItemDataRole.DecorationRole and |
|
206 index.column() == 0 |
|
207 ): |
|
208 if bookmarkNode.type() == BookmarkNode.Folder: |
212 if bookmarkNode.type() == BookmarkNode.Folder: |
209 return UI.PixmapCache.getIcon("dirOpen") |
213 return UI.PixmapCache.getIcon("dirOpen") |
210 import WebBrowser.WebBrowserWindow |
214 import WebBrowser.WebBrowserWindow |
|
215 |
211 return WebBrowser.WebBrowserWindow.WebBrowserWindow.icon( |
216 return WebBrowser.WebBrowserWindow.WebBrowserWindow.icon( |
212 QUrl(bookmarkNode.url)) |
217 QUrl(bookmarkNode.url) |
213 |
218 ) |
|
219 |
214 return None |
220 return None |
215 |
221 |
216 def columnCount(self, parent=None): |
222 def columnCount(self, parent=None): |
217 """ |
223 """ |
218 Public method to get the number of columns. |
224 Public method to get the number of columns. |
219 |
225 |
220 @param parent index of parent (QModelIndex) |
226 @param parent index of parent (QModelIndex) |
221 @return number of columns (integer) |
227 @return number of columns (integer) |
222 """ |
228 """ |
223 if parent is None: |
229 if parent is None: |
224 parent = QModelIndex() |
230 parent = QModelIndex() |
225 |
231 |
226 if parent.column() > 0: |
232 if parent.column() > 0: |
227 return 0 |
233 return 0 |
228 else: |
234 else: |
229 return len(self.__headers) |
235 return len(self.__headers) |
230 |
236 |
231 def rowCount(self, parent=None): |
237 def rowCount(self, parent=None): |
232 """ |
238 """ |
233 Public method to determine the number of rows. |
239 Public method to determine the number of rows. |
234 |
240 |
235 @param parent index of parent (QModelIndex) |
241 @param parent index of parent (QModelIndex) |
236 @return number of rows (integer) |
242 @return number of rows (integer) |
237 """ |
243 """ |
238 if parent is None: |
244 if parent is None: |
239 parent = QModelIndex() |
245 parent = QModelIndex() |
240 |
246 |
241 if parent.column() > 0: |
247 if parent.column() > 0: |
242 return 0 |
248 return 0 |
243 |
249 |
244 if not parent.isValid(): |
250 if not parent.isValid(): |
245 return len(self.__bookmarksManager.bookmarks().children()) |
251 return len(self.__bookmarksManager.bookmarks().children()) |
246 |
252 |
247 itm = parent.internalPointer() |
253 itm = parent.internalPointer() |
248 return len(itm.children()) |
254 return len(itm.children()) |
249 |
255 |
250 def index(self, row, column, parent=None): |
256 def index(self, row, column, parent=None): |
251 """ |
257 """ |
252 Public method to get a model index for a node cell. |
258 Public method to get a model index for a node cell. |
253 |
259 |
254 @param row row number (integer) |
260 @param row row number (integer) |
255 @param column column number (integer) |
261 @param column column number (integer) |
256 @param parent index of the parent (QModelIndex) |
262 @param parent index of the parent (QModelIndex) |
257 @return index (QModelIndex) |
263 @return index (QModelIndex) |
258 """ |
264 """ |
259 if parent is None: |
265 if parent is None: |
260 parent = QModelIndex() |
266 parent = QModelIndex() |
261 |
267 |
262 if ( |
268 if ( |
263 row < 0 or |
269 row < 0 |
264 column < 0 or |
270 or column < 0 |
265 row >= self.rowCount(parent) or |
271 or row >= self.rowCount(parent) |
266 column >= self.columnCount(parent) |
272 or column >= self.columnCount(parent) |
267 ): |
273 ): |
268 return QModelIndex() |
274 return QModelIndex() |
269 |
275 |
270 parentNode = self.node(parent) |
276 parentNode = self.node(parent) |
271 return self.createIndex(row, column, parentNode.children()[row]) |
277 return self.createIndex(row, column, parentNode.children()[row]) |
272 |
278 |
273 def parent(self, index=None): |
279 def parent(self, index=None): |
274 """ |
280 """ |
275 Public method to get the index of the parent node. |
281 Public method to get the index of the parent node. |
276 |
282 |
277 @param index index of the child node (QModelIndex) |
283 @param index index of the child node (QModelIndex) |
278 @return index of the parent node (QModelIndex) |
284 @return index of the parent node (QModelIndex) |
279 """ |
285 """ |
280 if index is None: |
286 if index is None: |
281 index = QModelIndex() |
287 index = QModelIndex() |
282 |
288 |
283 if not index.isValid(): |
289 if not index.isValid(): |
284 return QModelIndex() |
290 return QModelIndex() |
285 |
291 |
286 itemNode = self.node(index) |
292 itemNode = self.node(index) |
287 parentNode = itemNode.parent() if itemNode else None |
293 parentNode = itemNode.parent() if itemNode else None |
288 |
294 |
289 if ( |
295 if parentNode is None or parentNode == self.__bookmarksManager.bookmarks(): |
290 parentNode is None or |
|
291 parentNode == self.__bookmarksManager.bookmarks() |
|
292 ): |
|
293 return QModelIndex() |
296 return QModelIndex() |
294 |
297 |
295 # get the parent's row |
298 # get the parent's row |
296 grandParentNode = parentNode.parent() |
299 grandParentNode = parentNode.parent() |
297 parentRow = grandParentNode.children().index(parentNode) |
300 parentRow = grandParentNode.children().index(parentNode) |
298 return self.createIndex(parentRow, 0, parentNode) |
301 return self.createIndex(parentRow, 0, parentNode) |
299 |
302 |
300 def hasChildren(self, parent=None): |
303 def hasChildren(self, parent=None): |
301 """ |
304 """ |
302 Public method to check, if a parent node has some children. |
305 Public method to check, if a parent node has some children. |
303 |
306 |
304 @param parent index of the parent node (QModelIndex) |
307 @param parent index of the parent node (QModelIndex) |
305 @return flag indicating the presence of children (boolean) |
308 @return flag indicating the presence of children (boolean) |
306 """ |
309 """ |
307 if parent is None: |
310 if parent is None: |
308 parent = QModelIndex() |
311 parent = QModelIndex() |
309 |
312 |
310 if not parent.isValid(): |
313 if not parent.isValid(): |
311 return True |
314 return True |
312 |
315 |
313 from .BookmarkNode import BookmarkNode |
316 from .BookmarkNode import BookmarkNode |
|
317 |
314 parentNode = self.node(parent) |
318 parentNode = self.node(parent) |
315 return parentNode.type() == BookmarkNode.Folder |
319 return parentNode.type() == BookmarkNode.Folder |
316 |
320 |
317 def flags(self, index): |
321 def flags(self, index): |
318 """ |
322 """ |
319 Public method to get flags for a node cell. |
323 Public method to get flags for a node cell. |
320 |
324 |
321 @param index index of the node cell (QModelIndex) |
325 @param index index of the node cell (QModelIndex) |
322 @return flags (Qt.ItemFlags) |
326 @return flags (Qt.ItemFlags) |
323 """ |
327 """ |
324 if not index.isValid(): |
328 if not index.isValid(): |
325 return Qt.ItemFlag.NoItemFlags |
329 return Qt.ItemFlag.NoItemFlags |
326 |
330 |
327 node = self.node(index) |
331 node = self.node(index) |
328 type_ = node.type() |
332 type_ = node.type() |
329 flags = Qt.ItemFlag.ItemIsSelectable | Qt.ItemFlag.ItemIsEnabled |
333 flags = Qt.ItemFlag.ItemIsSelectable | Qt.ItemFlag.ItemIsEnabled |
330 |
334 |
331 if self.hasChildren(index): |
335 if self.hasChildren(index): |
332 flags |= Qt.ItemFlag.ItemIsDropEnabled |
336 flags |= Qt.ItemFlag.ItemIsDropEnabled |
333 |
337 |
334 if node in ( |
338 if node in (self.__bookmarksManager.menu(), self.__bookmarksManager.toolbar()): |
335 self.__bookmarksManager.menu(), |
|
336 self.__bookmarksManager.toolbar() |
|
337 ): |
|
338 return flags |
339 return flags |
339 |
340 |
340 flags |= Qt.ItemFlag.ItemIsDragEnabled |
341 flags |= Qt.ItemFlag.ItemIsDragEnabled |
341 |
342 |
342 from .BookmarkNode import BookmarkNode |
343 from .BookmarkNode import BookmarkNode |
343 if ( |
344 |
344 (index.column() == 0 and type_ != BookmarkNode.Separator) or |
345 if (index.column() == 0 and type_ != BookmarkNode.Separator) or ( |
345 (index.column() == 1 and type_ == BookmarkNode.Bookmark) |
346 index.column() == 1 and type_ == BookmarkNode.Bookmark |
346 ): |
347 ): |
347 flags |= Qt.ItemFlag.ItemIsEditable |
348 flags |= Qt.ItemFlag.ItemIsEditable |
348 |
349 |
349 return flags |
350 return flags |
350 |
351 |
351 def supportedDropActions(self): |
352 def supportedDropActions(self): |
352 """ |
353 """ |
353 Public method to report the supported drop actions. |
354 Public method to report the supported drop actions. |
354 |
355 |
355 @return supported drop actions (Qt.DropAction) |
356 @return supported drop actions (Qt.DropAction) |
356 """ |
357 """ |
357 return Qt.DropAction.CopyAction | Qt.DropAction.MoveAction |
358 return Qt.DropAction.CopyAction | Qt.DropAction.MoveAction |
358 |
359 |
359 def mimeTypes(self): |
360 def mimeTypes(self): |
360 """ |
361 """ |
361 Public method to report the supported mime types. |
362 Public method to report the supported mime types. |
362 |
363 |
363 @return supported mime types (list of strings) |
364 @return supported mime types (list of strings) |
364 """ |
365 """ |
365 return [self.MIMETYPE, "text/uri-list"] |
366 return [self.MIMETYPE, "text/uri-list"] |
366 |
367 |
367 def mimeData(self, indexes): |
368 def mimeData(self, indexes): |
368 """ |
369 """ |
369 Public method to return the mime data. |
370 Public method to return the mime data. |
370 |
371 |
371 @param indexes list of indexes (QModelIndexList) |
372 @param indexes list of indexes (QModelIndexList) |
372 @return mime data (QMimeData) |
373 @return mime data (QMimeData) |
373 """ |
374 """ |
374 from .XbelWriter import XbelWriter |
375 from .XbelWriter import XbelWriter |
375 |
376 |
376 data = QByteArray() |
377 data = QByteArray() |
377 stream = QDataStream(data, QIODevice.OpenModeFlag.WriteOnly) |
378 stream = QDataStream(data, QIODevice.OpenModeFlag.WriteOnly) |
378 urls = [] |
379 urls = [] |
379 |
380 |
380 for index in indexes: |
381 for index in indexes: |
381 if index.column() != 0 or not index.isValid(): |
382 if index.column() != 0 or not index.isValid(): |
382 continue |
383 continue |
383 |
384 |
384 encodedData = QByteArray() |
385 encodedData = QByteArray() |
385 buffer = QBuffer(encodedData) |
386 buffer = QBuffer(encodedData) |
386 buffer.open(QIODevice.OpenModeFlag.ReadWrite) |
387 buffer.open(QIODevice.OpenModeFlag.ReadWrite) |
387 writer = XbelWriter() |
388 writer = XbelWriter() |
388 parentNode = self.node(index) |
389 parentNode = self.node(index) |
389 writer.write(buffer, parentNode) |
390 writer.write(buffer, parentNode) |
390 stream << encodedData |
391 stream << encodedData |
391 urls.append(index.data(self.UrlRole)) |
392 urls.append(index.data(self.UrlRole)) |
392 |
393 |
393 mdata = QMimeData() |
394 mdata = QMimeData() |
394 mdata.setData(self.MIMETYPE, data) |
395 mdata.setData(self.MIMETYPE, data) |
395 mdata.setUrls(urls) |
396 mdata.setUrls(urls) |
396 return mdata |
397 return mdata |
397 |
398 |
398 def dropMimeData(self, data, action, row, column, parent): |
399 def dropMimeData(self, data, action, row, column, parent): |
399 """ |
400 """ |
400 Public method to accept the mime data of a drop action. |
401 Public method to accept the mime data of a drop action. |
401 |
402 |
402 @param data reference to the mime data (QMimeData) |
403 @param data reference to the mime data (QMimeData) |
403 @param action drop action requested (Qt.DropAction) |
404 @param action drop action requested (Qt.DropAction) |
404 @param row row number (integer) |
405 @param row row number (integer) |
405 @param column column number (integer) |
406 @param column column number (integer) |
406 @param parent index of the parent node (QModelIndex) |
407 @param parent index of the parent node (QModelIndex) |
407 @return flag indicating successful acceptance of the data (boolean) |
408 @return flag indicating successful acceptance of the data (boolean) |
408 """ |
409 """ |
409 if action == Qt.DropAction.IgnoreAction: |
410 if action == Qt.DropAction.IgnoreAction: |
410 return True |
411 return True |
411 |
412 |
412 if column > 0: |
413 if column > 0: |
413 return False |
414 return False |
414 |
415 |
415 parentNode = self.node(parent) |
416 parentNode = self.node(parent) |
416 |
417 |
417 if not data.hasFormat(self.MIMETYPE): |
418 if not data.hasFormat(self.MIMETYPE): |
418 if not data.hasUrls(): |
419 if not data.hasUrls(): |
419 return False |
420 return False |
420 |
421 |
421 from .BookmarkNode import BookmarkNode |
422 from .BookmarkNode import BookmarkNode |
|
423 |
422 node = BookmarkNode(BookmarkNode.Bookmark, parentNode) |
424 node = BookmarkNode(BookmarkNode.Bookmark, parentNode) |
423 node.url = bytes(data.urls()[0].toEncoded()).decode() |
425 node.url = bytes(data.urls()[0].toEncoded()).decode() |
424 |
426 |
425 if data.hasText(): |
427 if data.hasText(): |
426 node.title = data.text() |
428 node.title = data.text() |
427 else: |
429 else: |
428 node.title = node.url |
430 node.title = node.url |
429 |
431 |
430 self.__bookmarksManager.addBookmark(parentNode, node, row) |
432 self.__bookmarksManager.addBookmark(parentNode, node, row) |
431 return True |
433 return True |
432 |
434 |
433 ba = data.data(self.MIMETYPE) |
435 ba = data.data(self.MIMETYPE) |
434 stream = QDataStream(ba, QIODevice.OpenModeFlag.ReadOnly) |
436 stream = QDataStream(ba, QIODevice.OpenModeFlag.ReadOnly) |
435 if stream.atEnd(): |
437 if stream.atEnd(): |
436 return False |
438 return False |
437 |
439 |
438 undoStack = self.__bookmarksManager.undoRedoStack() |
440 undoStack = self.__bookmarksManager.undoRedoStack() |
439 undoStack.beginMacro("Move Bookmarks") |
441 undoStack.beginMacro("Move Bookmarks") |
440 |
442 |
441 from .XbelReader import XbelReader |
443 from .XbelReader import XbelReader |
|
444 |
442 while not stream.atEnd(): |
445 while not stream.atEnd(): |
443 encodedData = QByteArray() |
446 encodedData = QByteArray() |
444 stream >> encodedData |
447 stream >> encodedData |
445 buffer = QBuffer(encodedData) |
448 buffer = QBuffer(encodedData) |
446 buffer.open(QIODevice.OpenModeFlag.ReadOnly) |
449 buffer.open(QIODevice.OpenModeFlag.ReadOnly) |
447 |
450 |
448 reader = XbelReader() |
451 reader = XbelReader() |
449 rootNode = reader.read(buffer) |
452 rootNode = reader.read(buffer) |
450 for bookmarkNode in rootNode.children(): |
453 for bookmarkNode in rootNode.children(): |
451 rootNode.remove(bookmarkNode) |
454 rootNode.remove(bookmarkNode) |
452 row = max(0, row) |
455 row = max(0, row) |
453 self.__bookmarksManager.addBookmark( |
456 self.__bookmarksManager.addBookmark(parentNode, bookmarkNode, row) |
454 parentNode, bookmarkNode, row) |
|
455 self.__endMacro = True |
457 self.__endMacro = True |
456 |
458 |
457 return True |
459 return True |
458 |
460 |
459 def setData(self, index, value, role=Qt.ItemDataRole.EditRole): |
461 def setData(self, index, value, role=Qt.ItemDataRole.EditRole): |
460 """ |
462 """ |
461 Public method to set the data of a node cell. |
463 Public method to set the data of a node cell. |
462 |
464 |
463 @param index index of the node cell (QModelIndex) |
465 @param index index of the node cell (QModelIndex) |
464 @param value value to be set |
466 @param value value to be set |
465 @param role role of the data (integer) |
467 @param role role of the data (integer) |
466 @return flag indicating success (boolean) |
468 @return flag indicating success (boolean) |
467 """ |
469 """ |
468 if ( |
470 if not index.isValid() or (self.flags(index) & Qt.ItemFlag.ItemIsEditable) == 0: |
469 not index.isValid() or |
|
470 (self.flags(index) & Qt.ItemFlag.ItemIsEditable) == 0 |
|
471 ): |
|
472 return False |
471 return False |
473 |
472 |
474 item = self.node(index) |
473 item = self.node(index) |
475 |
474 |
476 if role in (Qt.ItemDataRole.EditRole, Qt.ItemDataRole.DisplayRole): |
475 if role in (Qt.ItemDataRole.EditRole, Qt.ItemDataRole.DisplayRole): |
477 if index.column() == 0: |
476 if index.column() == 0: |
478 self.__bookmarksManager.setTitle(item, value) |
477 self.__bookmarksManager.setTitle(item, value) |
479 elif index.column() == 1: |
478 elif index.column() == 1: |
480 self.__bookmarksManager.setUrl(item, value) |
479 self.__bookmarksManager.setUrl(item, value) |
481 else: |
480 else: |
482 return False |
481 return False |
483 |
482 |
484 elif role == BookmarksModel.UrlRole: |
483 elif role == BookmarksModel.UrlRole: |
485 self.__bookmarksManager.setUrl(item, value.toString()) |
484 self.__bookmarksManager.setUrl(item, value.toString()) |
486 |
485 |
487 elif role == BookmarksModel.UrlStringRole: |
486 elif role == BookmarksModel.UrlStringRole: |
488 self.__bookmarksManager.setUrl(item, value) |
487 self.__bookmarksManager.setUrl(item, value) |
489 |
488 |
490 elif role == BookmarksModel.VisitCountRole: |
489 elif role == BookmarksModel.VisitCountRole: |
491 self.__bookmarksManager.setVisitCount(item, value) |
490 self.__bookmarksManager.setVisitCount(item, value) |
492 |
491 |
493 else: |
492 else: |
494 return False |
493 return False |
495 |
494 |
496 return True |
495 return True |
497 |
496 |
498 def node(self, index): |
497 def node(self, index): |
499 """ |
498 """ |
500 Public method to get a bookmark node given its index. |
499 Public method to get a bookmark node given its index. |
501 |
500 |
502 @param index index of the node (QModelIndex) |
501 @param index index of the node (QModelIndex) |
503 @return bookmark node (BookmarkNode) |
502 @return bookmark node (BookmarkNode) |
504 """ |
503 """ |
505 itemNode = index.internalPointer() |
504 itemNode = index.internalPointer() |
506 if itemNode is None: |
505 if itemNode is None: |