• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdelibs API Reference
  • KDE Home
  • Contact Us
 

Nepomuk-Core

  • sources
  • kde-4.12
  • kdelibs
  • nepomuk-core
  • common
removablemediacache.cpp
Go to the documentation of this file.
1 /*
2  This file is part of the Nepomuk KDE project.
3  Copyright (C) 2011 Sebastian Trueg <trueg@kde.org>
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License as published by the Free Software Foundation; either
8  version 2.1 of the License, or (at your option) version 3, or any
9  later version accepted by the membership of KDE e.V. (or its
10  successor approved by the membership of KDE e.V.), which shall
11  act as a proxy defined in Section 6 of version 3 of the license.
12 
13  This library is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public
19  License along with this library. If not, see <http://www.gnu.org/licenses/>.
20 */
21 
22 #include "removablemediacache.h"
23 
24 #include <Solid/DeviceNotifier>
25 #include <Solid/DeviceInterface>
26 #include <Solid/Block>
27 #include <Solid/Device>
28 #include <Solid/StorageDrive>
29 #include <Solid/StorageVolume>
30 #include <Solid/StorageAccess>
31 #include <Solid/NetworkShare>
32 #include <Solid/OpticalDisc>
33 #include <Solid/Predicate>
34 
35 #include <KDebug>
36 
37 #include <QtCore/QMutexLocker>
38 
39 
40 namespace {
41  bool isUsableVolume( const Solid::Device& dev ) {
42  if ( dev.is<Solid::StorageAccess>() ) {
43  if( dev.is<Solid::StorageVolume>() &&
44  dev.parent().is<Solid::StorageDrive>() &&
45  ( dev.parent().as<Solid::StorageDrive>()->isRemovable() ||
46  dev.parent().as<Solid::StorageDrive>()->isHotpluggable() ) ) {
47  const Solid::StorageVolume* volume = dev.as<Solid::StorageVolume>();
48  if ( !volume->isIgnored() && volume->usage() == Solid::StorageVolume::FileSystem )
49  return true;
50  }
51  else if(dev.is<Solid::NetworkShare>()) {
52  return !dev.as<Solid::NetworkShare>()->url().isEmpty();
53  }
54  }
55 
56  // fallback
57  return false;
58  }
59 
60  bool isUsableVolume( const QString& udi ) {
61  Solid::Device dev( udi );
62  return isUsableVolume( dev );
63  }
64 }
65 
66 
67 Nepomuk2::RemovableMediaCache::RemovableMediaCache(QObject *parent)
68  : QObject(parent)
69  , m_entryCacheMutex( QMutex::Recursive )
70 {
71  initCacheEntries();
72 
73  connect( Solid::DeviceNotifier::instance(), SIGNAL( deviceAdded( const QString& ) ),
74  this, SLOT( slotSolidDeviceAdded( const QString& ) ) );
75  connect( Solid::DeviceNotifier::instance(), SIGNAL( deviceRemoved( const QString& ) ),
76  this, SLOT( slotSolidDeviceRemoved( const QString& ) ) );
77 }
78 
79 
80 Nepomuk2::RemovableMediaCache::~RemovableMediaCache()
81 {
82 }
83 
84 
85 void Nepomuk2::RemovableMediaCache::initCacheEntries()
86 {
87  QList<Solid::Device> devices
88  = Solid::Device::listFromQuery(QLatin1String("StorageVolume.usage=='FileSystem'"))
89  + Solid::Device::listFromType(Solid::DeviceInterface::NetworkShare);
90  foreach( const Solid::Device& dev, devices ) {
91  if ( isUsableVolume( dev ) ) {
92  if(Entry* entry = createCacheEntry( dev )) {
93  const Solid::StorageAccess* storage = entry->device().as<Solid::StorageAccess>();
94  if ( storage && storage->isAccessible() )
95  slotAccessibilityChanged( true, dev.udi() );
96  }
97  }
98  }
99 }
100 
101 QList<const Nepomuk2::RemovableMediaCache::Entry *> Nepomuk2::RemovableMediaCache::allMedia() const
102 {
103  QMutexLocker lock(&m_entryCacheMutex);
104  QList<const Entry*> media;
105  for(QHash<QString, Entry>::const_iterator it = m_metadataCache.begin(); it != m_metadataCache.end(); ++it)
106  media.append(&(*it));
107  return media;
108 }
109 
110 Nepomuk2::RemovableMediaCache::Entry* Nepomuk2::RemovableMediaCache::createCacheEntry( const Solid::Device& dev )
111 {
112  QMutexLocker lock(&m_entryCacheMutex);
113 
114  Entry entry(dev);
115  if(!entry.url().isEmpty()) {
116  kDebug() << "Usable" << dev.udi();
117 
118  // we only add to this set and never remove. This is no problem as this is a small set
119  m_usedSchemas.insert(KUrl(entry.url()).scheme());
120 
121  const Solid::StorageAccess* storage = dev.as<Solid::StorageAccess>();
122  connect( storage, SIGNAL(accessibilityChanged(bool, QString)),
123  this, SLOT(slotAccessibilityChanged(bool, QString)) );
124  connect( storage, SIGNAL(teardownRequested(QString)),
125  this, SLOT(slotTeardownRequested(QString)) );
126 
127  QHash<QString, Entry>::iterator it = m_metadataCache.insert( dev.udi(), entry );
128 
129  emit deviceAdded(&it.value());
130 
131  return &it.value();
132  }
133  else {
134  kDebug() << "Cannot use device due to empty identifier:" << dev.udi();
135  return 0;
136  }
137 }
138 
139 
140 const Nepomuk2::RemovableMediaCache::Entry* Nepomuk2::RemovableMediaCache::findEntryByFilePath( const QString& path ) const
141 {
142  QMutexLocker lock(&m_entryCacheMutex);
143 
144  for( QHash<QString, Entry>::const_iterator it = m_metadataCache.begin();
145  it != m_metadataCache.end(); ++it ) {
146  const Entry& entry = *it;
147  const Solid::StorageAccess* storage = entry.device().as<Solid::StorageAccess>();
148  if ( storage &&
149  storage->isAccessible() &&
150  path.startsWith( storage->filePath() ) )
151  return &entry;
152  }
153 
154  return 0;
155 }
156 
157 
158 const Nepomuk2::RemovableMediaCache::Entry* Nepomuk2::RemovableMediaCache::findEntryByUrl(const KUrl &url) const
159 {
160  QMutexLocker lock(&m_entryCacheMutex);
161 
162  const QString encodedUrl = QString::fromAscii(url.toEncoded());
163  for( QHash<QString, Entry>::const_iterator it = m_metadataCache.constBegin();
164  it != m_metadataCache.constEnd(); ++it ) {
165  const Entry& entry = *it;
166  if(encodedUrl.startsWith(entry.url())) {
167  return &entry;
168  }
169  }
170 
171  return 0;
172 }
173 
174 
175 QList<const Nepomuk2::RemovableMediaCache::Entry*> Nepomuk2::RemovableMediaCache::findEntriesByMountPath(const QString &path) const
176 {
177  QMutexLocker lock(&m_entryCacheMutex);
178 
179  QList<const Entry*> entries;
180  for( QHash<QString, Entry>::const_iterator it = m_metadataCache.constBegin();
181  it != m_metadataCache.constEnd(); ++it ) {
182  const Entry& entry = *it;
183  if(entry.isMounted() &&
184  entry.mountPath().startsWith(path)) {
185  entries.append(&entry);
186  }
187  }
188  return entries;
189 }
190 
191 
192 bool Nepomuk2::RemovableMediaCache::hasRemovableSchema(const KUrl &url) const
193 {
194  return m_usedSchemas.contains(url.scheme());
195 }
196 
197 
198 bool Nepomuk2::RemovableMediaCache::isEmpty() const
199 {
200  QMutexLocker lock(&m_entryCacheMutex);
201  return m_metadataCache.isEmpty();
202 }
203 
204 
205 void Nepomuk2::RemovableMediaCache::slotSolidDeviceAdded( const QString& udi )
206 {
207  kDebug() << udi;
208 
209  if ( isUsableVolume( udi ) ) {
210  createCacheEntry( Solid::Device( udi ) );
211  }
212 }
213 
214 
215 void Nepomuk2::RemovableMediaCache::slotSolidDeviceRemoved( const QString& udi )
216 {
217  QMutexLocker lock(&m_entryCacheMutex);
218  QHash< QString, Entry >::iterator it = m_metadataCache.find( udi );
219  if( it != m_metadataCache.end() ) {
220  kDebug() << "Found removable storage volume for Nepomuk undocking:" << udi;
221  emit deviceRemoved( &it.value() );
222  m_metadataCache.erase( it );
223  }
224 }
225 
226 
227 void Nepomuk2::RemovableMediaCache::slotAccessibilityChanged( bool accessible, const QString& udi )
228 {
229  kDebug() << accessible << udi;
230 
231  //
232  // cache new mount path
233  //
234  QMutexLocker lock(&m_entryCacheMutex);
235  Entry* entry = &m_metadataCache[udi];
236  Q_ASSERT( entry != 0 );
237 
238  if ( accessible ) {
239  kDebug() << udi << "accessible at" << entry->device().as<Solid::StorageAccess>()->filePath()
240  << "with identifier" << entry->url();
241  emit deviceMounted(entry);
242  }
243 }
244 
245 void Nepomuk2::RemovableMediaCache::slotTeardownRequested(const QString& udi)
246 {
247  QMutexLocker lock(&m_entryCacheMutex);
248  Entry* entry = &m_metadataCache[udi];
249  Q_ASSERT( entry != 0 );
250 
251  emit deviceTeardownRequested(entry);
252 }
253 
254 
255 
256 Nepomuk2::RemovableMediaCache::Entry::Entry()
257 {
258 }
259 
260 
261 Nepomuk2::RemovableMediaCache::Entry::Entry(const Solid::Device& device)
262  : m_device(device)
263 {
264  if(device.is<Solid::StorageVolume>()) {
265  const Solid::StorageVolume* volume = m_device.as<Solid::StorageVolume>();
266  if(device.is<Solid::OpticalDisc>() &&
267  !volume->label().isEmpty()) {
268  // we use the label as is - it is not even close to unique but
269  // so far we have nothing better
270 
271  // QUrl does convert the host to lower case
272  QString label = volume->label().toLower();
273  // QUrl does not allow spaces in the host
274  label.replace(' ', '_');
275 
276  m_urlPrefix = QLatin1String("optical://") + label;
277  }
278  else if(!volume->uuid().isEmpty()) {
279  // we always use lower-case uuids
280  m_urlPrefix = QLatin1String("filex://") + volume->uuid().toLower();
281  }
282  }
283  else if(device.is<Solid::NetworkShare>()) {
284  m_urlPrefix = device.as<Solid::NetworkShare>()->url().toString();
285  }
286 }
287 
288 QString Nepomuk2::RemovableMediaCache::Entry::constructRelativeUrlString(const QString &path) const
289 {
290  if(const Solid::StorageAccess* sa = m_device.as<Solid::StorageAccess>()) {
291  if(sa->isAccessible()) {
292  const QString relativePath = path.mid( sa->filePath().count() );
293  return m_urlPrefix + relativePath;
294  }
295  }
296 
297  // fallback
298  return QString();
299 }
300 
301 KUrl Nepomuk2::RemovableMediaCache::Entry::constructRelativeUrl( const QString& path ) const
302 {
303  return KUrl(constructRelativeUrlString(path));
304 }
305 
306 
307 KUrl Nepomuk2::RemovableMediaCache::Entry::constructLocalFileUrl( const KUrl& filexUrl ) const
308 {
309  if(const Solid::StorageAccess* sa = m_device.as<Solid::StorageAccess>()) {
310  if(sa->isAccessible()) {
311  // the base of the path: the mount path
312  KUrl fileUrl( sa->filePath() );
313  fileUrl.addPath(QUrl::fromEncoded(filexUrl.toEncoded().mid(m_urlPrefix.count())).toString());
314  return fileUrl;
315  }
316  }
317 
318  // fallback
319  return QString();
320 }
321 
322 QString Nepomuk2::RemovableMediaCache::Entry::mountPath() const
323 {
324  if(const Solid::StorageAccess* sa = m_device.as<Solid::StorageAccess>()) {
325  return sa->filePath();
326  }
327  else {
328  return QString();
329  }
330 }
331 
332 bool Nepomuk2::RemovableMediaCache::Entry::isMounted() const
333 {
334  if(const Solid::StorageAccess* sa = m_device.as<Solid::StorageAccess>()) {
335  return sa->isAccessible();
336  }
337  else {
338  return false;
339  }
340 }
341 
342 #include "removablemediacache.moc"
Nepomuk2::RemovableMediaCache::Entry::isMounted
bool isMounted() const
Definition: removablemediacache.cpp:332
Nepomuk2::RemovableMediaCache::deviceAdded
void deviceAdded(const Nepomuk2::RemovableMediaCache::Entry *entry)
Nepomuk2::RemovableMediaCache::Entry::constructRelativeUrlString
QString constructRelativeUrlString(const QString &path) const
Does the same as constructRelativeUrl except that no char conversion will ever take place...
Definition: removablemediacache.cpp:288
Nepomuk2::RemovableMediaCache::deviceRemoved
void deviceRemoved(const Nepomuk2::RemovableMediaCache::Entry *entry)
Nepomuk2::RemovableMediaCache::Entry::mountPath
QString mountPath() const
Definition: removablemediacache.cpp:322
Nepomuk2::RemovableMediaCache::isEmpty
bool isEmpty() const
Returns true if they are no devices in the RemoveableMediaCache.
Definition: removablemediacache.cpp:198
Nepomuk2::RemovableMediaCache::allMedia
QList< const Entry * > allMedia() const
Definition: removablemediacache.cpp:101
QHash
QObject
Nepomuk2::RemovableMediaCache::Entry::device
Solid::Device device() const
Definition: removablemediacache.h:66
Nepomuk2::RemovableMediaCache::findEntryByFilePath
const Entry * findEntryByFilePath(const QString &path) const
Definition: removablemediacache.cpp:140
removablemediacache.h
Nepomuk2::RemovableMediaCache::Entry
Definition: removablemediacache.h:53
Nepomuk2::RemovableMediaCache::findEntryByUrl
const Entry * findEntryByUrl(const KUrl &url) const
Definition: removablemediacache.cpp:158
Nepomuk2::RemovableMediaCache::~RemovableMediaCache
~RemovableMediaCache()
Definition: removablemediacache.cpp:80
Nepomuk2::RemovableMediaCache::RemovableMediaCache
RemovableMediaCache(QObject *parent=0)
Definition: removablemediacache.cpp:67
Nepomuk2::RemovableMediaCache::Entry::Entry
Entry()
Definition: removablemediacache.cpp:256
Nepomuk2::RemovableMediaCache::Entry::constructRelativeUrl
KUrl constructRelativeUrl(const QString &path) const
Definition: removablemediacache.cpp:301
Nepomuk2::RemovableMediaCache::Entry::constructLocalFileUrl
KUrl constructLocalFileUrl(const KUrl &filexUrl) const
Definition: removablemediacache.cpp:307
Nepomuk2::RemovableMediaCache::hasRemovableSchema
bool hasRemovableSchema(const KUrl &url) const
Returns true if the URL might be pointing to a file on a removable device as handled by this class...
Definition: removablemediacache.cpp:192
Nepomuk2::RemovableMediaCache::Entry::url
QString url() const
Definition: removablemediacache.h:67
Nepomuk2::RemovableMediaCache::findEntriesByMountPath
QList< const Entry * > findEntriesByMountPath(const QString &path) const
Searches for entries which are mounted at a path which starts with the given one. ...
Definition: removablemediacache.cpp:175
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:48:08 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

Nepomuk-Core

Skip menu "Nepomuk-Core"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal