Annotation of /trunk/kdelibs/patches/kdelibs-4.9.4-udisks2-kfileplacesdevicecache.patch
Parent Directory | Revision Log
Revision 1990 -
(hide annotations)
(download)
Mon Dec 10 15:50:04 2012 UTC (11 years, 9 months ago) by niro
File size: 12357 byte(s)
Mon Dec 10 15:50:04 2012 UTC (11 years, 9 months ago) by niro
File size: 12357 byte(s)
-added udisks2 patches
1 | niro | 1990 | diff --git a/kfile/CMakeLists.txt b/kfile/CMakeLists.txt |
2 | index ceae140..c7c4d3d 100644 | ||
3 | --- a/kfile/CMakeLists.txt | ||
4 | +++ b/kfile/CMakeLists.txt | ||
5 | @@ -20,6 +20,7 @@ set(kfile_LIB_SRCS | ||
6 | kfilefiltercombo.cpp | ||
7 | kfiletreeview.cpp | ||
8 | kfilewidget.cpp | ||
9 | + kfileplacesdevicecache.cpp | ||
10 | kfileplacesitem.cpp | ||
11 | kfileplacesmodel.cpp | ||
12 | kfileplacessharedbookmarks.cpp | ||
13 | @@ -63,6 +64,7 @@ install( FILES | ||
14 | kdirselectdialog.h | ||
15 | kdirsortfilterproxymodel.h | ||
16 | kfilefiltercombo.h | ||
17 | + kfileplacesdevicecache.h | ||
18 | kfileplacesmodel.h | ||
19 | kfileplacesview.h | ||
20 | kfilepreviewgenerator.h | ||
21 | diff --git a/kfile/kfileplacesdevicecache.cpp b/kfile/kfileplacesdevicecache.cpp | ||
22 | new file mode 100644 | ||
23 | index 0000000..40f7242 | ||
24 | --- /dev/null | ||
25 | +++ b/kfile/kfileplacesdevicecache.cpp | ||
26 | @@ -0,0 +1,174 @@ | ||
27 | +/* | ||
28 | + Copyright (C) 2012 Dan Vrátil <dvratil@redhat.com> | ||
29 | + | ||
30 | + This library is free software; you can redistribute it and/or | ||
31 | + modify it under the terms of the GNU Library General Public | ||
32 | + License version 2 as published by the Free Software Foundation. | ||
33 | + | ||
34 | + This library is distributed in the hope that it will be useful, | ||
35 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
36 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
37 | + Library General Public License for more details. | ||
38 | + | ||
39 | + You should have received a copy of the GNU Library General Public License | ||
40 | + along with this library; see the file COPYING.LIB. If not, write to | ||
41 | + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
42 | + Boston, MA 02110-1301, USA. | ||
43 | +*/ | ||
44 | + | ||
45 | +#include "kfileplacesdevicecache.h" | ||
46 | + | ||
47 | +#include <QMutex> | ||
48 | +#include <QtConcurrentRun> | ||
49 | +#include <QFutureWatcher> | ||
50 | +#include <QTimer> | ||
51 | + | ||
52 | +#include <kprotocolinfo.h> | ||
53 | +#include <solid/predicate.h> | ||
54 | +#include <solid/device.h> | ||
55 | +#include <solid/devicenotifier.h> | ||
56 | +#include <solid/genericinterface.h> | ||
57 | + | ||
58 | +#include <kdebug.h> | ||
59 | + | ||
60 | +KFilePlacesDeviceCache* KFilePlacesDeviceCache::s_instance = 0; | ||
61 | + | ||
62 | +class KFilePlacesDeviceCache::Private | ||
63 | +{ | ||
64 | + public: | ||
65 | + Private(KFilePlacesDeviceCache *parent): | ||
66 | + queryRunning(false), | ||
67 | + q(parent) | ||
68 | + { } | ||
69 | + | ||
70 | + ~Private() | ||
71 | + { } | ||
72 | + | ||
73 | + /* This method runs asynchronously in thread */ | ||
74 | + QSet<QString> listSolidDevicesAsync() | ||
75 | + { | ||
76 | + QSet<QString> udis; | ||
77 | + | ||
78 | + kDebug() << "Querying Solid devices..."; | ||
79 | + const QList<Solid::Device>& deviceList = Solid::Device::listFromQuery(solidPredicate); | ||
80 | + kDebug() << "Retrieved" << deviceList.count() << "devices"; | ||
81 | + | ||
82 | + Q_FOREACH (const Solid::Device& device, deviceList) { | ||
83 | + if (solidPredicate.matches(device)) { | ||
84 | + udis << device.udi(); | ||
85 | + } | ||
86 | + } | ||
87 | + | ||
88 | + return udis; | ||
89 | + } | ||
90 | + | ||
91 | + void _k_slotDeviceAdded(const QString &udi) | ||
92 | + { | ||
93 | + devicesCache << udi; | ||
94 | + | ||
95 | + Q_EMIT q->deviceAdded(udi); | ||
96 | + } | ||
97 | + | ||
98 | + void _k_slotDeviceRemoved(const QString &udi) | ||
99 | + { | ||
100 | + if (!devicesCache.contains(udi)) { | ||
101 | + return; | ||
102 | + } | ||
103 | + | ||
104 | + devicesCache.remove(udi); | ||
105 | + | ||
106 | + Q_EMIT q->deviceRemoved(udi); | ||
107 | + } | ||
108 | + | ||
109 | + void _k_listSolidDevicesFinished() | ||
110 | + { | ||
111 | + Q_FOREACH (const QString& device, futureWatcher->result()) { | ||
112 | + _k_slotDeviceAdded(device); | ||
113 | + } | ||
114 | + | ||
115 | + delete futureWatcher; | ||
116 | + futureWatcher = 0; | ||
117 | + | ||
118 | + queryRunning = false; | ||
119 | + } | ||
120 | + | ||
121 | + Solid::Predicate solidPredicate; | ||
122 | + | ||
123 | + QFutureWatcher< QSet<QString> >* futureWatcher; | ||
124 | + | ||
125 | + /* Static */ | ||
126 | + QSet<QString> devicesCache; | ||
127 | + bool queryRunning; | ||
128 | + | ||
129 | + KFilePlacesDeviceCache *q; | ||
130 | +}; | ||
131 | + | ||
132 | +KFilePlacesDeviceCache::KFilePlacesDeviceCache(): | ||
133 | + QObject(), | ||
134 | + d(new Private(this)) | ||
135 | +{ | ||
136 | + Solid::DeviceNotifier* notifier = Solid::DeviceNotifier::instance(); | ||
137 | + connect(notifier, SIGNAL(deviceAdded(QString)), this, SLOT(_k_slotDeviceAdded(QString))); | ||
138 | + connect(notifier, SIGNAL(deviceRemoved(QString)), this, SLOT(_k_slotDeviceRemoved(QString))); | ||
139 | + | ||
140 | + QString predicate("[[[[ StorageVolume.ignored == false AND [ StorageVolume.usage == 'FileSystem' OR StorageVolume.usage == 'Encrypted' ]]" | ||
141 | + " OR " | ||
142 | + "[ IS StorageAccess AND StorageDrive.driveType == 'Floppy' ]]" | ||
143 | + " OR " | ||
144 | + "OpticalDisc.availableContent & 'Audio' ]" | ||
145 | + " OR " | ||
146 | + "StorageAccess.ignored == false ]"); | ||
147 | + | ||
148 | + if (KProtocolInfo::isKnownProtocol("mtp")) { | ||
149 | + predicate.prepend("["); | ||
150 | + predicate.append(" OR PortableMediaPlayer.supportedProtocols == 'mtp']"); | ||
151 | + } | ||
152 | + | ||
153 | + d->solidPredicate = Solid::Predicate::fromString(predicate); | ||
154 | +} | ||
155 | + | ||
156 | +KFilePlacesDeviceCache* KFilePlacesDeviceCache::self() | ||
157 | +{ | ||
158 | + static QMutex mutex; | ||
159 | + | ||
160 | + mutex.lock(); | ||
161 | + if (s_instance == 0) { | ||
162 | + s_instance = new KFilePlacesDeviceCache(); | ||
163 | + } | ||
164 | + mutex.unlock(); | ||
165 | + | ||
166 | + return s_instance; | ||
167 | +} | ||
168 | + | ||
169 | +KFilePlacesDeviceCache::~KFilePlacesDeviceCache() | ||
170 | +{ | ||
171 | + Solid::DeviceNotifier* notifier = Solid::DeviceNotifier::instance(); | ||
172 | + disconnect(notifier, SIGNAL(deviceAdded(QString))); | ||
173 | + disconnect(notifier, SIGNAL(deviceRemoved(QString))); | ||
174 | + | ||
175 | + delete d; | ||
176 | +} | ||
177 | + | ||
178 | +const Solid::Predicate& KFilePlacesDeviceCache::predicate() const | ||
179 | +{ | ||
180 | + return d->solidPredicate; | ||
181 | +} | ||
182 | + | ||
183 | +const QSet<QString>& KFilePlacesDeviceCache::devices() const | ||
184 | +{ | ||
185 | + kDebug(); | ||
186 | + if (d->devicesCache.isEmpty() && !d->queryRunning) { | ||
187 | + d->queryRunning = true; | ||
188 | + d->futureWatcher = new QFutureWatcher< QSet<QString> >; | ||
189 | + connect(d->futureWatcher, SIGNAL(finished()), this, SLOT(_k_listSolidDevicesFinished())); | ||
190 | + | ||
191 | + QFuture< QSet<QString> > future = QtConcurrent::run(d, &Private::listSolidDevicesAsync); | ||
192 | + d->futureWatcher->setFuture(future); | ||
193 | + } | ||
194 | + | ||
195 | + return d->devicesCache; | ||
196 | +} | ||
197 | + | ||
198 | + | ||
199 | + | ||
200 | +#include "kfileplacesdevicecache.moc" | ||
201 | diff --git a/kfile/kfileplacesdevicecache.h b/kfile/kfileplacesdevicecache.h | ||
202 | new file mode 100644 | ||
203 | index 0000000..7293d03 | ||
204 | --- /dev/null | ||
205 | +++ b/kfile/kfileplacesdevicecache.h | ||
206 | @@ -0,0 +1,96 @@ | ||
207 | +/* | ||
208 | + Copyright (C) 2012 Dan Vrátil <dvratil@redhat.com> | ||
209 | + | ||
210 | + This library is free software; you can redistribute it and/or | ||
211 | + modify it under the terms of the GNU Library General Public | ||
212 | + License version 2 as published by the Free Software Foundation. | ||
213 | + | ||
214 | + This library is distributed in the hope that it will be useful, | ||
215 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
216 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
217 | + Library General Public License for more details. | ||
218 | + | ||
219 | + You should have received a copy of the GNU Library General Public License | ||
220 | + along with this library; see the file COPYING.LIB. If not, write to | ||
221 | + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
222 | + Boston, MA 02110-1301, USA. | ||
223 | +*/ | ||
224 | + | ||
225 | +#ifndef KFILEPLACESDEVICECACHE_H | ||
226 | +#define KFILEPLACESDEVICECACHE_H | ||
227 | + | ||
228 | +#include <kfile_export.h> | ||
229 | + | ||
230 | +#include <QObject> | ||
231 | +#include <QSet> | ||
232 | + | ||
233 | +#include <solid/predicate.h> | ||
234 | + | ||
235 | +/** | ||
236 | + * @short Asynchronous cache for Solid devices | ||
237 | + * | ||
238 | + * Purpose of this cache is to load Solid devices asynchronously, because | ||
239 | + * udisks2 backend can take quite a lot of time to enumerate devices, and | ||
240 | + * since Solid does not have async API, the UI thread is blocked for too long. | ||
241 | + * | ||
242 | + * When libsolid2 with asynchronous API is available, this class can go away. | ||
243 | + * | ||
244 | + * The cache keeps itself up-to-date and notifies listeners when a | ||
245 | + * new devices is added or removed. | ||
246 | + */ | ||
247 | +class KFILE_EXPORT KFilePlacesDeviceCache : public QObject | ||
248 | +{ | ||
249 | + Q_OBJECT | ||
250 | + | ||
251 | +public: | ||
252 | + /** | ||
253 | + * Returns a global instance of the cache | ||
254 | + */ | ||
255 | + static KFilePlacesDeviceCache* self(); | ||
256 | + | ||
257 | + /** | ||
258 | + * Returns list of Solid devices. | ||
259 | + * | ||
260 | + * This method always returns immediatelly. When there are no | ||
261 | + * devices in the cache, it returns an empty list and will asynchronously | ||
262 | + * query Solid for devices and will notify listeners by emitting | ||
263 | + * deviceAdded() signal for each devices loaded. | ||
264 | + */ | ||
265 | + const QSet<QString>& devices() const; | ||
266 | + | ||
267 | + /** | ||
268 | + * Returns Solid::Predicate used to obtain devices from Solid | ||
269 | + */ | ||
270 | + const Solid::Predicate& predicate() const; | ||
271 | + | ||
272 | +Q_SIGNALS: | ||
273 | + /** | ||
274 | + * Emitted whenever a new device is discovered. | ||
275 | + * | ||
276 | + * @param udi UDI (Universal Device ID) of the newly discovered device | ||
277 | + */ | ||
278 | + void deviceAdded(const QString& udi); | ||
279 | + | ||
280 | + /** | ||
281 | + * Emitted whenever a device is removed from system | ||
282 | + * | ||
283 | + * @param udi UDI (Universal Device ID) of the removed device | ||
284 | + */ | ||
285 | + void deviceRemoved(const QString& udi); | ||
286 | + | ||
287 | +private: | ||
288 | + Q_PRIVATE_SLOT(d, void _k_listSolidDevicesFinished()) | ||
289 | + Q_PRIVATE_SLOT(d, void _k_slotDeviceAdded(const QString&)) | ||
290 | + Q_PRIVATE_SLOT(d, void _k_slotDeviceRemoved(const QString&)) | ||
291 | + | ||
292 | + class Private; | ||
293 | + Private * const d; | ||
294 | + friend class Private; | ||
295 | + | ||
296 | + explicit KFilePlacesDeviceCache(); | ||
297 | + virtual ~KFilePlacesDeviceCache(); | ||
298 | + | ||
299 | + static KFilePlacesDeviceCache* s_instance; | ||
300 | +}; | ||
301 | + | ||
302 | +#endif // KFILEPLACESDEVICECACHE_H | ||
303 | diff --git a/kfile/kfileplacesmodel.cpp b/kfile/kfileplacesmodel.cpp | ||
304 | index 0192926..e0b01c6 100644 | ||
305 | --- a/kfile/kfileplacesmodel.cpp | ||
306 | +++ b/kfile/kfileplacesmodel.cpp | ||
307 | @@ -20,6 +20,7 @@ | ||
308 | #include "kfileplacesmodel.h" | ||
309 | #include "kfileplacesitem_p.h" | ||
310 | #include "kfileplacessharedbookmarks_p.h" | ||
311 | +#include "kfileplacesdevicecache.h" | ||
312 | |||
313 | #ifdef _WIN32_WCE | ||
314 | #include "Windows.h" | ||
315 | @@ -49,14 +50,12 @@ | ||
316 | #include <kio/netaccess.h> | ||
317 | #include <kprotocolinfo.h> | ||
318 | |||
319 | -#include <solid/devicenotifier.h> | ||
320 | #include <solid/storageaccess.h> | ||
321 | #include <solid/storagedrive.h> | ||
322 | #include <solid/storagevolume.h> | ||
323 | #include <solid/opticaldrive.h> | ||
324 | #include <solid/opticaldisc.h> | ||
325 | #include <solid/portablemediaplayer.h> | ||
326 | -#include <solid/predicate.h> | ||
327 | |||
328 | class KFilePlacesModel::Private | ||
329 | { | ||
330 | @@ -74,7 +73,6 @@ public: | ||
331 | QSet<QString> availableDevices; | ||
332 | QMap<QObject*, QPersistentModelIndex> setupInProgress; | ||
333 | |||
334 | - Solid::Predicate predicate; | ||
335 | KBookmarkManager *bookmarkManager; | ||
336 | KFilePlacesSharedBookmarks * sharedBookmarks; | ||
337 | |||
338 | @@ -149,30 +147,12 @@ KFilePlacesModel::KFilePlacesModel(QObject *parent) | ||
339 | // create after, so if we have own places, they are added afterwards, in case of equal priorities | ||
340 | d->sharedBookmarks = new KFilePlacesSharedBookmarks(d->bookmarkManager); | ||
341 | |||
342 | - QString predicate("[[[[ StorageVolume.ignored == false AND [ StorageVolume.usage == 'FileSystem' OR StorageVolume.usage == 'Encrypted' ]]" | ||
343 | - " OR " | ||
344 | - "[ IS StorageAccess AND StorageDrive.driveType == 'Floppy' ]]" | ||
345 | - " OR " | ||
346 | - "OpticalDisc.availableContent & 'Audio' ]" | ||
347 | - " OR " | ||
348 | - "StorageAccess.ignored == false ]"); | ||
349 | - | ||
350 | - if (KProtocolInfo::isKnownProtocol("mtp")) { | ||
351 | - predicate.prepend("["); | ||
352 | - predicate.append(" OR PortableMediaPlayer.supportedProtocols == 'mtp']"); | ||
353 | - } | ||
354 | - | ||
355 | - d->predicate = Solid::Predicate::fromString(predicate); | ||
356 | - | ||
357 | - Q_ASSERT(d->predicate.isValid()); | ||
358 | - | ||
359 | connect(d->bookmarkManager, SIGNAL(changed(QString,QString)), | ||
360 | this, SLOT(_k_reloadBookmarks())); | ||
361 | connect(d->bookmarkManager, SIGNAL(bookmarksChanged(QString)), | ||
362 | this, SLOT(_k_reloadBookmarks())); | ||
363 | |||
364 | - d->_k_reloadBookmarks(); | ||
365 | - QTimer::singleShot(0, this, SLOT(_k_initDeviceList())); | ||
366 | + d->_k_initDeviceList(); | ||
367 | } | ||
368 | |||
369 | KFilePlacesModel::~KFilePlacesModel() | ||
370 | @@ -313,30 +293,21 @@ QModelIndex KFilePlacesModel::closestItem(const KUrl &url) const | ||
371 | |||
372 | void KFilePlacesModel::Private::_k_initDeviceList() | ||
373 | { | ||
374 | - Solid::DeviceNotifier *notifier = Solid::DeviceNotifier::instance(); | ||
375 | - | ||
376 | - connect(notifier, SIGNAL(deviceAdded(QString)), | ||
377 | + KFilePlacesDeviceCache *cache = KFilePlacesDeviceCache::self(); | ||
378 | + connect(cache, SIGNAL(deviceAdded(QString)), | ||
379 | q, SLOT(_k_deviceAdded(QString))); | ||
380 | - connect(notifier, SIGNAL(deviceRemoved(QString)), | ||
381 | + connect(cache, SIGNAL(deviceRemoved(QString)), | ||
382 | q, SLOT(_k_deviceRemoved(QString))); | ||
383 | |||
384 | - const QList<Solid::Device> &deviceList = Solid::Device::listFromQuery(predicate); | ||
385 | - | ||
386 | - foreach(const Solid::Device &device, deviceList) { | ||
387 | - availableDevices << device.udi(); | ||
388 | - } | ||
389 | + availableDevices = cache->devices(); | ||
390 | |||
391 | _k_reloadBookmarks(); | ||
392 | } | ||
393 | |||
394 | void KFilePlacesModel::Private::_k_deviceAdded(const QString &udi) | ||
395 | { | ||
396 | - Solid::Device d(udi); | ||
397 | - | ||
398 | - if (predicate.matches(d)) { | ||
399 | - availableDevices << udi; | ||
400 | - _k_reloadBookmarks(); | ||
401 | - } | ||
402 | + availableDevices << udi; | ||
403 | + _k_reloadBookmarks(); | ||
404 | } | ||
405 | |||
406 | void KFilePlacesModel::Private::_k_deviceRemoved(const QString &udi) |