6#include <QtCore/QIODevice>
7#include <QtCore/QMimeData>
8#include <QtCore/QStack>
10#include <QtWidgets/QApplication>
11#include <QtWidgets/QStyle>
12#include <QtWidgets/QTreeView>
14using namespace Qt::StringLiterals;
20 : QAbstractItemModel()
36 QDataStream stream(&ba, QIODevice::WriteOnly);
37 stream << qint32(VERSION);
39 const QModelIndex &root = index(0,0, QModelIndex()).parent();
40 for (
int i = 0; i < rowCount(root); ++i)
41 collectItems(index(i, 0, root), 0, &stream);
52 folderIcon = QApplication::style()->standardIcon(QStyle::SP_DirClosedIcon);
53 bookmarkIcon = QIcon(
":/qt-project.org/assistant/images/bookmark.png"_L1);
58 QStack<BookmarkItem*> parents;
59 QDataStream stream(bookmarks);
63 if (version < VERSION) {
64 stream.device()->seek(0);
66 new BookmarkItem(DataVector() << tr(
"Bookmarks Toolbar") <<
"Folder"_L1 <<
true);
70 new BookmarkItem(DataVector() << tr(
"Bookmarks Menu") <<
"Folder"_L1 <<
true);
74 parents.push(rootItem);
80 while (!stream.atEnd()) {
81 stream >> depth >> name >> url >> expanded;
82 while ((parents.size() - 1) != depth)
85 BookmarkItem *item =
new BookmarkItem(DataVector() << name << url << expanded);
86 if (url ==
"Folder"_L1) {
87 parents.top()->addChild(item);
90 parents.top()->addChild(item);
95 setupCache(index(0,0, QModelIndex().parent()));
102 m_editable = editable;
108 for (QModelIndex index : std::as_const(cache))
109 treeView->setExpanded(index, index.data(UserRoleExpanded).toBool());
117 if (insertRow(rowCount(parent), parent))
118 next = index(rowCount(parent) - 1, 0, parent);
127 if (!index.isValid())
130 QModelIndexList indexes;
131 if (rowCount(index) > 0)
132 indexes = collectItems(index);
133 indexes.append(index);
135 for (
const QModelIndex &itemToRemove : std::as_const(indexes)) {
136 if (!removeRow(itemToRemove.row(), itemToRemove.parent()))
138 cache.remove(itemFromIndex(itemToRemove));
160 if (!index.isValid())
161 return QModelIndex();
165 if (parent != rootItem)
169 return QModelIndex();
175 if (index.isValid() && (index.column() != 0 && index.column() != 1))
176 return QModelIndex();
180 return createIndex(row, column, childItem);
182 return QModelIndex();
188 return Qt::MoveAction;
194 if (!index.isValid())
195 return Qt::NoItemFlags;
197 Qt::ItemFlags defaultFlags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
200 defaultFlags |= Qt::ItemIsEditable;
202 if (itemFromIndex(index) && index.data(UserRoleFolder).toBool()) {
203 if (index.column() > 0)
204 return defaultFlags &~ Qt::ItemIsEditable;
205 return defaultFlags | Qt::ItemIsDropEnabled;
208 return defaultFlags | Qt::ItemIsDragEnabled;
214 if (index.isValid()) {
218 case Qt::DisplayRole:
221 return item->data(index.column());
223 case Qt::DecorationRole:
224 if (index.column() == 0)
225 return index.data(UserRoleFolder).toBool()
226 ? folderIcon : bookmarkIcon;
230 return item->data(role);
241 emit dataChanged(index, index);
249 if (role != Qt::EditRole && role != UserRoleExpanded)
253 if (role == Qt::EditRole) {
255 if (!isFolder || index.column() == 0)
263 emit dataChanged(index, index);
271 if (rootItem && orientation == Qt::Horizontal && role == Qt::DisplayRole)
272 return rootItem->data(section);
279 return cache.value(item, QModelIndex());
286 return static_cast<
BookmarkItem*>(index.internalPointer());
293 QList<QPersistentModelIndex> hits;
294 const QModelIndexList &list = collectItems(QModelIndex());
295 for (
const QModelIndex &index : list) {
296 if (index.data().toString().contains(label, Qt::CaseInsensitive))
308 bool success =
false;
310 beginInsertRows(parent, position, position + rows - 1);
313 const QModelIndex ¤t = index(position, 0, parent);
314 cache.insert(itemFromIndex(current), current);
324 bool success =
false;
326 beginRemoveRows(index, position, position + rows - 1);
336 return QStringList() << MIMETYPE;
342 if (indexes.isEmpty())
346 QDataStream stream(&data, QIODevice::WriteOnly);
348 for (
const QModelIndex &index : indexes) {
349 if (index.column() == 0)
350 collectItems(index, 0, &stream);
353 QMimeData *mimeData =
new QMimeData();
354 mimeData->setData(MIMETYPE, data);
360 int row,
int column,
const QModelIndex &parent)
362 if (action == Qt::IgnoreAction)
365 if (!data->hasFormat(MIMETYPE) || column > 0)
368 QByteArray ba = data->data(MIMETYPE);
369 QDataStream stream(&ba, QIODevice::ReadOnly);
370 while (stream.atEnd())
376 while (!stream.atEnd()) {
377 stream >> depth >> name >> url >> expanded;
378 if (insertRow(qMax(0, row), parent)) {
379 const QModelIndex ¤t = index(qMax(0, row), 0, parent);
380 if (current.isValid()) {
382 item->setData(DataVector() << name << url << expanded);
392 const QModelIndexList &list = collectItems(parent);
393 for (
const QModelIndex &index : list)
394 cache.insert(itemFromIndex(index), index);
400 QModelIndexList list;
401 for (
int i = rowCount(parent) - 1; i >= 0 ; --i) {
402 const QModelIndex &next = index(i, 0, parent);
403 if (data(next, UserRoleFolder).toBool())
404 list += collectItems(next);
411BookmarkModel::collectItems(
const QModelIndex &parent, qint32 depth,
412 QDataStream *stream)
const
414 if (parent.isValid()) {
416 *stream << parent.data().toString();
420 for (
int i = 0; i < rowCount(parent); ++i) {
421 if (parent.data(UserRoleFolder).toBool())
422 collectItems(index(i, 0 , parent), depth + 1, stream);
QList< QVariant > DataVector
const QLatin1StringView MIMETYPE("application/bookmarks.assistant")
BookmarkItem * child(int number) const
bool insertChildren(bool isFolder, int position, int count)
void addChild(BookmarkItem *child)
bool removeChildren(int position, int count)
BookmarkItem * parent() const
void setData(const DataVector &data)
void setItemsEditable(bool editable)
QByteArray bookmarks() const
int columnCount(const QModelIndex &index=QModelIndex()) const override
Returns the number of columns for the children of the given parent.
Qt::ItemFlags flags(const QModelIndex &index) const override
Returns the item flags for the given index.
QVariant headerData(int section, Qt::Orientation orientation, int role) const override
Returns the data for the given role and section in the header with the specified orientation.
QModelIndex index(int row, int column, const QModelIndex &index) const override
Returns the index of the item in the model specified by the given row, column and parent index.
~BookmarkModel() override
bool insertRows(int position, int rows, const QModelIndex &parent) override
QModelIndex addItem(const QModelIndex &parent, bool isFolder=false)
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override
Handles the data supplied by a drag and drop operation that ended with the given action.
BookmarkItem * itemFromIndex(const QModelIndex &index) const
bool removeItem(const QModelIndex &index)
void setData(const QModelIndex &index, const QList< QVariant > &data)
bool setData(const QModelIndex &index, const QVariant &value, int role) override
Sets the role data for the item at index to value.
QStringList mimeTypes() const override
Returns the list of allowed MIME types.
QModelIndex indexFromItem(BookmarkItem *item) const
void expandFoldersIfNeeeded(QTreeView *treeView)
int rowCount(const QModelIndex &index=QModelIndex()) const override
Returns the number of rows under the given parent.
void setBookmarks(const QByteArray &bookmarks)
QVariant data(const QModelIndex &index, int role) const override
Returns the data stored under the given role for the item referred to by the index.
QList< QPersistentModelIndex > indexListFor(const QString &label) const
QModelIndex parent(const QModelIndex &index) const override
QMimeData * mimeData(const QModelIndexList &indexes) const override
Returns an object that contains serialized items of data corresponding to the list of indexes specifi...
Qt::DropActions supportedDropActions() const override
bool removeRows(int position, int rows, const QModelIndex &parent) override