Contents of /trunk/kdelibs/patches/kdelibs-4.9.4-udisks2-kfileplacesdevicecache.patch
Parent Directory | Revision Log
Revision 1990 -
(show 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 | 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) |