45
|
1 /****************************************************************************
|
|
2 **
|
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
|
4 ** Contact: Qt Software Information (qt-info@nokia.com)
|
|
5 **
|
|
6 ** This file is part of the demonstration applications of the Qt Toolkit.
|
|
7 **
|
|
8 ** $QT_BEGIN_LICENSE:LGPL$
|
|
9 ** Commercial Usage
|
|
10 ** Licensees holding valid Qt Commercial licenses may use this file in
|
|
11 ** accordance with the Qt Commercial License Agreement provided with the
|
|
12 ** Software or, alternatively, in accordance with the terms contained in
|
|
13 ** a written agreement between you and Nokia.
|
|
14 **
|
|
15 ** GNU Lesser General Public License Usage
|
|
16 ** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
17 ** General Public License version 2.1 as published by the Free Software
|
|
18 ** Foundation and appearing in the file LICENSE.LGPL included in the
|
|
19 ** packaging of this file. Please review the following information to
|
|
20 ** ensure the GNU Lesser General Public License version 2.1 requirements
|
|
21 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
22 **
|
|
23 ** In addition, as a special exception, Nokia gives you certain
|
|
24 ** additional rights. These rights are described in the Nokia Qt LGPL
|
|
25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
|
|
26 ** package.
|
|
27 **
|
|
28 ** GNU General Public License Usage
|
|
29 ** Alternatively, this file may be used under the terms of the GNU
|
|
30 ** General Public License version 3.0 as published by the Free Software
|
|
31 ** Foundation and appearing in the file LICENSE.GPL included in the
|
|
32 ** packaging of this file. Please review the following information to
|
|
33 ** ensure the GNU General Public License version 3.0 requirements will be
|
|
34 ** met: http://www.gnu.org/copyleft/gpl.html.
|
|
35 **
|
|
36 ** If you are unsure which license is appropriate for your use, please
|
|
37 ** contact the sales department at qt-sales@nokia.com.
|
|
38 ** $QT_END_LICENSE$
|
|
39 **
|
|
40 ****************************************************************************/
|
|
41
|
72
|
42 module bookmarks;
|
45
|
43
|
|
44
|
72
|
45 import qt.core.QObject;
|
|
46 import qt.core.QAbstractItemModel;
|
|
47
|
|
48
|
|
49 import qt.core.QBuffer;
|
|
50 import qt.core.QFile;
|
|
51 import qt.core.QMimeData;
|
94
|
52 import qt.core.QPersistentModelIndex;
|
72
|
53
|
94
|
54 import qt.gui.QUndoStack;
|
|
55 import qt.gui.QUndoCommand;
|
72
|
56 import qt.gui.QDesktopServices;
|
|
57 import qt.gui.QDragEnterEvent;
|
|
58 import qt.gui.QFileDialog;
|
|
59 import qt.gui.QHeaderView;
|
|
60 import qt.gui.QIcon;
|
|
61 import qt.gui.QMessageBox;
|
|
62 import qt.gui.QToolButton;
|
|
63
|
94
|
64 import qt.webkit.QWebSettings;
|
72
|
65
|
94
|
66 //import qt.core.QDebug;
|
72
|
67
|
45
|
68 import bookmarks;
|
|
69 import autosaver;
|
|
70 import browserapplication;
|
|
71 import history;
|
|
72 import xbel;
|
|
73
|
|
74
|
77
|
75 const string BOOKMARKBAR = "Bookmarks Bar";
|
|
76 const string BOOKMARKMENU = "Bookmarks Menu";
|
45
|
77
|
|
78
|
|
79 /*!
|
73
|
80 Bookmark manager, owner of the bookmarks, loads, saves and basic tasks
|
|
81 */
|
45
|
82 class BookmarksManager : public QObject
|
|
83 {
|
74
|
84 mixin Signal!("entryAdded", BookmarkNode /*item*/);
|
|
85 mixin Signal!("entryRemoved", BookmarkNode /*parent*/, int /*row*/, BookmarkNode /*item*/);
|
|
86 mixin Signal!("entryChanged", BookmarkNode /*item*/);
|
45
|
87
|
|
88 public:
|
73
|
89
|
|
90 this(QObject parent = null)
|
|
91 {
|
|
92 super(parent);
|
|
93 m_loaded = false;
|
|
94 m_saveTimer = new AutoSaver(this);
|
|
95 m_bookmarkRootNode = null;
|
|
96 m_bookmarkModel = null;
|
|
97 this.entryAdded.connect(&m_saveTimer.changeOccurred);
|
|
98 this.entryRemoved.connect(&m_saveTimer.changeOccurred);
|
|
99 this.entryChanged.connect(&m_saveTimer.changeOccurred);
|
|
100 }
|
45
|
101
|
73
|
102 ~this()
|
|
103 {
|
|
104 m_saveTimer.saveIfNeccessary();
|
|
105 }
|
45
|
106
|
73
|
107 void addBookmark(BookmarkNode parent, BookmarkNode node, int row = -1)
|
|
108 {
|
|
109 if (!m_loaded)
|
|
110 return;
|
|
111 assert(parent);
|
|
112 InsertBookmarksCommand command = new InsertBookmarksCommand(this, parent, node, row);
|
|
113 m_commands.push(command);
|
|
114 }
|
45
|
115
|
74
|
116 void removeBookmark(BookmarkNode node)
|
73
|
117 {
|
|
118 if (!m_loaded)
|
|
119 return;
|
|
120
|
|
121 assert(node);
|
|
122 BookmarkNode parent = node.parent();
|
|
123 int row = parent.children().indexOf(node);
|
|
124 RemoveBookmarksCommand command = new RemoveBookmarksCommand(this, parent, row);
|
|
125 m_commands.push(command);
|
|
126 }
|
|
127
|
77
|
128 void setTitle(BookmarkNode node, string newTitle)
|
73
|
129 {
|
|
130 if (!m_loaded)
|
|
131 return;
|
|
132
|
|
133 assert(node);
|
|
134 ChangeBookmarkCommand command = new ChangeBookmarkCommand(this, node, newTitle, true);
|
|
135 m_commands.push(command);
|
|
136 }
|
45
|
137
|
77
|
138 void setUrl(BookmarkNode node, string newUrl)
|
73
|
139 {
|
|
140 if (!m_loaded)
|
|
141 return;
|
45
|
142
|
73
|
143 assert(node);
|
|
144 ChangeBookmarkCommand command = new ChangeBookmarkCommand(this, node, newUrl, false);
|
|
145 m_commands.push(command);
|
|
146 }
|
45
|
147
|
73
|
148 void changeExpanded()
|
|
149 {
|
|
150 m_saveTimer.changeOccurred();
|
|
151 }
|
45
|
152
|
74
|
153 BookmarkNode bookmarks()
|
73
|
154 {
|
|
155 if (!m_loaded)
|
|
156 load();
|
|
157 return m_bookmarkRootNode;
|
|
158 }
|
45
|
159
|
74
|
160 BookmarkNode menu()
|
73
|
161 {
|
|
162 if (!m_loaded)
|
|
163 load();
|
45
|
164
|
73
|
165 for (int i = m_bookmarkRootNode.children().count() - 1; i >= 0; --i) {
|
77
|
166 BookmarkNode node = m_bookmarkRootNode.children()[i];
|
73
|
167 if (node.title == tr(BOOKMARKMENU))
|
|
168 return node;
|
|
169 }
|
|
170 assert(false);
|
|
171 return 0;
|
|
172 }
|
45
|
173
|
74
|
174 BookmarkNode toolbar()
|
73
|
175 {
|
|
176 if (!m_loaded)
|
|
177 load();
|
45
|
178
|
73
|
179 for (int i = m_bookmarkRootNode.children().count() - 1; i >= 0; --i) {
|
77
|
180 BookmarkNode node = m_bookmarkRootNode.children()[i];
|
73
|
181 if (node.title == tr(BOOKMARKBAR))
|
|
182 return node;
|
|
183 }
|
|
184 assert(false);
|
|
185 return 0;
|
|
186 }
|
45
|
187
|
73
|
188 BookmarksModel bookmarksModel()
|
|
189 {
|
|
190 if (!m_bookmarkModel)
|
|
191 m_bookmarkModel = new BookmarksModel(this, this);
|
|
192 return m_bookmarkModel;
|
|
193 }
|
45
|
194
|
73
|
195 QUndoStack undoRedoStack() { return m_commands; };
|
45
|
196
|
73
|
197 public:
|
|
198
|
|
199 void importBookmarks()
|
|
200 {
|
77
|
201 string fileName = QFileDialog.getOpenFileName(0, tr("Open File"), null, tr("XBEL (*.xbel *.xml)"));
|
73
|
202 if (fileName.isEmpty())
|
|
203 return;
|
45
|
204
|
73
|
205 XbelReader reader;
|
|
206 BookmarkNode importRootNode = reader.read(fileName);
|
|
207 if (reader.error() != QXmlStreamReader.NoError) {
|
80
|
208 QMessageBox.warning(0, "Loading Bookmark",
|
73
|
209 tr("Error when loading bookmarks on line %1, column %2:\n"
|
|
210 "%3").arg(reader.lineNumber()).arg(reader.columnNumber()).arg(reader.errorString()));
|
|
211 }
|
45
|
212
|
73
|
213 importRootNode.setType(BookmarkNode.Folder);
|
|
214 importRootNode.title = (tr("Imported %1").arg(QDate.currentDate().toString(Qt.SystemLocaleShortDate)));
|
|
215 addBookmark(menu(), importRootNode);
|
|
216 }
|
45
|
217
|
|
218
|
73
|
219 void exportBookmarks()
|
|
220 {
|
77
|
221 string fileName = QFileDialog.getSaveFileName(0, tr("Save File"),
|
73
|
222 tr("%1 Bookmarks.xbel").arg(QCoreApplication.applicationName()),
|
|
223 tr("XBEL (*.xbel *.xml)"));
|
|
224 if (fileName.isEmpty())
|
|
225 return;
|
45
|
226
|
73
|
227 XbelWriter writer;
|
|
228 if (!writer.write(fileName, m_bookmarkRootNode))
|
|
229 QMessageBox.critical(0, tr("Export error"), tr("error saving bookmarks"));
|
|
230 }
|
45
|
231
|
73
|
232 private:
|
|
233
|
|
234 void save()
|
|
235 {
|
|
236 if (!m_loaded)
|
|
237 return;
|
45
|
238
|
73
|
239 XbelWriter writer;
|
77
|
240 string dir = QDesktopServices.storageLocation(QDesktopServices.DataLocation);
|
80
|
241 string bookmarkFile = dir ~ "/bookmarks.xbel";
|
73
|
242 if (!writer.write(bookmarkFile, m_bookmarkRootNode))
|
94
|
243 qWarning("BookmarkManager: error saving to" ~ bookmarkFile);
|
73
|
244 }
|
45
|
245
|
|
246 private:
|
73
|
247
|
|
248 void load()
|
|
249 {
|
|
250 if (m_loaded)
|
|
251 return;
|
|
252 m_loaded = true;
|
45
|
253
|
77
|
254 string dir = QDesktopServices.storageLocation(QDesktopServices.DataLocation);
|
80
|
255 string bookmarkFile = dir ~ "/bookmarks.xbel";
|
73
|
256 if (!QFile.exists(bookmarkFile))
|
80
|
257 bookmarkFile = ":defaultbookmarks.xbel";
|
45
|
258
|
73
|
259 XbelReader reader;
|
|
260 m_bookmarkRootNode = reader.read(bookmarkFile);
|
|
261 if (reader.error() != QXmlStreamReader.NoError) {
|
80
|
262 QMessageBox.warning(0, "Loading Bookmark",
|
73
|
263 tr("Error when loading bookmarks on line %1, column %2:\n"
|
|
264 "%3").arg(reader.lineNumber()).arg(reader.columnNumber()).arg(reader.errorString()));
|
|
265 }
|
45
|
266
|
73
|
267 BookmarkNode toolbar = null;
|
|
268 BookmarkNode menu = null;
|
74
|
269 BookmarkNode[] others;
|
73
|
270 for (int i = m_bookmarkRootNode.children().count() - 1; i >= 0; --i) {
|
77
|
271 BookmarkNode node = m_bookmarkRootNode.children()[i];
|
73
|
272 if (node.type() == BookmarkNode.Folder) {
|
|
273 // Automatically convert
|
|
274 if (node.title == tr("Toolbar Bookmarks") && !toolbar) {
|
|
275 node.title = tr(BOOKMARKBAR);
|
|
276 }
|
|
277 if (node.title == tr(BOOKMARKBAR) && !toolbar) {
|
|
278 toolbar = node;
|
|
279 }
|
45
|
280
|
73
|
281 // Automatically convert
|
|
282 if (node.title == tr("Menu") && !menu) {
|
|
283 node.title = tr(BOOKMARKMENU);
|
|
284 }
|
|
285 if (node.title == tr(BOOKMARKMENU) && !menu) {
|
|
286 menu = node;
|
|
287 }
|
|
288 } else {
|
77
|
289 others ~= node;
|
73
|
290 }
|
|
291 m_bookmarkRootNode.remove(node);
|
|
292 }
|
|
293 assert(m_bookmarkRootNode.children().count() == 0);
|
|
294 if (!toolbar) {
|
|
295 toolbar = new BookmarkNode(BookmarkNode.Folder, m_bookmarkRootNode);
|
|
296 toolbar.title = tr(BOOKMARKBAR);
|
|
297 } else {
|
|
298 m_bookmarkRootNode.add(toolbar);
|
|
299 }
|
45
|
300
|
73
|
301 if (!menu) {
|
|
302 menu = new BookmarkNode(BookmarkNode.Folder, m_bookmarkRootNode);
|
|
303 menu.title = tr(BOOKMARKMENU);
|
|
304 } else {
|
|
305 m_bookmarkRootNode.add(menu);
|
|
306 }
|
45
|
307
|
77
|
308 for (int i = 0; i < others.length; ++i)
|
|
309 menu.add(others[i]);
|
73
|
310 }
|
45
|
311
|
73
|
312 bool m_loaded;
|
|
313 AutoSaver m_saveTimer;
|
|
314 BookmarkNode m_bookmarkRootNode;
|
|
315 BookmarksModel m_bookmarkModel;
|
|
316 QUndoStack m_commands;
|
72
|
317 }
|
45
|
318
|
|
319 class RemoveBookmarksCommand : public QUndoCommand
|
|
320 {
|
73
|
321 public:
|
45
|
322
|
73
|
323 this(BookmarksManager m_bookmarkManagaer, BookmarkNode parent, int row)
|
|
324 {
|
74
|
325 super(BookmarksManager.tr("Remove Bookmark"));
|
73
|
326 m_row = row;
|
|
327 m_bookmarkManagaer = m_bookmarkManagaer;
|
|
328 m_node = parent.children().value(row);
|
|
329 m_parent = parent;
|
|
330 m_done = false;
|
|
331 }
|
45
|
332
|
73
|
333 ~this()
|
|
334 {
|
|
335 if (m_done && !m_node.parent()) {
|
|
336 delete m_node;
|
|
337 }
|
|
338 }
|
45
|
339
|
73
|
340 void undo()
|
|
341 {
|
|
342 m_parent.add(m_node, m_row);
|
74
|
343 m_bookmarkManagaer.entryAdded.emit(m_node);
|
73
|
344 m_done = false;
|
|
345 }
|
45
|
346
|
73
|
347 void redo()
|
|
348 {
|
|
349 m_parent.remove(m_node);
|
74
|
350 m_bookmarkManagaer.entryRemoved.emit(m_parent, m_row, m_node);
|
73
|
351 m_done = true;
|
|
352 }
|
45
|
353
|
|
354 protected:
|
73
|
355
|
|
356 int m_row;
|
|
357 BookmarksManager m_bookmarkManagaer;
|
|
358 BookmarkNode m_node;
|
|
359 BookmarkNode m_parent;
|
|
360 bool m_done;
|
|
361 }
|
45
|
362
|
|
363 class InsertBookmarksCommand : public RemoveBookmarksCommand
|
|
364 {
|
73
|
365 public:
|
|
366 this(BookmarksManager m_bookmarkManagaer, BookmarkNode parent, BookmarkNode node, int row)
|
|
367 {
|
|
368 super(m_bookmarkManagaer, parent, row);
|
45
|
369
|
73
|
370 setText(BookmarksManager.tr("Insert Bookmark"));
|
|
371 m_node = node;
|
|
372 }
|
45
|
373
|
73
|
374 void undo() { RemoveBookmarksCommand.redo(); }
|
|
375 void redo() { RemoveBookmarksCommand.undo(); }
|
45
|
376 }
|
|
377
|
|
378 class ChangeBookmarkCommand : public QUndoCommand
|
|
379 {
|
73
|
380 public:
|
45
|
381
|
77
|
382 this(BookmarksManager m_bookmarkManagaer, BookmarkNode node, string newValue, bool title)
|
73
|
383 {
|
|
384 super();
|
|
385 m_bookmarkManagaer = m_bookmarkManagaer;
|
|
386 m_title = title;
|
|
387 m_newValue = newValue;
|
|
388 m_node = node;
|
|
389 if (m_title) {
|
|
390 m_oldValue = m_node.title;
|
|
391 setText(BookmarksManager.tr("Name Change"));
|
|
392 } else {
|
|
393 m_oldValue = m_node.url;
|
|
394 setText(BookmarksManager.tr("Address Change"));
|
|
395 }
|
|
396 }
|
45
|
397
|
73
|
398 void undo()
|
|
399 {
|
|
400 if (m_title)
|
|
401 m_node.title = m_oldValue;
|
|
402 else
|
|
403 m_node.url = m_oldValue;
|
74
|
404 m_bookmarkManagaer.entryChanged.emit(m_node);
|
73
|
405 }
|
45
|
406
|
73
|
407 void redo()
|
|
408 {
|
|
409 if (m_title)
|
|
410 m_node.title = m_newValue;
|
|
411 else
|
|
412 m_node.url = m_newValue;
|
74
|
413 m_bookmarkManagaer.entryChanged.emit(m_node);
|
73
|
414 }
|
45
|
415
|
|
416 private:
|
73
|
417
|
|
418 BookmarksManager m_bookmarkManagaer;
|
|
419 bool m_title;
|
77
|
420 string m_oldValue;
|
|
421 string m_newValue;
|
73
|
422 BookmarkNode m_node;
|
45
|
423 }
|
|
424
|
|
425 /*!
|
73
|
426 BookmarksModel is a QAbstractItemModel wrapper around the BookmarkManager
|
|
427 */
|
72
|
428 import qt.gui.QIcon;
|
|
429
|
45
|
430 class BookmarksModel : public QAbstractItemModel
|
|
431 {
|
73
|
432 public:
|
45
|
433
|
73
|
434 void entryAdded(BookmarkNode item)
|
|
435 {
|
|
436 assert(item && item.parent());
|
|
437 int row = item.parent().children().indexOf(item);
|
|
438 BookmarkNode parent = item.parent();
|
|
439 // item was already added so remove beore beginInsertRows is called
|
|
440 parent.remove(item);
|
|
441 beginInsertRows(index(parent), row, row);
|
|
442 parent.add(item, row);
|
|
443 endInsertRows();
|
|
444 }
|
45
|
445
|
74
|
446 void entryRemoved(BookmarkNode parent, int row, BookmarkNode item)
|
73
|
447 {
|
|
448 // item was already removed, re-add so beginRemoveRows works
|
|
449 parent.add(item, row);
|
|
450 beginRemoveRows(index(parent), row, row);
|
|
451 parent.remove(item);
|
|
452 endRemoveRows();
|
|
453 }
|
45
|
454
|
74
|
455 void entryChanged(BookmarkNode item)
|
73
|
456 {
|
|
457 QModelIndex idx = index(item);
|
74
|
458 dataChanged.emit(idx, idx);
|
73
|
459 }
|
|
460
|
45
|
461 public:
|
73
|
462
|
|
463 enum Roles {
|
|
464 TypeRole = Qt.UserRole + 1,
|
|
465 UrlRole = Qt.UserRole + 2,
|
|
466 UrlStringRole = Qt.UserRole + 3,
|
|
467 SeparatorRole = Qt.UserRole + 4
|
74
|
468 };
|
45
|
469
|
74
|
470 this(BookmarksManager bookmarkManager, QObject parent = null)
|
73
|
471 {
|
74
|
472 super(parent);
|
73
|
473 m_endMacro = false;
|
|
474 m_bookmarksManager = bookmarkManager;
|
|
475 bookmarkManager.entryAdded.connect(&this.entryAdded);
|
|
476 bookmarkManager.entryRemoved.connect(&this.entryRemoved);
|
|
477 bookmarkManager.entryChanged.connect(&this.entryChanged);
|
|
478 }
|
45
|
479
|
74
|
480 BookmarksManager bookmarksManager()
|
|
481 {
|
|
482 return m_bookmarksManager;
|
|
483 }
|
45
|
484
|
74
|
485 QVariant headerData(int section, Qt.Orientation orientation, int role = Qt.DisplayRole)
|
73
|
486 {
|
|
487 if (orientation == Qt.Horizontal && role == Qt.DisplayRole) {
|
|
488 switch (section) {
|
|
489 case 0: return tr("Title");
|
|
490 case 1: return tr("Address");
|
|
491 }
|
|
492 }
|
|
493 return QAbstractItemModel.headerData(section, orientation, role);
|
|
494 }
|
45
|
495
|
73
|
496 QVariant data(QModelIndex index, int role = Qt.DisplayRole)
|
|
497 {
|
|
498 if (!index.isValid() || index.model() != this)
|
77
|
499 return QVariant();
|
45
|
500
|
73
|
501 BookmarkNode bookmarkNode = node(index);
|
|
502 switch (role) {
|
|
503 case Qt.EditRole:
|
|
504 case Qt.DisplayRole:
|
|
505 if (bookmarkNode.type() == BookmarkNode.Separator) {
|
|
506 switch (index.column()) {
|
|
507 case 0: return QString(50, 0xB7);
|
94
|
508 case 1: return null;
|
73
|
509 }
|
|
510 }
|
45
|
511
|
73
|
512 switch (index.column()) {
|
|
513 case 0: return bookmarkNode.title;
|
|
514 case 1: return bookmarkNode.url;
|
|
515 }
|
|
516 break;
|
|
517 case BookmarksModel.UrlRole:
|
94
|
518 return new QUrl(bookmarkNode.url);
|
73
|
519 break;
|
|
520 case BookmarksModel.UrlStringRole:
|
|
521 return bookmarkNode.url;
|
|
522 break;
|
|
523 case BookmarksModel.TypeRole:
|
|
524 return bookmarkNode.type();
|
|
525 break;
|
|
526 case BookmarksModel.SeparatorRole:
|
|
527 return (bookmarkNode.type() == BookmarkNode.Separator);
|
|
528 break;
|
|
529 case Qt.DecorationRole:
|
|
530 if (index.column() == 0) {
|
|
531 if (bookmarkNode.type() == BookmarkNode.Folder)
|
|
532 return QApplication.style().standardIcon(QStyle.SP_DirIcon);
|
|
533 return BrowserApplication.instance().icon(bookmarkNode.url);
|
|
534 }
|
|
535 }
|
45
|
536
|
73
|
537 return QVariant();
|
|
538 }
|
|
539
|
|
540 int columnCount(QModelIndex parent = QModelIndex())
|
|
541 {
|
|
542 return (parent.column() > 0) ? 0 : 2;
|
|
543 }
|
|
544
|
|
545 int rowCount(QModelIndex parent = QModelIndex())
|
|
546 {
|
|
547 if (parent.column() > 0)
|
|
548 return 0;
|
45
|
549
|
73
|
550 if (!parent.isValid())
|
|
551 return m_bookmarksManager.bookmarks().children().count();
|
45
|
552
|
74
|
553 BookmarkNode item = cast(BookmarkNode) parent.internalPointer();
|
73
|
554 return item.children().count();
|
|
555 }
|
|
556
|
74
|
557 QModelIndex index(int row, int column, QModelIndex parent = QModelIndex())
|
73
|
558 {
|
|
559 if (row < 0 || column < 0 || row >= rowCount(parent) || column >= columnCount(parent))
|
|
560 return QModelIndex();
|
45
|
561
|
73
|
562 // get the parent node
|
|
563 BookmarkNode parentNode = node(parent);
|
77
|
564 return createIndex(row, column, parentNode.children()[row]);
|
73
|
565 }
|
45
|
566
|
74
|
567 QModelIndex parent(QModelIndex index = QModelIndex())
|
73
|
568 {
|
|
569 if (!index.isValid())
|
|
570 return QModelIndex();
|
45
|
571
|
73
|
572 BookmarkNode itemNode = node(index);
|
|
573 BookmarkNode parentNode = (itemNode ? itemNode.parent() : 0);
|
|
574 if (!parentNode || parentNode == m_bookmarksManager.bookmarks())
|
|
575 return QModelIndex();
|
45
|
576
|
73
|
577 // get the parent's row
|
|
578 BookmarkNode grandParentNode = parentNode.parent();
|
|
579 int parentRow = grandParentNode.children().indexOf(parentNode);
|
|
580 assert(parentRow >= 0);
|
|
581 return createIndex(parentRow, 0, parentNode);
|
|
582 }
|
45
|
583
|
94
|
584 int flags(QModelIndex index)
|
73
|
585 {
|
|
586 if (!index.isValid())
|
|
587 return Qt.NoItemFlags;
|
|
588
|
94
|
589 int flags = Qt_ItemFlag.ItemIsSelectable | Qt_ItemFlag.ItemIsEnabled;
|
45
|
590
|
73
|
591 BookmarkNode bookmarkNode = node(index);
|
45
|
592
|
73
|
593 if (bookmarkNode != m_bookmarksManager.menu() && bookmarkNode != m_bookmarksManager.toolbar()) {
|
94
|
594 flags |= Qt_ItemFlag.ItemIsDragEnabled;
|
73
|
595 if (bookmarkNode.type() != BookmarkNode.Separator)
|
94
|
596 flags |= Qt_ItemFlag.ItemIsEditable;
|
73
|
597 }
|
|
598 if (hasChildren(index))
|
94
|
599 flags |= Qt_ItemFlag.ItemIsDropEnabled;
|
73
|
600 return flags;
|
|
601 }
|
|
602
|
94
|
603 int supportedDropActions()
|
73
|
604 {
|
94
|
605 return Qt_DropActiont.CopyAction | Qt_DropAction.MoveAction;
|
73
|
606 }
|
45
|
607
|
74
|
608 bool removeRows(int row, int count, QModelIndex parent = QModelIndex())
|
73
|
609 {
|
|
610 if (row < 0 || count <= 0 || row + count > rowCount(parent))
|
|
611 return false;
|
|
612
|
|
613 BookmarkNode bookmarkNode = node(parent);
|
|
614 for (int i = row + count - 1; i >= row; --i) {
|
77
|
615 BookmarkNode node = bookmarkNode.children()[i];
|
73
|
616 if (node == m_bookmarksManager.menu() || node == m_bookmarksManager.toolbar())
|
|
617 continue;
|
45
|
618
|
73
|
619 m_bookmarksManager.removeBookmark(node);
|
|
620 }
|
|
621 if (m_endMacro) {
|
|
622 m_bookmarksManager.undoRedoStack().endMacro();
|
|
623 m_endMacro = false;
|
|
624 }
|
|
625 return true;
|
|
626 }
|
|
627
|
94
|
628 bool setData(QModelIndex index, QVariant value, int role = Qt_ItemDataRole.EditRole)
|
73
|
629 {
|
94
|
630 if (!index.isValid() || (flags(index) & Qt_ItemFlag.ItemIsEditable) == 0)
|
73
|
631 return false;
|
45
|
632
|
73
|
633 BookmarkNode item = node(index);
|
45
|
634
|
73
|
635 switch (role) {
|
94
|
636 case Qt_ItemFlag.EditRole:
|
|
637 case Qt_ItemFlag.DisplayRole:
|
73
|
638 if (index.column() == 0) {
|
|
639 m_bookmarksManager.setTitle(item, value.toString());
|
|
640 break;
|
|
641 }
|
|
642 if (index.column() == 1) {
|
|
643 m_bookmarksManager.setUrl(item, value.toString());
|
|
644 break;
|
|
645 }
|
|
646 return false;
|
|
647 case BookmarksModel.UrlRole:
|
|
648 m_bookmarksManager.setUrl(item, value.toUrl().toString());
|
|
649 break;
|
|
650 case BookmarksModel.UrlStringRole:
|
|
651 m_bookmarksManager.setUrl(item, value.toString());
|
|
652 break;
|
|
653 default:
|
|
654 break;
|
|
655 return false;
|
|
656 }
|
|
657
|
|
658 return true;
|
|
659 }
|
45
|
660
|
94
|
661 QMimeData mimeData(QModelIndex[] indexes)
|
73
|
662 {
|
94
|
663 auto mimeData = new QMimeData();
|
|
664 auto data = new QByteArray;
|
|
665 auto stream = new QDataStream(data, QIODevice.WriteOnly);
|
74
|
666 foreach (QModelIndex index; indexes) {
|
73
|
667 if (index.column() != 0 || !index.isValid())
|
|
668 continue;
|
94
|
669 auto encodedData = new QByteArray;
|
|
670 auto buffer = new QBuffer(encodedData);
|
73
|
671 buffer.open(QBuffer.ReadWrite);
|
94
|
672 auto writer = new XbelWriter;
|
|
673 BookmarkNode parentNode = node(index);
|
|
674 writer.write(buffer, parentNode);
|
73
|
675 stream << encodedData;
|
|
676 }
|
|
677 mimeData.setData(MIMETYPE, data);
|
|
678 return mimeData;
|
|
679 }
|
45
|
680
|
80
|
681 const string MIMETYPE = "application/bookmarks.xbel";
|
45
|
682
|
77
|
683 string[] mimeTypes()
|
73
|
684 {
|
77
|
685 return [ MIMETYPE ];
|
73
|
686 }
|
45
|
687
|
94
|
688 bool dropMimeData(QMimeData data, Qt_DropAction action, int row, int column, QModelIndex parent)
|
73
|
689 {
|
94
|
690 if (action == Qt_DropAction.IgnoreAction)
|
73
|
691 return true;
|
45
|
692
|
73
|
693 if (!data.hasFormat(MIMETYPE) || column > 0)
|
|
694 return false;
|
45
|
695
|
73
|
696 QByteArray ba = data.data(MIMETYPE);
|
94
|
697 QDataStream stream = new QDataStream(ba, QIODevice.ReadOnly);
|
73
|
698 if (stream.atEnd())
|
|
699 return false;
|
45
|
700
|
73
|
701 QUndoStack undoStack = m_bookmarksManager.undoRedoStack();
|
80
|
702 undoStack.beginMacro("Move Bookmarks");
|
45
|
703
|
73
|
704 while (!stream.atEnd()) {
|
94
|
705 auto encodedData = new QByteArray;
|
73
|
706 stream >> encodedData;
|
94
|
707 auto buffer = new QBuffer(encodedData);
|
73
|
708 buffer.open(QBuffer.ReadOnly);
|
45
|
709
|
80
|
710 auto reader = new XbelReader;
|
94
|
711 BookmarkNode rootNode = reader.read(buffer);
|
74
|
712 BookmarkNode[] children = rootNode.children();
|
73
|
713 for (int i = 0; i < children.count(); ++i) {
|
77
|
714 BookmarkNode bookmarkNode = children[i];
|
73
|
715 rootNode.remove(bookmarkNode);
|
|
716 row = qMax(0, row);
|
|
717 BookmarkNode parentNode = node(parent);
|
|
718 m_bookmarksManager.addBookmark(parentNode, bookmarkNode, row);
|
|
719 m_endMacro = true;
|
|
720 }
|
|
721 delete rootNode;
|
|
722 }
|
|
723 return true;
|
|
724 }
|
45
|
725
|
73
|
726 bool hasChildren(QModelIndex parent = QModelIndex())
|
|
727 {
|
|
728 if (!parent.isValid())
|
|
729 return true;
|
|
730 const BookmarkNode parentNode = node(parent);
|
|
731 return (parentNode.type() == BookmarkNode.Folder);
|
|
732 }
|
45
|
733
|
73
|
734 BookmarkNode node(QModelIndex index)
|
|
735 {
|
74
|
736 BookmarkNode itemNode = cast(BookmarkNode) index.internalPointer();
|
73
|
737 if (!itemNode)
|
|
738 return m_bookmarksManager.bookmarks();
|
|
739 return itemNode;
|
|
740 }
|
45
|
741
|
73
|
742 QModelIndex index(BookmarkNode node)
|
|
743 {
|
|
744 BookmarkNode parent = node.parent();
|
|
745 if (!parent)
|
|
746 return QModelIndex();
|
|
747 return createIndex(parent.children().indexOf(node), 0, node);
|
|
748 }
|
45
|
749
|
|
750 private:
|
|
751
|
73
|
752 bool m_endMacro;
|
|
753 BookmarksManager m_bookmarksManager;
|
45
|
754 }
|
|
755
|
|
756 // Menu that is dynamically populated from the bookmarks
|
|
757 import modelmenu;
|
73
|
758
|
45
|
759 class BookmarksMenu : public ModelMenu
|
|
760 {
|
74
|
761 mixin Signal!("openUrl", QUrl /*url*/);
|
45
|
762
|
|
763 public:
|
73
|
764
|
74
|
765 this(QWidget parent = null)
|
73
|
766 {
|
|
767 super(parent);
|
|
768 m_bookmarksManager = 0;
|
|
769 this.activated.connect(&this.activated);
|
|
770 setMaxRows(-1);
|
|
771 setHoverRole(BookmarksModel.UrlStringRole);
|
|
772 setSeparatorRole(BookmarksModel.SeparatorRole);
|
|
773 }
|
|
774
|
74
|
775 void setInitialActions(QAction[] actions)
|
73
|
776 {
|
|
777 m_initialActions = actions;
|
|
778 for (int i = 0; i < m_initialActions.count(); ++i)
|
77
|
779 addAction(m_initialActions[i]);
|
73
|
780 }
|
|
781
|
45
|
782 protected:
|
73
|
783
|
45
|
784 bool prePopulated()
|
73
|
785 {
|
|
786 m_bookmarksManager = BrowserApplication.bookmarksManager();
|
|
787 setModel(m_bookmarksManager.bookmarksModel());
|
|
788 setRootIndex(m_bookmarksManager.bookmarksModel().index(1, 0));
|
|
789 // initial actions
|
|
790 for (int i = 0; i < m_initialActions.count(); ++i)
|
77
|
791 addAction(m_initialActions[i]);
|
73
|
792 if (!m_initialActions.isEmpty())
|
|
793 addSeparator();
|
|
794 createMenu(model().index(0, 0), 1, this);
|
|
795 return true;
|
|
796 }
|
45
|
797
|
|
798 private:
|
73
|
799
|
|
800 void activated(QModelIndex index)
|
|
801 {
|
74
|
802 openUrl.emit(index.data(BookmarksModel.UrlRole).toUrl());
|
73
|
803 }
|
|
804
|
|
805 private:
|
|
806
|
|
807 BookmarksManager m_bookmarksManager;
|
74
|
808 QAction[] m_initialActions;
|
45
|
809 }
|
|
810
|
|
811 /*
|
|
812 Proxy model that filters out the bookmarks so only the folders
|
|
813 are left behind. Used in the add bookmark dialog combobox.
|
|
814 */
|
72
|
815 import qt.gui.QSortFilterProxyModel;
|
|
816
|
45
|
817 class AddBookmarkProxyModel : public QSortFilterProxyModel
|
|
818 {
|
|
819 public:
|
73
|
820
|
|
821 this(QObject parent = null)
|
|
822 {
|
|
823 super(parent);
|
|
824 }
|
|
825
|
|
826 int columnCount(QModelIndex parent = QModelIndex())
|
|
827 {
|
|
828 return qMin(1, QSortFilterProxyModel.columnCount(parent));
|
|
829 }
|
|
830
|
|
831 protected:
|
|
832
|
|
833 bool filterAcceptsRow(int source_row, QModelIndex source_parent)
|
|
834 {
|
|
835 QModelIndex idx = sourceModel().index(source_row, 0, source_parent);
|
|
836 return sourceModel().hasChildren(idx);
|
|
837 }
|
45
|
838 }
|
|
839
|
|
840 /*!
|
73
|
841 Add bookmark dialog
|
|
842 */
|
72
|
843
|
45
|
844 import ui_addbookmarkdialog;
|
72
|
845
|
94
|
846 class AddBookmarkDialog : public QDialog //, public Ui_AddBookmarkDialog
|
45
|
847 {
|
94
|
848 AddBookmarkDialog ui;
|
|
849
|
73
|
850 public:
|
45
|
851
|
77
|
852 this(string url, string title, QWidget parent = null, BookmarksManager bookmarkManager = null)
|
73
|
853 {
|
94
|
854 super(parent);
|
73
|
855 m_url = url;
|
|
856 m_bookmarksManager = bookmarkManager;
|
|
857
|
|
858 setWindowFlags(Qt.Sheet);
|
|
859 if (!m_bookmarksManager)
|
|
860 m_bookmarksManager = BrowserApplication.bookmarksManager();
|
94
|
861 ui.setupUi(this);
|
73
|
862 QTreeView view = new QTreeView(this);
|
|
863 m_proxyModel = new AddBookmarkProxyModel(this);
|
|
864 BookmarksModel model = m_bookmarksManager.bookmarksModel();
|
|
865 m_proxyModel.setSourceModel(model);
|
|
866 view.setModel(m_proxyModel);
|
|
867 view.expandAll();
|
|
868 view.header().setStretchLastSection(true);
|
|
869 view.header().hide();
|
|
870 view.setItemsExpandable(false);
|
|
871 view.setRootIsDecorated(false);
|
|
872 view.setIndentation(10);
|
|
873 location.setModel(m_proxyModel);
|
|
874 view.show();
|
|
875 location.setView(view);
|
|
876 BookmarkNode menu = m_bookmarksManager.menu();
|
|
877 QModelIndex idx = m_proxyModel.mapFromSource(model.index(menu));
|
|
878 view.setCurrentIndex(idx);
|
|
879 location.setCurrentIndex(idx.row());
|
|
880 name.setText(title);
|
|
881 }
|
72
|
882
|
|
883 private:
|
45
|
884
|
73
|
885 void accept()
|
|
886 {
|
|
887 QModelIndex index = location.view().currentIndex();
|
|
888 index = m_proxyModel.mapToSource(index);
|
|
889 if (!index.isValid())
|
|
890 index = m_bookmarksManager.bookmarksModel().index(0, 0);
|
|
891 BookmarkNode parent = m_bookmarksManager.bookmarksModel().node(index);
|
|
892 BookmarkNode bookmark = new BookmarkNode(BookmarkNode.Bookmark);
|
|
893 bookmark.url = m_url;
|
|
894 bookmark.title = name.text();
|
|
895 m_bookmarksManager.addBookmark(parent, bookmark);
|
|
896 QDialog.accept();
|
|
897 }
|
45
|
898
|
|
899 private:
|
73
|
900
|
77
|
901 string m_url;
|
73
|
902 BookmarksManager m_bookmarksManager;
|
|
903 AddBookmarkProxyModel m_proxyModel;
|
45
|
904 }
|
|
905
|
|
906 import ui_bookmarks;
|
|
907
|
|
908 //class TreeProxyModel;
|
94
|
909 class BookmarksDialog : public QDialog //, public Ui_BookmarksDialog
|
45
|
910 {
|
94
|
911 BookmarksDialog ui;
|
|
912
|
74
|
913 mixin Signal!("openUrl", QUrl /*url*/);
|
45
|
914
|
|
915 public:
|
73
|
916
|
|
917 this(QWidget parent = null, BookmarksManager manager = null)
|
|
918 {
|
94
|
919 super(parent);
|
73
|
920 m_bookmarksManager = manager;
|
|
921 if (!m_bookmarksManager)
|
|
922 m_bookmarksManager = BrowserApplication.bookmarksManager();
|
94
|
923 ui.setupUi(this);
|
45
|
924
|
73
|
925 tree.setUniformRowHeights(true);
|
|
926 tree.setSelectionBehavior(QAbstractItemView.SelectRows);
|
|
927 tree.setSelectionMode(QAbstractItemView.ContiguousSelection);
|
|
928 tree.setTextElideMode(Qt.ElideMiddle);
|
|
929 m_bookmarksModel = m_bookmarksManager.bookmarksModel();
|
|
930 m_proxyModel = new TreeProxyModel(this);
|
|
931 search.textChanged.connect(&m_proxyModel.setFilterFixedString);
|
|
932 removeButton.clicked.connect(&tree.removeOne);
|
|
933 m_proxyModel.setSourceModel(m_bookmarksModel);
|
|
934 tree.setModel(m_proxyModel);
|
|
935 tree.setDragDropMode(QAbstractItemView.InternalMove);
|
|
936 tree.setExpanded(m_proxyModel.index(0, 0), true);
|
|
937 tree.setAlternatingRowColors(true);
|
|
938 auto fm = new QFontMetrics(font());
|
|
939 int header = fm.width(QLatin1Char('m')) * 40;
|
|
940 tree.header().resizeSection(0, header);
|
|
941 tree.header().setStretchLastSection(true);
|
|
942 tree.activated.connect(&this.open);
|
|
943 tree.setContextMenuPolicy(Qt.CustomContextMenu);
|
|
944 tree.customContextMenuRequested.connect(&this.customContextMenuRequested);
|
|
945 addFolderButton.clicked.connect(&this.newFolder);
|
|
946 expandNodes(m_bookmarksManager.bookmarks());
|
|
947 setAttribute(Qt.WA_DeleteOnClose);
|
|
948 }
|
|
949
|
|
950 ~this()
|
|
951 {
|
|
952 if (saveExpandedNodes(tree.rootIndex()))
|
|
953 m_bookmarksManager.changeExpanded();
|
|
954 }
|
45
|
955
|
|
956 private:
|
73
|
957
|
|
958 void customContextMenuRequested(QPoint pos)
|
|
959 {
|
77
|
960 auto menu = new QMenu;
|
73
|
961 QModelIndex index = tree.indexAt(pos);
|
|
962 index = index.sibling(index.row(), 0);
|
|
963 if (index.isValid() && !tree.model().hasChildren(index)) {
|
|
964 menu.addAction(tr("Open"), this, SLOT(open()));
|
|
965 menu.addSeparator();
|
|
966 }
|
|
967 menu.addAction(tr("Delete"), tree, SLOT(removeOne()));
|
|
968 menu.exec(QCursor.pos());
|
|
969 }
|
|
970
|
|
971 void open()
|
|
972 {
|
|
973 QModelIndex index = tree.currentIndex();
|
|
974 if (!index.parent().isValid())
|
|
975 return;
|
74
|
976 openUrl.emit(index.sibling(index.row(), 1).data(BookmarksModel.UrlRole).toUrl());
|
73
|
977 }
|
|
978
|
|
979 void newFolder()
|
|
980 {
|
|
981 QModelIndex currentIndex = tree.currentIndex();
|
|
982 QModelIndex idx = currentIndex;
|
|
983 if (idx.isValid() && !idx.model().hasChildren(idx))
|
|
984 idx = idx.parent();
|
|
985 if (!idx.isValid())
|
|
986 idx = tree.rootIndex();
|
|
987 idx = m_proxyModel.mapToSource(idx);
|
|
988 BookmarkNode parent = m_bookmarksManager.bookmarksModel().node(idx);
|
|
989 BookmarkNode node = new BookmarkNode(BookmarkNode.Folder);
|
|
990 node.title = tr("New Folder");
|
|
991 m_bookmarksManager.addBookmark(parent, node, currentIndex.row() + 1);
|
|
992 }
|
45
|
993
|
73
|
994 private:
|
|
995 void expandNodes(BookmarkNode node)
|
|
996 {
|
|
997 for (int i = 0; i < node.children().count(); ++i) {
|
|
998 BookmarkNode childNode = node.children()[i];
|
|
999 if (childNode.expanded) {
|
|
1000 QModelIndex idx = m_bookmarksModel.index(childNode);
|
|
1001 idx = m_proxyModel.mapFromSource(idx);
|
|
1002 tree.setExpanded(idx, true);
|
|
1003 expandNodes(childNode);
|
|
1004 }
|
|
1005 }
|
|
1006 }
|
45
|
1007
|
73
|
1008 bool saveExpandedNodes(QModelIndex parent)
|
|
1009 {
|
|
1010 bool changed = false;
|
|
1011 for (int i = 0; i < m_proxyModel.rowCount(parent); ++i) {
|
|
1012 QModelIndex child = m_proxyModel.index(i, 0, parent);
|
|
1013 QModelIndex sourceIndex = m_proxyModel.mapToSource(child);
|
|
1014 BookmarkNode childNode = m_bookmarksModel.node(sourceIndex);
|
|
1015 bool wasExpanded = childNode.expanded;
|
|
1016 if (tree.isExpanded(child)) {
|
|
1017 childNode.expanded = true;
|
|
1018 changed |= saveExpandedNodes(child);
|
|
1019 } else {
|
|
1020 childNode.expanded = false;
|
|
1021 }
|
|
1022 changed |= (wasExpanded != childNode.expanded);
|
|
1023 }
|
|
1024 return changed;
|
|
1025 }
|
|
1026
|
|
1027 BookmarksManager m_bookmarksManager;
|
|
1028 BookmarksModel m_bookmarksModel;
|
|
1029 TreeProxyModel m_proxyModel;
|
72
|
1030 }
|
45
|
1031
|
74
|
1032
|
72
|
1033 import qt.gui.QToolBar;
|
|
1034
|
74
|
1035
|
45
|
1036 class BookmarksToolBar : public QToolBar
|
|
1037 {
|
74
|
1038 mixin Signal!("openUrl", QUrl /*url*/);
|
45
|
1039
|
|
1040 public:
|
|
1041
|
73
|
1042 this(BookmarksModel model, QWidget parent = null)
|
|
1043 {
|
|
1044 super(tr("Bookmark"), parent);
|
|
1045 m_bookmarksModel = model;
|
|
1046 this.actionTriggered.connect(&this.triggered);
|
|
1047 setRootIndex(model.index(0, 0));
|
|
1048 m_bookmarksModel.modelReset.connect(&this.build);
|
|
1049 m_bookmarksModel.rowsInserted.connect(&this.build);
|
|
1050 m_bookmarksModel.rowsRemoved.connect(&this.build);
|
|
1051 m_bookmarksModel.dataChanged.connect(&this.build);
|
|
1052 setAcceptDrops(true);
|
|
1053 }
|
45
|
1054
|
74
|
1055 void setRootIndex(QModelIndex index)
|
73
|
1056 {
|
|
1057 m_root = index;
|
|
1058 build();
|
|
1059 }
|
|
1060
|
|
1061 QModelIndex rootIndex()
|
|
1062 {
|
|
1063 return m_root;
|
|
1064 }
|
45
|
1065
|
|
1066 protected:
|
|
1067
|
73
|
1068 void dragEnterEvent(QDragEnterEvent event)
|
|
1069 {
|
77
|
1070 QMimeData mimeData = event.mimeData();
|
73
|
1071 if (mimeData.hasUrls())
|
|
1072 event.acceptProposedAction();
|
|
1073 QToolBar.dragEnterEvent(event);
|
|
1074 }
|
45
|
1075
|
73
|
1076 void dropEvent(QDropEvent event)
|
|
1077 {
|
77
|
1078 QMimeData mimeData = event.mimeData();
|
73
|
1079 if (mimeData.hasUrls() && mimeData.hasText()) {
|
74
|
1080 QUrl[] urls = mimeData.urls();
|
73
|
1081 QAction action = actionAt(event.pos());
|
77
|
1082 string dropText;
|
73
|
1083 if (action)
|
|
1084 dropText = action.text();
|
|
1085 int row = -1;
|
|
1086 QModelIndex parentIndex = m_root;
|
|
1087 for (int i = 0; i < m_bookmarksModel.rowCount(m_root); ++i) {
|
|
1088 QModelIndex idx = m_bookmarksModel.index(i, 0, m_root);
|
77
|
1089 string title = idx.data().toString();
|
73
|
1090 if (title == dropText) {
|
|
1091 row = i;
|
|
1092 if (m_bookmarksModel.hasChildren(idx)) {
|
|
1093 parentIndex = idx;
|
|
1094 row = -1;
|
|
1095 }
|
|
1096 break;
|
|
1097 }
|
|
1098 }
|
|
1099 BookmarkNode bookmark = new BookmarkNode(BookmarkNode.Bookmark);
|
77
|
1100 bookmark.url = urls[0].toString();
|
73
|
1101 bookmark.title = mimeData.text();
|
45
|
1102
|
73
|
1103 BookmarkNode parent = m_bookmarksModel.node(parentIndex);
|
|
1104 BookmarksManager bookmarksManager = m_bookmarksModel.bookmarksManager();
|
|
1105 bookmarksManager.addBookmark(parent, bookmark, row);
|
|
1106 event.acceptProposedAction();
|
|
1107 }
|
|
1108 QToolBar.dropEvent(event);
|
|
1109 }
|
45
|
1110
|
|
1111 private:
|
73
|
1112
|
|
1113 void triggered(QAction action)
|
|
1114 {
|
|
1115 QVariant v = action.data();
|
74
|
1116 if (v.canConvert!(QUrl)()) {
|
|
1117 openUrl.emit(v.toUrl());
|
73
|
1118 }
|
|
1119 }
|
|
1120
|
|
1121 void activated(QModelIndex index)
|
|
1122 {
|
74
|
1123 openUrl.emit(index.data(BookmarksModel.UrlRole).toUrl());
|
73
|
1124 }
|
|
1125
|
|
1126 void build()
|
|
1127 {
|
|
1128 clear();
|
|
1129 for (int i = 0; i < m_bookmarksModel.rowCount(m_root); ++i) {
|
|
1130 QModelIndex idx = m_bookmarksModel.index(i, 0, m_root);
|
|
1131 if (m_bookmarksModel.hasChildren(idx)) {
|
|
1132 QToolButton button = new QToolButton(this);
|
|
1133 button.setPopupMode(QToolButton.InstantPopup);
|
94
|
1134 button.setArrowType(Qt_ArrowType.DownArrow);
|
73
|
1135 button.setText(idx.data().toString());
|
|
1136 ModelMenu menu = new ModelMenu(this);
|
|
1137 menu.activated.connect(&this.activated);
|
|
1138 menu.setModel(m_bookmarksModel);
|
|
1139 menu.setRootIndex(idx);
|
|
1140 menu.addAction(new QAction(menu));
|
|
1141 button.setMenu(menu);
|
|
1142 button.setToolButtonStyle(Qt.ToolButtonTextOnly);
|
|
1143 QAction a = addWidget(button);
|
|
1144 a.setText(idx.data().toString());
|
|
1145 } else {
|
|
1146 QAction action = addAction(idx.data().toString());
|
|
1147 action.setData(idx.data(BookmarksModel.UrlRole));
|
|
1148 }
|
|
1149 }
|
|
1150 }
|
|
1151
|
|
1152 private:
|
|
1153
|
|
1154 BookmarksModel m_bookmarksModel;
|
|
1155 QPersistentModelIndex m_root;
|
45
|
1156 }
|