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