From 334be268bf75b863f7c912ae28bab46f7bbc325a Mon Sep 17 00:00:00 2001 From: Aqua-sama Date: Sun, 4 Feb 2018 17:27:58 +0100 Subject: Bookmarks drag and drop --- lib/bookmarks/bookmarksmodel.cpp | 75 ++++++++++++++++++++++++++++++++------- lib/bookmarks/bookmarksmodel.h | 12 +++++++ lib/bookmarks/bookmarkswidget.cpp | 11 ++++-- lib/bookmarks/bookmarkswidget.h | 2 ++ lib/bookmarks/xbel.cpp | 35 +++--------------- lib/bookmarks/xbel.h | 4 +-- 6 files changed, 92 insertions(+), 47 deletions(-) diff --git a/lib/bookmarks/bookmarksmodel.cpp b/lib/bookmarks/bookmarksmodel.cpp index 418d456..ba537ba 100644 --- a/lib/bookmarks/bookmarksmodel.cpp +++ b/lib/bookmarks/bookmarksmodel.cpp @@ -7,6 +7,8 @@ */ #include "bookmarksmodel.h" +#include +#include BookmarksModel::BookmarksModel(QStyle *style, QObject *parent) : QAbstractItemModel(parent) @@ -166,10 +168,10 @@ Qt::ItemFlags BookmarksModel::flags(const QModelIndex &index) const case BookmarkItem::Root: break; case BookmarkItem::Folder: - flags |= Qt::ItemIsEditable; + flags |= Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; break; case BookmarkItem::Bookmark: - flags |= Qt::ItemIsEnabled | Qt::ItemNeverHasChildren; + flags |= Qt::ItemIsEnabled | Qt::ItemNeverHasChildren | Qt::ItemIsDragEnabled; break; } return flags; @@ -253,19 +255,18 @@ bool BookmarksModel::setData(const QModelIndex &index, const QVariant &value, in case BookmarkItem::Bookmark: if(role == TitleRole && (node->title != value.toString())) { - node->title = value.toString(); - modified = true; - emit dataChanged(this->index(node, 0), this->index(node, 1)); - //emit dataChanged(index, index); - return true; + node->title = value.toString(); + modified = true; + emit dataChanged(this->index(node, 0), this->index(node, 1)); + //emit dataChanged(index, index); + return true; } else if(role == OpenUrlRole && (node->href != value.toString())) { - node->href = value.toString(); - modified = true; - emit dataChanged(this->index(node, 0), this->index(node, 1)); - //emit dataChanged(index, index); - return true; - + node->href = value.toString(); + modified = true; + emit dataChanged(this->index(node, 0), this->index(node, 1)); + //emit dataChanged(index, index); + return true; } return false; } @@ -327,3 +328,51 @@ void BookmarksModel::expandItems(QTreeView *view, BookmarkItem *root) } } } +QMimeData *BookmarksModel::mimeData(const QModelIndexList &indexes) const +{ + auto *qMimeData = new QMimeData(); + QByteArray data; + + for(const QModelIndex &idx : indexes) { + if(idx.column() != 0 || !idx.isValid()) + continue; + + QByteArray encodedData; + QBuffer buffer(&encodedData); + buffer.open(QBuffer::ReadWrite); + Xbel writer(&buffer); + writer.write(static_cast(idx.internalPointer())); + + data.append(encodedData); + } + + qMimeData->setData(mimeTypes().first(), data); + + return qMimeData; +} + +bool BookmarksModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) +{ + if(action == Qt::IgnoreAction) + return true; + + // invalid format or column + if(!data->hasFormat(mimeTypes().first()) || column > 0) + return false; + + QByteArray bytes = data->data(mimeTypes().first()); + + QBuffer buffer(&bytes); + buffer.open(QIODevice::ReadOnly); + + Xbel reader(&buffer); + auto *parentItem = static_cast(parent.internalPointer()); + Q_CHECK_PTR(parentItem); + + beginInsertRows(parent, parentItem->row(), parentItem->row()); + reader.read(parentItem); + endInsertRows(); + + modified = true; + return true; +} diff --git a/lib/bookmarks/bookmarksmodel.h b/lib/bookmarks/bookmarksmodel.h index ea1d203..b6cadbf 100644 --- a/lib/bookmarks/bookmarksmodel.h +++ b/lib/bookmarks/bookmarksmodel.h @@ -56,6 +56,18 @@ public: void expandItems(QTreeView *view, BookmarkItem *root = nullptr); + // drag and drop + Qt::DropActions supportedDropActions() const override + { + return Qt::CopyAction | Qt::MoveAction; + } + QStringList mimeTypes() const override + { + return {"application/bookmarks.xbel"}; + } + QMimeData *mimeData(const QModelIndexList &indexes) const override; + bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override; + private: QIcon folderIcon; QIcon bookmarkIcon; diff --git a/lib/bookmarks/bookmarkswidget.cpp b/lib/bookmarks/bookmarkswidget.cpp index 09f8c22..5e0e391 100644 --- a/lib/bookmarks/bookmarkswidget.cpp +++ b/lib/bookmarks/bookmarkswidget.cpp @@ -30,8 +30,14 @@ BookmarksWidget::BookmarksWidget(const QString &path, QWidget *parent) m_model = new BookmarksModel(style(), this); ui->treeView->setModel(m_model); - - xbel = new Xbel(path); + ui->treeView->viewport()->setAcceptDrops(true); + ui->treeView->setDragEnabled(true); + ui->treeView->setDragDropMode(QAbstractItemView::InternalMove); + ui->treeView->setDropIndicatorShown(true); + + m_bookmarksFile.setFileName(path); + m_bookmarksFile.open(QIODevice::ReadWrite | QIODevice::Text); + xbel = new Xbel(&m_bookmarksFile); qDebug("Reading bookmarks [%s] %s", qUtf8Printable(path), m_model->read(xbel) ? "ok" : "failed"); m_model->expandItems(ui->treeView); @@ -102,6 +108,7 @@ BookmarksWidget::BookmarksWidget(const QString &path, QWidget *parent) BookmarksWidget::~BookmarksWidget() { + m_bookmarksFile.close(); delete xbel; delete ui; } diff --git a/lib/bookmarks/bookmarkswidget.h b/lib/bookmarks/bookmarkswidget.h index 23e275f..abb4ac4 100644 --- a/lib/bookmarks/bookmarkswidget.h +++ b/lib/bookmarks/bookmarkswidget.h @@ -13,6 +13,7 @@ #include "xbel.h" #include #include +#include namespace Ui { @@ -40,6 +41,7 @@ private: Ui::BookmarksDialog *ui; BookmarksModel *m_model; Xbel *xbel; + QFile m_bookmarksFile; }; #endif // BOOKMARKSDIALOG_H diff --git a/lib/bookmarks/xbel.cpp b/lib/bookmarks/xbel.cpp index 1be9c7e..47d855b 100644 --- a/lib/bookmarks/xbel.cpp +++ b/lib/bookmarks/xbel.cpp @@ -9,37 +9,24 @@ #include "xbel.h" #include -Xbel::Xbel(const QString &path) +Xbel::Xbel(QIODevice *file) { - m_path = path; + Q_CHECK_PTR(file); + m_file = file; } bool Xbel::read(BookmarkItem *root) { - // if the path is empty, there is nothing to load - if(m_path.isEmpty()) { - return false; - } - - QFile file(m_path); - if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - // file cannot be opened for reading - return false; - } - - QXmlStreamReader xmlReader(&file); + QXmlStreamReader xmlReader(m_file); if(xmlReader.readNextStartElement()) { if(!(xmlReader.name() == "xbel" && xmlReader.attributes().value("version") == "1.0")) { - // invalid xbel - qWarning("Error parsing %s", qUtf8Printable(m_path)); return false; } readChildElements(xmlReader, root); } - file.close(); return true; } @@ -67,18 +54,7 @@ void Xbel::readChildElements(QXmlStreamReader &reader, BookmarkItem *parentItem) bool Xbel::write(BookmarkItem *root) { - - // if the path is empty, there is nothing to save to - if(m_path.isEmpty()) - return false; - - QFile file(m_path); - if(!file.open(QIODevice::WriteOnly | QIODevice::Text)) { - // file cannot be opened for writing - return false; - } - - QXmlStreamWriter xmlWriter(&file); + QXmlStreamWriter xmlWriter(m_file); xmlWriter.setAutoFormatting(true); xmlWriter.writeStartDocument(); @@ -91,7 +67,6 @@ bool Xbel::write(BookmarkItem *root) xmlWriter.writeEndDocument(); - file.close(); return true; } diff --git a/lib/bookmarks/xbel.h b/lib/bookmarks/xbel.h index 52f7072..f0945bf 100644 --- a/lib/bookmarks/xbel.h +++ b/lib/bookmarks/xbel.h @@ -16,7 +16,7 @@ class Xbel { public: - explicit Xbel(const QString &path); + explicit Xbel(QIODevice *file); bool read(BookmarkItem *root); bool write(BookmarkItem *root); @@ -24,7 +24,7 @@ private: void readChildElements(QXmlStreamReader &reader, BookmarkItem *parentItem); void writeChildElements(QXmlStreamWriter &writer, BookmarkItem *parentItem); - QString m_path; + QIODevice *m_file; }; #endif // XBELREADER_H -- cgit v1.2.1