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

KFile

  • kfile
kfileplacesmodel.cpp
Go to the documentation of this file.
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 #include "kfileplacessharedbookmarks_p.h"
23 
24 #ifdef Q_OS_WIN
25 #include "Windows.h"
26 #include "WinBase.h"
27 #include <QtCore/QDir>
28 #endif
29 
30 #include <QtCore/QMimeData>
31 #include <QtCore/QTimer>
32 #include <QtCore/QFile>
33 #include <QtGui/QColor>
34 #include <QtGui/QAction>
35 
36 #include <kfileitem.h>
37 #include <kglobal.h>
38 #include <klocale.h>
39 #include <kuser.h>
40 #include <kstandarddirs.h>
41 #include <kcomponentdata.h>
42 #include <kicon.h>
43 #include <kmimetype.h>
44 #include <kdebug.h>
45 
46 #include <kbookmarkmanager.h>
47 #include <kbookmark.h>
48 
49 #include <kio/netaccess.h>
50 
51 #include <solid/devicenotifier.h>
52 #include <solid/storageaccess.h>
53 #include <solid/storagedrive.h>
54 #include <solid/storagevolume.h>
55 #include <solid/opticaldrive.h>
56 #include <solid/opticaldisc.h>
57 #include <solid/predicate.h>
58 
59 class KFilePlacesModel::Private
60 {
61 public:
62  Private(KFilePlacesModel *self) : q(self), bookmarkManager(0), sharedBookmarks(0) {}
63  ~Private()
64  {
65  delete sharedBookmarks;
66  qDeleteAll(items);
67  }
68 
69  KFilePlacesModel *q;
70 
71  QList<KFilePlacesItem*> items;
72  QSet<QString> availableDevices;
73  QMap<QObject*, QPersistentModelIndex> setupInProgress;
74 
75  Solid::Predicate predicate;
76  KBookmarkManager *bookmarkManager;
77  KFilePlacesSharedBookmarks * sharedBookmarks;
78 
79  void reloadAndSignal();
80  QList<KFilePlacesItem *> loadBookmarkList();
81 
82  void _k_initDeviceList();
83  void _k_deviceAdded(const QString &udi);
84  void _k_deviceRemoved(const QString &udi);
85  void _k_itemChanged(const QString &udi);
86  void _k_reloadBookmarks();
87  void _k_storageSetupDone(Solid::ErrorType error, QVariant errorData);
88  void _k_storageTeardownDone(Solid::ErrorType error, QVariant errorData);
89 };
90 
91 KFilePlacesModel::KFilePlacesModel(QObject *parent)
92  : QAbstractItemModel(parent), d(new Private(this))
93 {
94  const QString file = KStandardDirs::locateLocal("data", "kfileplaces/bookmarks.xml");
95  d->bookmarkManager = KBookmarkManager::managerForFile(file, "kfilePlaces");
96 
97  // Let's put some places in there if it's empty. We have a corner case here:
98  // Given you have bookmarked some folders (which have been saved on
99  // ~/.local/share/user-places.xbel (according to freedesktop bookmarks spec), and
100  // deleted the home directory ~/.kde, the call managerForFile() will return the
101  // bookmark manager for the fallback "kfilePlaces", making root.first().isNull() being
102  // false (you have your own items bookmarked), resulting on only being added your own
103  // bookmarks, and not the default ones too. So, we also check if kfileplaces/bookmarks.xml
104  // file exists, and if it doesn't, we also add the default places. (ereslibre)
105  KBookmarkGroup root = d->bookmarkManager->root();
106  if (root.first().isNull() || !QFile::exists(file)) {
107 
108  // NOTE: The context for these I18N_NOOP2 calls has to be "KFile System Bookmarks".
109  // The real i18nc call is made later, with this context, so the two must match.
110  //
111  // createSystemBookmark actually does nothing with its third argument,
112  // but we have to give it something so the I18N_NOOP2 calls stay here for now.
113  //
114  // (coles, 13th May 2009)
115 
116  KFilePlacesItem::createSystemBookmark(d->bookmarkManager,
117  "Home", I18N_NOOP2("KFile System Bookmarks", "Home"),
118  KUrl(KUser().homeDir()), "user-home");
119  KFilePlacesItem::createSystemBookmark(d->bookmarkManager,
120  "Network", I18N_NOOP2("KFile System Bookmarks", "Network"),
121  KUrl("remote:/"), "network-workgroup");
122 #ifdef Q_OS_WIN
123  // adding drives
124  foreach ( const QFileInfo& info, QDir::drives() ) {
125 #ifndef _WIN32_WCE
126  uint type = DRIVE_UNKNOWN;
127 #endif
128  QString driveIcon = "drive-harddisk";
129 #ifndef _WIN32_WCE
130  QT_WA({ type = GetDriveTypeW((wchar_t *)info.absoluteFilePath().utf16()); },
131  { type = GetDriveTypeA(info.absoluteFilePath().toLocal8Bit()); });
132  // qDebug() << "drive " << info.absoluteFilePath() << " type: " << type;
133  switch (type) {
134  case DRIVE_REMOVABLE:
135  driveIcon = "drive-removable-media";
136  break;
137  case DRIVE_FIXED:
138  driveIcon = "drive-harddisk";
139  break;
140  case DRIVE_REMOTE:
141  driveIcon = "network-server";
142  break;
143  case DRIVE_CDROM:
144  driveIcon = "drive-optical";
145  break;
146  case DRIVE_RAMDISK:
147  case DRIVE_UNKNOWN:
148  case DRIVE_NO_ROOT_DIR:
149  default:
150  driveIcon = "drive-harddisk";
151  }
152 #endif
153  KFilePlacesItem::createSystemBookmark(d->bookmarkManager,
154  info.absoluteFilePath(), info.absoluteFilePath(),
155  KUrl(info.absoluteFilePath()), driveIcon);
156  }
157 #else
158  KFilePlacesItem::createSystemBookmark(d->bookmarkManager,
159  "Root", I18N_NOOP2("KFile System Bookmarks", "Root"),
160  KUrl("/"), "folder-red");
161 #endif
162  KFilePlacesItem::createSystemBookmark(d->bookmarkManager,
163  "Trash", I18N_NOOP2("KFile System Bookmarks", "Trash"),
164  KUrl("trash:/"), "user-trash");
165 
166  // Force bookmarks to be saved. If on open/save dialog and the bookmarks are not saved, QFile::exists
167  // will always return false, which opening/closing all the time the open/save dialog would case the
168  // bookmarks to be added once each time, having lots of times each bookmark. This forces the defaults
169  // to be saved on the bookmarks.xml file. Of course, the complete list of bookmarks (those that come from
170  // user-places.xbel will be filled later). (ereslibre)
171  d->bookmarkManager->saveAs(file);
172  }
173 
174  // create after, so if we have own places, they are added afterwards, in case of equal priorities
175  d->sharedBookmarks = new KFilePlacesSharedBookmarks(d->bookmarkManager);
176 
177  d->predicate = Solid::Predicate::fromString(
178  "[[[[ StorageVolume.ignored == false AND [ StorageVolume.usage == 'FileSystem' OR StorageVolume.usage == 'Encrypted' ]]"
179  " OR "
180  "[ IS StorageAccess AND StorageDrive.driveType == 'Floppy' ]]"
181  " OR "
182  "OpticalDisc.availableContent & 'Audio' ]"
183  " OR "
184  "StorageAccess.ignored == false ]");
185  Q_ASSERT(d->predicate.isValid());
186 
187  connect(d->bookmarkManager, SIGNAL(changed(QString,QString)),
188  this, SLOT(_k_reloadBookmarks()));
189  connect(d->bookmarkManager, SIGNAL(bookmarksChanged(QString)),
190  this, SLOT(_k_reloadBookmarks()));
191 
192  d->_k_reloadBookmarks();
193  QTimer::singleShot(0, this, SLOT(_k_initDeviceList()));
194 }
195 
196 KFilePlacesModel::~KFilePlacesModel()
197 {
198  delete d;
199 }
200 
201 KUrl KFilePlacesModel::url(const QModelIndex &index) const
202 {
203  return KUrl(data(index, UrlRole).toUrl());
204 }
205 
206 bool KFilePlacesModel::setupNeeded(const QModelIndex &index) const
207 {
208  return data(index, SetupNeededRole).toBool();
209 }
210 
211 KIcon KFilePlacesModel::icon(const QModelIndex &index) const
212 {
213  return KIcon(data(index, Qt::DecorationRole).value<QIcon>());
214 }
215 
216 QString KFilePlacesModel::text(const QModelIndex &index) const
217 {
218  return data(index, Qt::DisplayRole).toString();
219 }
220 
221 bool KFilePlacesModel::isHidden(const QModelIndex &index) const
222 {
223  return data(index, HiddenRole).toBool();
224 }
225 
226 bool KFilePlacesModel::isDevice(const QModelIndex &index) const
227 {
228  if (!index.isValid())
229  return false;
230 
231  KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer());
232 
233  return item->isDevice();
234 }
235 
236 Solid::Device KFilePlacesModel::deviceForIndex(const QModelIndex &index) const
237 {
238  if (!index.isValid())
239  return Solid::Device();
240 
241  KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer());
242 
243  if (item->isDevice()) {
244  return item->device();
245  } else {
246  return Solid::Device();
247  }
248 }
249 
250 KBookmark KFilePlacesModel::bookmarkForIndex(const QModelIndex &index) const
251 {
252  if (!index.isValid())
253  return KBookmark();
254 
255  KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer());
256 
257  if (!item->isDevice()) {
258  return item->bookmark();
259  } else {
260  return KBookmark();
261  }
262 }
263 
264 QVariant KFilePlacesModel::data(const QModelIndex &index, int role) const
265 {
266  if (!index.isValid())
267  return QVariant();
268 
269  KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer());
270  return item->data(role);
271 }
272 
273 QModelIndex KFilePlacesModel::index(int row, int column, const QModelIndex &parent) const
274 {
275  if (row<0 || column!=0 || row>=d->items.size())
276  return QModelIndex();
277 
278  if (parent.isValid())
279  return QModelIndex();
280 
281  return createIndex(row, column, d->items.at(row));
282 }
283 
284 QModelIndex KFilePlacesModel::parent(const QModelIndex &child) const
285 {
286  Q_UNUSED(child);
287  return QModelIndex();
288 }
289 
290 int KFilePlacesModel::rowCount(const QModelIndex &parent) const
291 {
292  if (parent.isValid())
293  return 0;
294  else
295  return d->items.size();
296 }
297 
298 int KFilePlacesModel::columnCount(const QModelIndex &parent) const
299 {
300  Q_UNUSED(parent)
301  // We only know 1 piece of information for a particular entry
302  return 1;
303 }
304 
305 QModelIndex KFilePlacesModel::closestItem(const KUrl &url) const
306 {
307  int foundRow = -1;
308  int maxLength = 0;
309 
310  // Search the item which is equal to the URL or at least is a parent URL.
311  // If there are more than one possible item URL candidates, choose the item
312  // which covers the bigger range of the URL.
313  for (int row = 0; row<d->items.size(); ++row) {
314  KFilePlacesItem *item = d->items[row];
315  KUrl itemUrl = KUrl(item->data(UrlRole).toUrl());
316 
317  if (itemUrl.isParentOf(url)) {
318  const int length = itemUrl.prettyUrl().length();
319  if (length > maxLength) {
320  foundRow = row;
321  maxLength = length;
322  }
323  }
324  }
325 
326  if (foundRow==-1)
327  return QModelIndex();
328  else
329  return createIndex(foundRow, 0, d->items[foundRow]);
330 }
331 
332 void KFilePlacesModel::Private::_k_initDeviceList()
333 {
334  Solid::DeviceNotifier *notifier = Solid::DeviceNotifier::instance();
335 
336  connect(notifier, SIGNAL(deviceAdded(QString)),
337  q, SLOT(_k_deviceAdded(QString)));
338  connect(notifier, SIGNAL(deviceRemoved(QString)),
339  q, SLOT(_k_deviceRemoved(QString)));
340 
341  const QList<Solid::Device> &deviceList = Solid::Device::listFromQuery(predicate);
342 
343  foreach(const Solid::Device &device, deviceList) {
344  availableDevices << device.udi();
345  }
346 
347  _k_reloadBookmarks();
348 }
349 
350 void KFilePlacesModel::Private::_k_deviceAdded(const QString &udi)
351 {
352  Solid::Device d(udi);
353 
354  if (predicate.matches(d)) {
355  availableDevices << udi;
356  _k_reloadBookmarks();
357  }
358 }
359 
360 void KFilePlacesModel::Private::_k_deviceRemoved(const QString &udi)
361 {
362  if (availableDevices.contains(udi)) {
363  availableDevices.remove(udi);
364  _k_reloadBookmarks();
365  }
366 }
367 
368 void KFilePlacesModel::Private::_k_itemChanged(const QString &id)
369 {
370  for (int row = 0; row<items.size(); ++row) {
371  if (items.at(row)->id()==id) {
372  QModelIndex index = q->index(row, 0);
373  emit q->dataChanged(index, index);
374  }
375  }
376 }
377 
378 void KFilePlacesModel::Private::_k_reloadBookmarks()
379 {
380  QList<KFilePlacesItem*> currentItems = loadBookmarkList();
381 
382  QList<KFilePlacesItem*>::Iterator it_i = items.begin();
383  QList<KFilePlacesItem*>::Iterator it_c = currentItems.begin();
384 
385  QList<KFilePlacesItem*>::Iterator end_i = items.end();
386  QList<KFilePlacesItem*>::Iterator end_c = currentItems.end();
387 
388  while (it_i!=end_i || it_c!=end_c) {
389  if (it_i==end_i && it_c!=end_c) {
390  int row = items.count();
391 
392  q->beginInsertRows(QModelIndex(), row, row);
393  it_i = items.insert(it_i, *it_c);
394  ++it_i;
395  it_c = currentItems.erase(it_c);
396 
397  end_i = items.end();
398  end_c = currentItems.end();
399  q->endInsertRows();
400 
401  } else if (it_i!=end_i && it_c==end_c) {
402  int row = items.indexOf(*it_i);
403 
404  q->beginRemoveRows(QModelIndex(), row, row);
405  delete *it_i;
406  it_i = items.erase(it_i);
407 
408  end_i = items.end();
409  end_c = currentItems.end();
410  q->endRemoveRows();
411 
412  } else if ((*it_i)->id()==(*it_c)->id()) {
413  bool shouldEmit = !((*it_i)->bookmark()==(*it_c)->bookmark());
414  (*it_i)->setBookmark((*it_c)->bookmark());
415  if (shouldEmit) {
416  int row = items.indexOf(*it_i);
417  QModelIndex idx = q->index(row, 0);
418  emit q->dataChanged(idx, idx);
419  }
420  ++it_i;
421  ++it_c;
422  } else if ((*it_i)->id()!=(*it_c)->id()) {
423  int row = items.indexOf(*it_i);
424 
425  if (it_i+1!=end_i && (*(it_i+1))->id()==(*it_c)->id()) { // if the next one matches, it's a remove
426  q->beginRemoveRows(QModelIndex(), row, row);
427  delete *it_i;
428  it_i = items.erase(it_i);
429 
430  end_i = items.end();
431  end_c = currentItems.end();
432  q->endRemoveRows();
433  } else {
434  q->beginInsertRows(QModelIndex(), row, row);
435  it_i = items.insert(it_i, *it_c);
436  ++it_i;
437  it_c = currentItems.erase(it_c);
438 
439  end_i = items.end();
440  end_c = currentItems.end();
441  q->endInsertRows();
442  }
443  }
444  }
445 
446  qDeleteAll(currentItems);
447  currentItems.clear();
448 }
449 
450 QList<KFilePlacesItem *> KFilePlacesModel::Private::loadBookmarkList()
451 {
452  QList<KFilePlacesItem*> items;
453 
454  KBookmarkGroup root = bookmarkManager->root();
455  KBookmark bookmark = root.first();
456  QSet<QString> devices = availableDevices;
457 
458  while (!bookmark.isNull()) {
459  QString udi = bookmark.metaDataItem("UDI");
460  QString appName = bookmark.metaDataItem("OnlyInApp");
461  bool deviceAvailable = devices.remove(udi);
462 
463  bool allowedHere = appName.isEmpty() || (appName==KGlobal::mainComponent().componentName());
464 
465  if ((udi.isEmpty() && allowedHere) || deviceAvailable) {
466  KFilePlacesItem *item;
467  if (deviceAvailable) {
468  item = new KFilePlacesItem(bookmarkManager, bookmark.address(), udi);
469  // TODO: Update bookmark internal element
470  } else {
471  item = new KFilePlacesItem(bookmarkManager, bookmark.address());
472  }
473  connect(item, SIGNAL(itemChanged(QString)),
474  q, SLOT(_k_itemChanged(QString)));
475  items << item;
476  }
477 
478  bookmark = root.next(bookmark);
479  }
480 
481  // Add bookmarks for the remaining devices, they were previously unknown
482  foreach (const QString &udi, devices) {
483  bookmark = KFilePlacesItem::createDeviceBookmark(bookmarkManager, udi);
484  if (!bookmark.isNull()) {
485  KFilePlacesItem *item = new KFilePlacesItem(bookmarkManager,
486  bookmark.address(), udi);
487  connect(item, SIGNAL(itemChanged(QString)),
488  q, SLOT(_k_itemChanged(QString)));
489  // TODO: Update bookmark internal element
490  items << item;
491  }
492  }
493 
494  return items;
495 }
496 
497 void KFilePlacesModel::Private::reloadAndSignal()
498 {
499  bookmarkManager->emitChanged(bookmarkManager->root()); // ... we'll get relisted anyway
500 }
501 
502 Qt::DropActions KFilePlacesModel::supportedDropActions() const
503 {
504  return Qt::ActionMask;
505 }
506 
507 Qt::ItemFlags KFilePlacesModel::flags(const QModelIndex &index) const
508 {
509  Qt::ItemFlags res = Qt::ItemIsSelectable|Qt::ItemIsEnabled;
510 
511  if (index.isValid())
512  res|= Qt::ItemIsDragEnabled;
513 
514  if (!index.isValid())
515  res|= Qt::ItemIsDropEnabled;
516 
517  return res;
518 }
519 
520 static QString _k_internalMimetype(const KFilePlacesModel * const self)
521 {
522  return QString("application/x-kfileplacesmodel-")+QString::number((qptrdiff)self);
523 }
524 
525 QStringList KFilePlacesModel::mimeTypes() const
526 {
527  QStringList types;
528 
529  types << _k_internalMimetype(this) << "text/uri-list";
530 
531  return types;
532 }
533 
534 QMimeData *KFilePlacesModel::mimeData(const QModelIndexList &indexes) const
535 {
536  KUrl::List urls;
537  QByteArray itemData;
538 
539  QDataStream stream(&itemData, QIODevice::WriteOnly);
540 
541  foreach (const QModelIndex &index, indexes) {
542  KUrl itemUrl = url(index);
543  if (itemUrl.isValid())
544  urls << itemUrl;
545  stream << index.row();
546  }
547 
548  QMimeData *mimeData = new QMimeData();
549 
550  if (!urls.isEmpty())
551  urls.populateMimeData(mimeData);
552 
553  mimeData->setData(_k_internalMimetype(this), itemData);
554 
555  return mimeData;
556 }
557 
558 bool KFilePlacesModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
559  int row, int column, const QModelIndex &parent)
560 {
561  if (action == Qt::IgnoreAction)
562  return true;
563 
564  if (column > 0)
565  return false;
566 
567  if (row==-1 && parent.isValid()) {
568  return false; // Don't allow to move an item onto another one,
569  // too easy for the user to mess something up
570  // If we really really want to allow copying files this way,
571  // let's do it in the views to get the good old drop menu
572  }
573 
574 
575  KBookmark afterBookmark;
576 
577  if (row==-1) {
578  // The dropped item is moved or added to the last position
579 
580  KFilePlacesItem *lastItem = d->items.last();
581  afterBookmark = lastItem->bookmark();
582 
583  } else {
584  // The dropped item is moved or added before position 'row', ie after position 'row-1'
585 
586  if (row>0) {
587  KFilePlacesItem *afterItem = d->items[row-1];
588  afterBookmark = afterItem->bookmark();
589  }
590  }
591 
592  if (data->hasFormat(_k_internalMimetype(this))) {
593  // The operation is an internal move
594  QByteArray itemData = data->data(_k_internalMimetype(this));
595  QDataStream stream(&itemData, QIODevice::ReadOnly);
596  int itemRow;
597 
598  stream >> itemRow;
599 
600  KFilePlacesItem *item = d->items[itemRow];
601  KBookmark bookmark = item->bookmark();
602 
603  d->bookmarkManager->root().moveBookmark(bookmark, afterBookmark);
604 
605  } else if (data->hasFormat("text/uri-list")) {
606  // The operation is an add
607  KUrl::List urls = KUrl::List::fromMimeData(data);
608 
609  KBookmarkGroup group = d->bookmarkManager->root();
610 
611  foreach (const KUrl &url, urls) {
612  // TODO: use KIO::stat in order to get the UDS_DISPLAY_NAME too
613  KMimeType::Ptr mimetype = KMimeType::mimeType(KIO::NetAccess::mimetype(url, 0));
614 
615  if (!mimetype) {
616  kWarning() << "URL not added to Places as mimetype could not be determined!";
617  continue;
618  }
619 
620  if (!mimetype->is("inode/directory")) {
621  // Only directories are allowed
622  continue;
623  }
624 
625  KBookmark bookmark = KFilePlacesItem::createBookmark(d->bookmarkManager,
626  url.fileName(), url,
627  mimetype->iconName(url));
628  group.moveBookmark(bookmark, afterBookmark);
629  afterBookmark = bookmark;
630  }
631 
632  } else {
633  // Oops, shouldn't happen thanks to mimeTypes()
634  kWarning() << ": received wrong mimedata, " << data->formats();
635  return false;
636  }
637 
638  d->reloadAndSignal();
639 
640  return true;
641 }
642 
643 void KFilePlacesModel::addPlace(const QString &text, const KUrl &url,
644  const QString &iconName, const QString &appName)
645 {
646  addPlace(text, url, iconName, appName, QModelIndex());
647 }
648 
649 void KFilePlacesModel::addPlace(const QString &text, const KUrl &url,
650  const QString &iconName, const QString &appName,
651  const QModelIndex &after)
652 {
653  KBookmark bookmark = KFilePlacesItem::createBookmark(d->bookmarkManager,
654  text, url, iconName);
655 
656  if (!appName.isEmpty()) {
657  bookmark.setMetaDataItem("OnlyInApp", appName);
658  }
659 
660  if (after.isValid()) {
661  KFilePlacesItem *item = static_cast<KFilePlacesItem*>(after.internalPointer());
662  d->bookmarkManager->root().moveBookmark(bookmark, item->bookmark());
663  }
664 
665  d->reloadAndSignal();
666 }
667 
668 void KFilePlacesModel::editPlace(const QModelIndex &index, const QString &text, const KUrl &url,
669  const QString &iconName, const QString &appName)
670 {
671  if (!index.isValid()) return;
672 
673  KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer());
674 
675  if (item->isDevice()) return;
676 
677  KBookmark bookmark = item->bookmark();
678 
679  if (bookmark.isNull()) return;
680 
681  bookmark.setFullText(text);
682  bookmark.setUrl(url);
683  bookmark.setIcon(iconName);
684  bookmark.setMetaDataItem("OnlyInApp", appName);
685 
686  d->reloadAndSignal();
687  emit dataChanged(index, index);
688 }
689 
690 void KFilePlacesModel::removePlace(const QModelIndex &index) const
691 {
692  if (!index.isValid()) return;
693 
694  KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer());
695 
696  if (item->isDevice()) return;
697 
698  KBookmark bookmark = item->bookmark();
699 
700  if (bookmark.isNull()) return;
701 
702  d->bookmarkManager->root().deleteBookmark(bookmark);
703  d->reloadAndSignal();
704 }
705 
706 void KFilePlacesModel::setPlaceHidden(const QModelIndex &index, bool hidden)
707 {
708  if (!index.isValid()) return;
709 
710  KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer());
711 
712  KBookmark bookmark = item->bookmark();
713 
714  if (bookmark.isNull()) return;
715 
716  bookmark.setMetaDataItem("IsHidden", (hidden ? "true" : "false"));
717 
718  d->reloadAndSignal();
719  emit dataChanged(index, index);
720 }
721 
722 int KFilePlacesModel::hiddenCount() const
723 {
724  int rows = rowCount();
725  int hidden = 0;
726 
727  for (int i=0; i<rows; ++i) {
728  if (isHidden(index(i, 0))) {
729  hidden++;
730  }
731  }
732 
733  return hidden;
734 }
735 
736 QAction *KFilePlacesModel::teardownActionForIndex(const QModelIndex &index) const
737 {
738  Solid::Device device = deviceForIndex(index);
739 
740  if (device.is<Solid::StorageAccess>() && device.as<Solid::StorageAccess>()->isAccessible()) {
741 
742  Solid::StorageDrive *drive = device.as<Solid::StorageDrive>();
743 
744  if (drive==0) {
745  drive = device.parent().as<Solid::StorageDrive>();
746  }
747 
748  bool hotpluggable = false;
749  bool removable = false;
750 
751  if (drive!=0) {
752  hotpluggable = drive->isHotpluggable();
753  removable = drive->isRemovable();
754  }
755 
756  QString iconName;
757  QString text;
758  QString label = data(index, Qt::DisplayRole).toString().replace('&',"&&");
759 
760  if (device.is<Solid::OpticalDisc>()) {
761  text = i18n("&Release '%1'", label);
762  } else if (removable || hotpluggable) {
763  text = i18n("&Safely Remove '%1'", label);
764  iconName = "media-eject";
765  } else {
766  text = i18n("&Unmount '%1'", label);
767  iconName = "media-eject";
768  }
769 
770  if (!iconName.isEmpty()) {
771  return new QAction(KIcon(iconName), text, 0);
772  } else {
773  return new QAction(text, 0);
774  }
775  }
776 
777  return 0;
778 }
779 
780 QAction *KFilePlacesModel::ejectActionForIndex(const QModelIndex &index) const
781 {
782  Solid::Device device = deviceForIndex(index);
783 
784  if (device.is<Solid::OpticalDisc>()) {
785 
786  QString label = data(index, Qt::DisplayRole).toString().replace('&',"&&");
787  QString text = i18n("&Eject '%1'", label);
788 
789  return new QAction(KIcon("media-eject"), text, 0);
790  }
791 
792  return 0;
793 }
794 
795 void KFilePlacesModel::requestTeardown(const QModelIndex &index)
796 {
797  Solid::Device device = deviceForIndex(index);
798  Solid::StorageAccess *access = device.as<Solid::StorageAccess>();
799 
800  if (access!=0) {
801  connect(access, SIGNAL(teardownDone(Solid::ErrorType,QVariant,QString)),
802  this, SLOT(_k_storageTeardownDone(Solid::ErrorType,QVariant)));
803 
804  access->teardown();
805  }
806 }
807 
808 void KFilePlacesModel::requestEject(const QModelIndex &index)
809 {
810  Solid::Device device = deviceForIndex(index);
811 
812  Solid::OpticalDrive *drive = device.parent().as<Solid::OpticalDrive>();
813 
814  if (drive!=0) {
815  connect(drive, SIGNAL(ejectDone(Solid::ErrorType,QVariant,QString)),
816  this, SLOT(_k_storageTeardownDone(Solid::ErrorType,QVariant)));
817 
818  drive->eject();
819  } else {
820  QString label = data(index, Qt::DisplayRole).toString().replace('&',"&&");
821  QString message = i18n("The device '%1' is not a disk and cannot be ejected.", label);
822  emit errorMessage(message);
823  }
824 }
825 
826 void KFilePlacesModel::requestSetup(const QModelIndex &index)
827 {
828  Solid::Device device = deviceForIndex(index);
829 
830  if (device.is<Solid::StorageAccess>()
831  && !d->setupInProgress.contains(device.as<Solid::StorageAccess>())
832  && !device.as<Solid::StorageAccess>()->isAccessible()) {
833 
834  Solid::StorageAccess *access = device.as<Solid::StorageAccess>();
835 
836  d->setupInProgress[access] = index;
837 
838  connect(access, SIGNAL(setupDone(Solid::ErrorType,QVariant,QString)),
839  this, SLOT(_k_storageSetupDone(Solid::ErrorType,QVariant)));
840 
841  access->setup();
842  }
843 }
844 
845 void KFilePlacesModel::Private::_k_storageSetupDone(Solid::ErrorType error, QVariant errorData)
846 {
847  QPersistentModelIndex index = setupInProgress.take(q->sender());
848 
849  if (!index.isValid()) {
850  return;
851  }
852 
853  if (!error) {
854  emit q->setupDone(index, true);
855  } else {
856  if (errorData.isValid()) {
857  emit q->errorMessage(i18n("An error occurred while accessing '%1', the system responded: %2",
858  q->text(index),
859  errorData.toString()));
860  } else {
861  emit q->errorMessage(i18n("An error occurred while accessing '%1'",
862  q->text(index)));
863  }
864  emit q->setupDone(index, false);
865  }
866 
867 }
868 
869 void KFilePlacesModel::Private::_k_storageTeardownDone(Solid::ErrorType error, QVariant errorData)
870 {
871  if (error && errorData.isValid()) {
872  emit q->errorMessage(errorData.toString());
873  }
874 }
875 
876 #include "kfileplacesmodel.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Tue Jul 17 2012 07:46:13 by doxygen 1.8.1 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KFile

Skip menu "KFile"
  • Main Page
  • Namespace List
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs-4.8.4 API Reference

Skip menu "kdelibs-4.8.4 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
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
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