1
mirror of https://invent.kde.org/network/falkon.git synced 2024-11-11 17:42:10 +01:00
falkonOfficial/src/lib/bookmarks/bookmarksmodel.cpp

338 lines
8.5 KiB
C++
Raw Normal View History

2014-02-07 22:48:30 +01:00
/* ============================================================
* QupZilla - WebKit based browser
* Copyright (C) 2014 David Rosca <nowrep@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
#include "bookmarksmodel.h"
#include "bookmarkitem.h"
#include "bookmarks.h"
#include "iconprovider.h"
#include <QApplication>
#include <QMimeData>
#include <QStyle>
//#define BOOKMARKSMODEL_DEBUG
#ifdef BOOKMARKSMODEL_DEBUG
#include <QTreeView>
#include "modeltest.h"
#endif
BookmarksModel::BookmarksModel(Bookmarks* bookmarks, QObject* parent)
: QAbstractItemModel(parent)
, m_bookmarks(bookmarks)
{
connect(m_bookmarks, SIGNAL(bookmarkChanged(BookmarkItem*)), this, SLOT(bookmarkChanged(BookmarkItem*)));
#ifdef BOOKMARKSMODEL_DEBUG
new ModelTest(this, this);
QTreeView* view = new QTreeView;
view->setModel(this);
view->setSelectionMode(QAbstractItemView::ExtendedSelection);
view->setDragEnabled(true);
view->setAcceptDrops(true);
view->setDropIndicatorShown(true);
view->expandAll();
view->show();
#endif
}
void BookmarksModel::addBookmark(BookmarkItem* parent, int row, BookmarkItem* item)
{
Q_ASSERT(parent);
Q_ASSERT(item);
Q_ASSERT(row >= 0);
Q_ASSERT(row <= parent->children().count());
beginInsertRows(index(parent), row, row);
parent->addChild(item, row);
endInsertRows();
}
void BookmarksModel::removeBookmark(BookmarkItem* item)
{
Q_ASSERT(item);
Q_ASSERT(item->parent());
int idx = item->parent()->children().indexOf(item);
beginRemoveRows(index(item->parent()), idx, idx);
item->parent()->removeChild(item);
endRemoveRows();
}
Qt::ItemFlags BookmarksModel::flags(const QModelIndex &index) const
{
BookmarkItem* itm = item(index);
if (!index.isValid() || !itm) {
return Qt::NoItemFlags;
}
Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
if (itm->type() == BookmarkItem::Folder) {
flags |= Qt::ItemIsDropEnabled;
}
if (m_bookmarks->canBeModified(itm)) {
flags |= Qt::ItemIsDragEnabled;
}
return flags;
}
QVariant BookmarksModel::data(const QModelIndex &index, int role) const
{
BookmarkItem* itm = item(index);
if (!itm) {
return QVariant();
}
switch (role) {
case TypeRole:
return itm->type();
case UrlRole:
return itm->url();
case TitleRole:
return itm->title();
case DescriptionRole:
return itm->description();
case KeywordRole:
return itm->keyword();
case ExpandedRole:
return itm->isExpanded();
case Qt::DisplayRole:
case Qt::ToolTipRole:
switch (index.column()) {
case 0:
return itm->title();
case 1:
return itm->url();
default:
return QVariant();
}
case Qt::DecorationRole:
if (index.column() != 0) {
return QVariant();
}
switch (itm->type()) {
case BookmarkItem::Folder:
return QApplication::style()->standardIcon(QStyle::SP_DirIcon);
case BookmarkItem::Url:
return _iconForUrl(itm->url());
default:
return QVariant();
}
default:
return QVariant();
}
}
QVariant BookmarksModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
switch (section) {
case 0:
return tr("Title");
case 1:
return tr("Address");
}
}
return QAbstractItemModel::headerData(section, orientation, role);
}
int BookmarksModel::rowCount(const QModelIndex &parent) const
{
if (parent.column() > 0) {
return 0;
}
BookmarkItem* itm = item(parent);
return itm->children().count();
}
int BookmarksModel::columnCount(const QModelIndex &parent) const
{
if (parent.column() > 0) {
return 0;
}
return 2;
}
bool BookmarksModel::hasChildren(const QModelIndex &parent) const
{
BookmarkItem* itm = item(parent);
return !itm->children().isEmpty();
}
#if 0
bool BookmarksModel::removeRows(int row, int count, const QModelIndex &parent)
{
if (!hasIndex(row, 0, parent) || !hasIndex(row + count, 0, parent)) {
return false;
}
BookmarkItem* itm = item(parent);
int offset = 0;
for (int i = 0; i < count; ++i) {
int idx = i + row + offset;
BookmarkItem* child = itm->children().at(idx);
if (!m_bookmarks->removeBookmark(child)) {
offset++;
continue;
}
}
return true;
}
#endif
Qt::DropActions BookmarksModel::supportedDropActions() const
{
return Qt::CopyAction | Qt::MoveAction;
}
#define MIMETYPE QLatin1String("application/qupzilla.bookmarks")
QStringList BookmarksModel::mimeTypes() const
{
QStringList types;
types.append(MIMETYPE);
return types;
}
QMimeData* BookmarksModel::mimeData(const QModelIndexList &indexes) const
{
QMimeData* mimeData = new QMimeData();
QByteArray encodedData;
QDataStream stream(&encodedData, QIODevice::WriteOnly);
foreach (const QModelIndex &index, indexes) {
// If item's parent (=folder) is also selected, we will just move the whole folder
if (index.isValid() && index.column() == 0 && !indexes.contains(index.parent())) {
stream << index.row() << (quint32) index.internalId();
}
}
mimeData->setData(MIMETYPE, encodedData);
return mimeData;
}
bool BookmarksModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
{
Q_UNUSED(column)
if (action == Qt::IgnoreAction) {
return true;
}
if (!data->hasFormat(MIMETYPE) || !parent.isValid()) {
return false;
}
BookmarkItem* parentItm = item(parent);
Q_ASSERT(parentItm->type() == BookmarkItem::Folder);
QByteArray encodedData = data->data(MIMETYPE);
QDataStream stream(&encodedData, QIODevice::ReadOnly);
QList<BookmarkItem*> items;
while (!stream.atEnd()) {
int row;
quint32 id;
stream >> row >> id;
QModelIndex index = createIndex(row, 0, id);
BookmarkItem* itm = item(index);
Q_ASSERT(index.isValid());
Q_ASSERT(itm != m_bookmarks->rootItem());
// Cannot move bookmark to itself
if (itm == parentItm) {
return false;
}
items.append(itm);
}
row = qMax(row, 0);
foreach (BookmarkItem* itm, items) {
// If we are moving an item through the folder and item is above the row to insert,
// we must decrease row by one (by the dropped folder)
if (itm->parent() == parentItm && itm->parent()->children().indexOf(itm) < row) {
row--;
}
m_bookmarks->removeBookmark(itm);
m_bookmarks->insertBookmark(parentItm, row++, itm);
}
return true;
}
QModelIndex BookmarksModel::parent(const QModelIndex &child) const
{
if (!child.isValid()) {
return QModelIndex();
}
BookmarkItem* itm = item(child);
return index(itm->parent());
}
QModelIndex BookmarksModel::index(int row, int column, const QModelIndex &parent) const
{
if (!hasIndex(row, column, parent)) {
return QModelIndex();
}
BookmarkItem* parentItem = item(parent);
return createIndex(row, column, parentItem->children().at(row));
}
QModelIndex BookmarksModel::index(BookmarkItem* item) const
{
BookmarkItem* parent = item->parent();
if (!parent) {
return QModelIndex();
}
return createIndex(parent->children().indexOf(item), 0, item);
}
void BookmarksModel::bookmarkChanged(BookmarkItem* item)
{
QModelIndex idx = index(item);
emit dataChanged(idx, idx);
}
BookmarkItem* BookmarksModel::item(const QModelIndex &index) const
{
BookmarkItem* itm = static_cast<BookmarkItem*>(index.internalPointer());
return itm ? itm : m_bookmarks->rootItem();
}