]> cloud.milkyroute.net Git - dolphin.git/blob - src/kfileplacesmodel.cpp
Add the KFilePlacesModel class. It allows to list user's "places" (a mix
[dolphin.git] / src / kfileplacesmodel.cpp
1 /* This file is part of the KDE project
2 Copyright (C) 2007 Kevin Ottens <ervin@kde.org>
3 Copyright (C) 2007 David Faure <faure@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License version 2 as published by the Free Software Foundation.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
18
19 */
20 #include "kfileplacesmodel.h"
21 #include "kfileplacesitem_p.h"
22
23 #include <kglobal.h>
24 #include <kstandarddirs.h>
25 #include <kcomponentdata.h>
26 #include <kicon.h>
27
28 #include <kdevicelistmodel.h>
29 #include <kbookmarkmanager.h>
30 #include <kbookmark.h>
31
32 #include <solid/volume.h>
33
34 class KFilePlacesModel::Private
35 {
36 public:
37 Private(KFilePlacesModel *self) : q(self), deviceModel(0), bookmarkManager(0) {}
38
39
40 KFilePlacesModel *q;
41
42 QList<KFilePlacesItem*> items;
43 QMap<QString, QPersistentModelIndex> availableDevices;
44
45 KDeviceListModel *deviceModel;
46 KBookmarkManager *bookmarkManager;
47
48 QVariant bookmarkData(const QString &address, int role) const;
49 QVariant deviceData(const QPersistentModelIndex &index, int role) const;
50
51 void _k_devicesInserted(const QModelIndex &parent, int start, int end);
52 void _k_devicesRemoved(const QModelIndex &parent, int start, int end);
53 void _k_reloadBookmarks();
54 };
55
56 KFilePlacesModel::KFilePlacesModel(QObject *parent)
57 : QAbstractItemModel(parent), d(new Private(this))
58 {
59 QString basePath = KGlobal::mainComponent().componentName();
60 basePath.append("/bookmarks.xml");
61 const QString file = KStandardDirs::locateLocal("data", basePath);
62
63 d->bookmarkManager = KBookmarkManager::managerForFile(file, "dolphin", false);
64
65 d->deviceModel = new KDeviceListModel("IS Volume", this);
66
67 connect(d->deviceModel, SIGNAL(rowsInserted(const QModelIndex&, int, int)),
68 this, SLOT(_k_devicesInserted(const QModelIndex&, int, int)));
69 connect(d->deviceModel, SIGNAL(rowsAboutToBeRemoved(const QModelIndex&, int, int)),
70 this, SLOT(_k_devicesRemoved(const QModelIndex&, int, int)));
71 connect(d->bookmarkManager, SIGNAL(changed(const QString&, const QString&)),
72 this, SLOT(_k_reloadBookmarks()));
73
74 d->_k_reloadBookmarks();
75 }
76
77 KFilePlacesModel::~KFilePlacesModel()
78 {
79 delete d;
80 }
81
82 KUrl KFilePlacesModel::url(const QModelIndex &index) const
83 {
84 return KUrl(data(index, UrlRole).toString());
85 }
86
87 bool KFilePlacesModel::mountNeeded(const QModelIndex &index) const
88 {
89 return data(index, MountNeededRole).toBool();
90 }
91
92 QVariant KFilePlacesModel::data(const QModelIndex &index, int role) const
93 {
94 if (!index.isValid())
95 return QVariant();
96
97 QVariant returnData;
98
99 KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer());
100
101 if (item->isDevice()) {
102 returnData = d->deviceData(item->deviceIndex(), role);
103 } else {
104 returnData = d->bookmarkData(item->bookmarkAddress(), role);
105 }
106
107 return returnData;
108 }
109
110 QModelIndex KFilePlacesModel::index(int row, int column, const QModelIndex &parent) const
111 {
112 if (row<0 || column!=0 || row>=d->items.size())
113 return QModelIndex();
114
115 if (parent.isValid())
116 return QModelIndex();
117
118 return createIndex(row, column, d->items[row]);
119 }
120
121 QModelIndex KFilePlacesModel::parent(const QModelIndex &child) const
122 {
123 return QModelIndex();
124 }
125
126 int KFilePlacesModel::rowCount(const QModelIndex &parent) const
127 {
128 if (parent.isValid())
129 return 0;
130 else
131 return d->items.size();
132 }
133
134 int KFilePlacesModel::columnCount(const QModelIndex &parent) const
135 {
136 Q_UNUSED(parent)
137 // We only know 1 information for a particualiar entry
138 return 1;
139 }
140
141 QModelIndex KFilePlacesModel::closestItem(const KUrl &url) const
142 {
143 int foundRow = -1;
144 int maxLength = 0;
145
146 // Search the item which is equal to the URL or at least is a parent URL.
147 // If there are more than one possible item URL candidates, choose the item
148 // which covers the bigger range of the URL.
149 for (int row = 0; row<d->items.size(); ++row) {
150 KFilePlacesItem *item = d->items[row];
151 KUrl itemUrl;
152
153 if (item->isDevice()) {
154 itemUrl = KUrl(d->deviceData(item->deviceIndex(), UrlRole).toString());
155 } else {
156 itemUrl = KUrl(d->bookmarkData(item->bookmarkAddress(), UrlRole).toString());
157 }
158
159 if (itemUrl.isParentOf(url)) {
160 const int length = itemUrl.prettyUrl().length();
161 if (length > maxLength) {
162 foundRow = row;
163 maxLength = length;
164 }
165 }
166 }
167
168 if (foundRow==-1)
169 return QModelIndex();
170 else
171 return createIndex(foundRow, 0, d->items[foundRow]);
172 }
173
174 QVariant KFilePlacesModel::Private::bookmarkData(const QString &address, int role) const
175 {
176 KBookmark bookmark = bookmarkManager->findByAddress(address);
177
178 if (bookmark.isNull()) return QVariant();
179
180 switch (role)
181 {
182 case Qt::DisplayRole:
183 return bookmark.text();
184 case Qt::DecorationRole:
185 return KIcon(bookmark.icon());
186 case UrlRole:
187 return bookmark.url();
188 case MountNeededRole:
189 return false;
190 default:
191 return QVariant();
192 }
193 }
194
195 QVariant KFilePlacesModel::Private::deviceData(const QPersistentModelIndex &index, int role) const
196 {
197 if (index.isValid()) {
198 switch (role)
199 {
200 case UrlRole:
201 return KUrl(deviceModel->deviceForIndex(index).as<Solid::Volume>()->mountPoint());
202 case MountNeededRole:
203 return !deviceModel->deviceForIndex(index).as<Solid::Volume>()->isMounted();
204 default:
205 return deviceModel->data(index, role);
206 }
207 } else {
208 return QVariant();
209 }
210 }
211
212 void KFilePlacesModel::Private::_k_devicesInserted(const QModelIndex &parent, int start, int end)
213 {
214 for (int i = start; i<=end; ++i) {
215 QModelIndex index = parent.child(i, 0);
216 QString udi = deviceModel->deviceForIndex(index).udi();
217
218 availableDevices[udi] = index;
219 }
220
221 _k_reloadBookmarks();
222 }
223
224 void KFilePlacesModel::Private::_k_devicesRemoved(const QModelIndex &parent, int start, int end)
225 {
226 for (int i = start; i<=end; ++i) {
227 QModelIndex index = parent.child(i, 0);
228 // Can't find by UDI since the device is already invalid.
229 availableDevices.remove(availableDevices.key(index));
230 }
231
232 _k_reloadBookmarks();
233 }
234
235 void KFilePlacesModel::Private::_k_reloadBookmarks()
236 {
237 qDeleteAll(items);
238 items.clear();
239 q->reset();
240
241 KBookmarkGroup root = bookmarkManager->root();
242 KBookmark bookmark = root.first();
243 QMap<QString, QPersistentModelIndex> devices = availableDevices;
244
245 while (!bookmark.isNull()) {
246 QString udi = bookmark.metaDataItem("UDI");
247 QPersistentModelIndex index = devices.take(udi);
248
249 if (udi.isEmpty() || index.isValid()) {
250 q->beginInsertRows(QModelIndex(), items.size(), items.size());
251
252 KFilePlacesItem *item = new KFilePlacesItem();
253 item->setBookmarkAddress(bookmark.address());
254 if (index.isValid()) {
255 item->setDeviceIndex(index);
256 // TODO: Update bookmark internal element
257 }
258 items << item;
259
260 q->endInsertRows();
261 }
262
263 bookmark = root.next(bookmark);
264 }
265
266 // Add bookmarks for the remaining devices, they were previously unknown
267 foreach (QString udi, devices.keys()) {
268 bookmark = root.createNewSeparator();
269 bookmark.setMetaDataItem("UDI", udi);
270
271 q->beginInsertRows(QModelIndex(), items.size(), items.size());
272
273 KFilePlacesItem *item = new KFilePlacesItem();
274 item->setBookmarkAddress(bookmark.address());
275 item->setDeviceIndex(devices[udi]);
276 // TODO: Update bookmark internal element
277 items << item;
278
279 q->endInsertRows();
280 }
281 }
282
283 #include "kfileplacesmodel.moc"