From: Kevin Ottens Date: Sun, 1 Apr 2007 22:28:03 +0000 (+0000) Subject: Add the KFilePlacesModel class. It allows to list user's "places" (a mix X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/commitdiff_plain/056ac9a271f3a8fec02326ed0b478c3a71baaf0c Add the KFilePlacesModel class. It allows to list user's "places" (a mix of bookmarks and volume devices). Still incomplete, for now it simply list the places (drag and drop, and more interaction needs to be implemented). It's supposed to move into kdelibs/kio soon. svn path=/trunk/KDE/kdebase/apps/; revision=649038 --- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 90a4b121f..015c71ee5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -37,6 +37,8 @@ install(TARGETS dolphinprivate DESTINATION ${LIB_INSTALL_DIR} ) set(dolphin_SRCS applyviewpropsjob.cpp + kfileplacesmodel.cpp + kfileplacesitem.cpp bookmarkselector.cpp bookmarkssettingspage.cpp bookmarkssidebarpage.cpp diff --git a/src/dolphinmainwindow.cpp b/src/dolphinmainwindow.cpp index 5a78ff98e..767db820d 100644 --- a/src/dolphinmainwindow.cpp +++ b/src/dolphinmainwindow.cpp @@ -35,6 +35,7 @@ #include "urlnavigator.h" #include "viewpropertiesdialog.h" #include "viewproperties.h" +#include "kfileplacesmodel.h" #include "dolphin_generalsettings.h" @@ -1332,6 +1333,15 @@ void DolphinMainWindow::setupDockWidgets() infoDock->hide(); treeViewDock->hide(); } + + // FIXME: To merge with the current bookmark sidebar + QDockWidget *placesDock = new QDockWidget(i18n("Places")); + placesDock->setObjectName("placesDock"); + placesDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); + QListView *listView = new QListView(placesDock); + placesDock->setWidget(listView); + listView->setModel(new KFilePlacesModel(listView)); + addDockWidget(Qt::LeftDockWidgetArea, placesDock); } void DolphinMainWindow::updateHistory() diff --git a/src/kfileplacesitem.cpp b/src/kfileplacesitem.cpp new file mode 100644 index 000000000..bbef32bc9 --- /dev/null +++ b/src/kfileplacesitem.cpp @@ -0,0 +1,56 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "kfileplacesitem_p.h" + +KFilePlacesItem::KFilePlacesItem() + : m_isDevice(false) +{ +} + +KFilePlacesItem::~KFilePlacesItem() +{ +} + +bool KFilePlacesItem::isDevice() const +{ + return m_isDevice; +} + +QString KFilePlacesItem::bookmarkAddress() const +{ + return m_bookmarkAddress; +} + +void KFilePlacesItem::setBookmarkAddress(const QString &address) +{ + m_bookmarkAddress = address; +} + +QPersistentModelIndex KFilePlacesItem::deviceIndex() const +{ + return m_deviceIndex; +} + +void KFilePlacesItem::setDeviceIndex(const QPersistentModelIndex &index) +{ + m_deviceIndex = index; + m_isDevice = index.isValid(); +} + diff --git a/src/kfileplacesitem_p.h b/src/kfileplacesitem_p.h new file mode 100644 index 000000000..e3aed78ea --- /dev/null +++ b/src/kfileplacesitem_p.h @@ -0,0 +1,45 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Kevin Ottens + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ +#ifndef KFILEPLACESITEM_P_H +#define KFILEPLACESITEM_P_H + +#include +#include + +class KFilePlacesItem +{ +public: + KFilePlacesItem(); + ~KFilePlacesItem(); + + bool isDevice() const; + + QString bookmarkAddress() const; + void setBookmarkAddress(const QString &address); + + QPersistentModelIndex deviceIndex() const; + void setDeviceIndex(const QPersistentModelIndex &index); + +private: + bool m_isDevice; + QString m_bookmarkAddress; + QPersistentModelIndex m_deviceIndex; +}; + +#endif diff --git a/src/kfileplacesmodel.cpp b/src/kfileplacesmodel.cpp new file mode 100644 index 000000000..00ee52d43 --- /dev/null +++ b/src/kfileplacesmodel.cpp @@ -0,0 +1,283 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Kevin Ottens + Copyright (C) 2007 David Faure + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ +#include "kfileplacesmodel.h" +#include "kfileplacesitem_p.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include + +class KFilePlacesModel::Private +{ +public: + Private(KFilePlacesModel *self) : q(self), deviceModel(0), bookmarkManager(0) {} + + + KFilePlacesModel *q; + + QList items; + QMap availableDevices; + + KDeviceListModel *deviceModel; + KBookmarkManager *bookmarkManager; + + QVariant bookmarkData(const QString &address, int role) const; + QVariant deviceData(const QPersistentModelIndex &index, int role) const; + + void _k_devicesInserted(const QModelIndex &parent, int start, int end); + void _k_devicesRemoved(const QModelIndex &parent, int start, int end); + void _k_reloadBookmarks(); +}; + +KFilePlacesModel::KFilePlacesModel(QObject *parent) + : QAbstractItemModel(parent), d(new Private(this)) +{ + QString basePath = KGlobal::mainComponent().componentName(); + basePath.append("/bookmarks.xml"); + const QString file = KStandardDirs::locateLocal("data", basePath); + + d->bookmarkManager = KBookmarkManager::managerForFile(file, "dolphin", false); + + d->deviceModel = new KDeviceListModel("IS Volume", this); + + connect(d->deviceModel, SIGNAL(rowsInserted(const QModelIndex&, int, int)), + this, SLOT(_k_devicesInserted(const QModelIndex&, int, int))); + connect(d->deviceModel, SIGNAL(rowsAboutToBeRemoved(const QModelIndex&, int, int)), + this, SLOT(_k_devicesRemoved(const QModelIndex&, int, int))); + connect(d->bookmarkManager, SIGNAL(changed(const QString&, const QString&)), + this, SLOT(_k_reloadBookmarks())); + + d->_k_reloadBookmarks(); +} + +KFilePlacesModel::~KFilePlacesModel() +{ + delete d; +} + +KUrl KFilePlacesModel::url(const QModelIndex &index) const +{ + return KUrl(data(index, UrlRole).toString()); +} + +bool KFilePlacesModel::mountNeeded(const QModelIndex &index) const +{ + return data(index, MountNeededRole).toBool(); +} + +QVariant KFilePlacesModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + QVariant returnData; + + KFilePlacesItem *item = static_cast(index.internalPointer()); + + if (item->isDevice()) { + returnData = d->deviceData(item->deviceIndex(), role); + } else { + returnData = d->bookmarkData(item->bookmarkAddress(), role); + } + + return returnData; +} + +QModelIndex KFilePlacesModel::index(int row, int column, const QModelIndex &parent) const +{ + if (row<0 || column!=0 || row>=d->items.size()) + return QModelIndex(); + + if (parent.isValid()) + return QModelIndex(); + + return createIndex(row, column, d->items[row]); +} + +QModelIndex KFilePlacesModel::parent(const QModelIndex &child) const +{ + return QModelIndex(); +} + +int KFilePlacesModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) + return 0; + else + return d->items.size(); +} + +int KFilePlacesModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + // We only know 1 information for a particualiar entry + return 1; +} + +QModelIndex KFilePlacesModel::closestItem(const KUrl &url) const +{ + int foundRow = -1; + int maxLength = 0; + + // Search the item which is equal to the URL or at least is a parent URL. + // If there are more than one possible item URL candidates, choose the item + // which covers the bigger range of the URL. + for (int row = 0; rowitems.size(); ++row) { + KFilePlacesItem *item = d->items[row]; + KUrl itemUrl; + + if (item->isDevice()) { + itemUrl = KUrl(d->deviceData(item->deviceIndex(), UrlRole).toString()); + } else { + itemUrl = KUrl(d->bookmarkData(item->bookmarkAddress(), UrlRole).toString()); + } + + if (itemUrl.isParentOf(url)) { + const int length = itemUrl.prettyUrl().length(); + if (length > maxLength) { + foundRow = row; + maxLength = length; + } + } + } + + if (foundRow==-1) + return QModelIndex(); + else + return createIndex(foundRow, 0, d->items[foundRow]); +} + +QVariant KFilePlacesModel::Private::bookmarkData(const QString &address, int role) const +{ + KBookmark bookmark = bookmarkManager->findByAddress(address); + + if (bookmark.isNull()) return QVariant(); + + switch (role) + { + case Qt::DisplayRole: + return bookmark.text(); + case Qt::DecorationRole: + return KIcon(bookmark.icon()); + case UrlRole: + return bookmark.url(); + case MountNeededRole: + return false; + default: + return QVariant(); + } +} + +QVariant KFilePlacesModel::Private::deviceData(const QPersistentModelIndex &index, int role) const +{ + if (index.isValid()) { + switch (role) + { + case UrlRole: + return KUrl(deviceModel->deviceForIndex(index).as()->mountPoint()); + case MountNeededRole: + return !deviceModel->deviceForIndex(index).as()->isMounted(); + default: + return deviceModel->data(index, role); + } + } else { + return QVariant(); + } +} + +void KFilePlacesModel::Private::_k_devicesInserted(const QModelIndex &parent, int start, int end) +{ + for (int i = start; i<=end; ++i) { + QModelIndex index = parent.child(i, 0); + QString udi = deviceModel->deviceForIndex(index).udi(); + + availableDevices[udi] = index; + } + + _k_reloadBookmarks(); +} + +void KFilePlacesModel::Private::_k_devicesRemoved(const QModelIndex &parent, int start, int end) +{ + for (int i = start; i<=end; ++i) { + QModelIndex index = parent.child(i, 0); + // Can't find by UDI since the device is already invalid. + availableDevices.remove(availableDevices.key(index)); + } + + _k_reloadBookmarks(); +} + +void KFilePlacesModel::Private::_k_reloadBookmarks() +{ + qDeleteAll(items); + items.clear(); + q->reset(); + + KBookmarkGroup root = bookmarkManager->root(); + KBookmark bookmark = root.first(); + QMap devices = availableDevices; + + while (!bookmark.isNull()) { + QString udi = bookmark.metaDataItem("UDI"); + QPersistentModelIndex index = devices.take(udi); + + if (udi.isEmpty() || index.isValid()) { + q->beginInsertRows(QModelIndex(), items.size(), items.size()); + + KFilePlacesItem *item = new KFilePlacesItem(); + item->setBookmarkAddress(bookmark.address()); + if (index.isValid()) { + item->setDeviceIndex(index); + // TODO: Update bookmark internal element + } + items << item; + + q->endInsertRows(); + } + + bookmark = root.next(bookmark); + } + + // Add bookmarks for the remaining devices, they were previously unknown + foreach (QString udi, devices.keys()) { + bookmark = root.createNewSeparator(); + bookmark.setMetaDataItem("UDI", udi); + + q->beginInsertRows(QModelIndex(), items.size(), items.size()); + + KFilePlacesItem *item = new KFilePlacesItem(); + item->setBookmarkAddress(bookmark.address()); + item->setDeviceIndex(devices[udi]); + // TODO: Update bookmark internal element + items << item; + + q->endInsertRows(); + } +} + +#include "kfileplacesmodel.moc" diff --git a/src/kfileplacesmodel.h b/src/kfileplacesmodel.h new file mode 100644 index 000000000..42c37aafa --- /dev/null +++ b/src/kfileplacesmodel.h @@ -0,0 +1,106 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Kevin Ottens + Copyright (C) 2007 David Faure + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ +#ifndef KFILEPLACESMODEL_H +#define KFILEPLACESMODEL_H + +#include + +#include +#include + +/** + * This class is a list view model. Each entry represents a "place" + * where user can access files. Only revelant when + * used with QListView or QTableView. + */ +class KIO_EXPORT KFilePlacesModel : public QAbstractItemModel +{ + Q_OBJECT +public: + enum AdditionalRoles { + UrlRole = 0x069CD12B, + HiddenRole = 0x0741CAAC, + MountNeededRole = 0x059A935D + }; + + KFilePlacesModel(QObject *parent=0); + ~KFilePlacesModel(); + + KUrl url(const QModelIndex &index) const; + bool mountNeeded(const QModelIndex &index) const; + + /** + * @brief Get a visible data based on Qt role for the given index. + * Return the device information for the give index. + * + * @param index The QModelIndex which contains the row, column to fetch the data. + * @param role The Interview data role(ex: Qt::DisplayRole). + * + * @return the data for the given index and role. + */ + QVariant data(const QModelIndex &index, int role) const; + + /** + * @brief Get the children model index for the given row and column. + */ + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + + /** + * @brief Get the parent QModelIndex for the given model child. + */ + QModelIndex parent(const QModelIndex &child) const; + + /** + * @brief Get the number of rows for a model index. + */ + int rowCount(const QModelIndex &parent = QModelIndex()) const; + + /** + * @brief Get the number of columns for a model index. + */ + int columnCount(const QModelIndex &parent = QModelIndex()) const; + + /** + * Returns the closest item for the URL \a url. + * The closest item is defined as item which is equal to + * the URL or at least is a parent URL. If there are more than + * one possible parent URL candidates, the item which covers + * the bigger range of the URL is returned. + * + * Example: the url is '/home/peter/Documents/Music'. + * Available items are: + * - /home/peter + * - /home/peter/Documents + * + * The returned item will the one for '/home/peter/Documents'. + */ + QModelIndex closestItem(const KUrl &url) const; + +private: + Q_PRIVATE_SLOT(d, void _k_devicesInserted(const QModelIndex&, int, int)) + Q_PRIVATE_SLOT(d, void _k_devicesRemoved(const QModelIndex&, int, int)) + Q_PRIVATE_SLOT(d, void _k_reloadBookmarks()) + + class Private; + Private * const d; + friend class Private; +}; + +#endif