27 #include <QtCore/QDir>
30 #include <QtCore/QMimeData>
31 #include <QtCore/QTimer>
32 #include <QtCore/QFile>
33 #include <QtGui/QColor>
34 #include <QtGui/QAction>
65 delete sharedBookmarks;
71 QList<KFilePlacesItem*> items;
72 QSet<QString> availableDevices;
79 void reloadAndSignal();
80 QList<KFilePlacesItem *> loadBookmarkList();
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();
106 if (root.
first().
isNull() || !QFile::exists(file)) {
117 "Home",
I18N_NOOP2(
"KFile System Bookmarks",
"Home"),
120 "Network",
I18N_NOOP2(
"KFile System Bookmarks",
"Network"),
121 KUrl(
"remote:/"),
"network-workgroup");
124 foreach (
const QFileInfo& info, QDir::drives() ) {
126 uint type = DRIVE_UNKNOWN;
128 QString driveIcon =
"drive-harddisk";
130 QT_WA({ type = GetDriveTypeW((
wchar_t *)info.absoluteFilePath().utf16()); },
131 { type = GetDriveTypeA(info.absoluteFilePath().toLocal8Bit()); });
134 case DRIVE_REMOVABLE:
135 driveIcon =
"drive-removable-media";
138 driveIcon =
"drive-harddisk";
141 driveIcon =
"network-server";
144 driveIcon =
"drive-optical";
148 case DRIVE_NO_ROOT_DIR:
150 driveIcon =
"drive-harddisk";
154 info.absoluteFilePath(), info.absoluteFilePath(),
155 KUrl(info.absoluteFilePath()), driveIcon);
159 "Root",
I18N_NOOP2(
"KFile System Bookmarks",
"Root"),
160 KUrl(
"/"),
"folder-red");
163 "Trash",
I18N_NOOP2(
"KFile System Bookmarks",
"Trash"),
164 KUrl(
"trash:/"),
"user-trash");
171 d->bookmarkManager->saveAs(file);
178 "[[[[ StorageVolume.ignored == false AND [ StorageVolume.usage == 'FileSystem' OR StorageVolume.usage == 'Encrypted' ]]"
180 "[ IS StorageAccess AND StorageDrive.driveType == 'Floppy' ]]"
182 "OpticalDisc.availableContent & 'Audio' ]"
184 "StorageAccess.ignored == false ]");
185 Q_ASSERT(d->predicate.isValid());
188 this, SLOT(_k_reloadBookmarks()));
189 connect(d->bookmarkManager, SIGNAL(bookmarksChanged(
QString)),
190 this, SLOT(_k_reloadBookmarks()));
192 d->_k_reloadBookmarks();
193 QTimer::singleShot(0,
this, SLOT(_k_initDeviceList()));
213 return KIcon(
data(index, Qt::DecorationRole).value<QIcon>());
218 return data(index, Qt::DisplayRole).toString();
228 if (!index.isValid())
238 if (!index.isValid())
252 if (!index.isValid())
266 if (!index.isValid())
270 return item->
data(role);
275 if (row<0 || column!=0 || row>=d->items.size())
276 return QModelIndex();
278 if (parent.isValid())
279 return QModelIndex();
281 return createIndex(row, column, d->items.at(row));
287 return QModelIndex();
292 if (parent.isValid())
295 return d->items.size();
313 for (
int row = 0; row<d->items.size(); ++row) {
318 const int length = itemUrl.
prettyUrl().length();
319 if (length > maxLength) {
327 return QModelIndex();
329 return createIndex(foundRow, 0, d->items[foundRow]);
332 void KFilePlacesModel::Private::_k_initDeviceList()
336 connect(notifier, SIGNAL(deviceAdded(
QString)),
337 q, SLOT(_k_deviceAdded(
QString)));
338 connect(notifier, SIGNAL(deviceRemoved(
QString)),
339 q, SLOT(_k_deviceRemoved(
QString)));
344 availableDevices << device.
udi();
347 _k_reloadBookmarks();
350 void KFilePlacesModel::Private::_k_deviceAdded(
const QString &udi)
354 if (predicate.matches(d)) {
355 availableDevices << udi;
356 _k_reloadBookmarks();
360 void KFilePlacesModel::Private::_k_deviceRemoved(
const QString &udi)
362 if (availableDevices.contains(udi)) {
363 availableDevices.remove(udi);
364 _k_reloadBookmarks();
368 void KFilePlacesModel::Private::_k_itemChanged(
const QString &
id)
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);
378 void KFilePlacesModel::Private::_k_reloadBookmarks()
380 QList<KFilePlacesItem*> currentItems = loadBookmarkList();
382 QList<KFilePlacesItem*>::Iterator it_i = items.begin();
383 QList<KFilePlacesItem*>::Iterator it_c = currentItems.begin();
385 QList<KFilePlacesItem*>::Iterator end_i = items.end();
386 QList<KFilePlacesItem*>::Iterator end_c = currentItems.end();
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();
392 q->beginInsertRows(QModelIndex(), row, row);
393 it_i = items.insert(it_i, *it_c);
395 it_c = currentItems.erase(it_c);
398 end_c = currentItems.end();
401 }
else if (it_i!=end_i && it_c==end_c) {
402 int row = items.indexOf(*it_i);
404 q->beginRemoveRows(QModelIndex(), row, row);
406 it_i = items.erase(it_i);
409 end_c = currentItems.end();
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());
416 int row = items.indexOf(*it_i);
417 QModelIndex idx = q->index(row, 0);
418 emit q->dataChanged(idx, idx);
422 }
else if ((*it_i)->id()!=(*it_c)->id()) {
423 int row = items.indexOf(*it_i);
425 if (it_i+1!=end_i && (*(it_i+1))->
id()==(*it_c)->id()) {
426 q->beginRemoveRows(QModelIndex(), row, row);
428 it_i = items.erase(it_i);
431 end_c = currentItems.end();
434 q->beginInsertRows(QModelIndex(), row, row);
435 it_i = items.insert(it_i, *it_c);
437 it_c = currentItems.erase(it_c);
440 end_c = currentItems.end();
446 qDeleteAll(currentItems);
447 currentItems.clear();
450 QList<KFilePlacesItem *> KFilePlacesModel::Private::loadBookmarkList()
452 QList<KFilePlacesItem*> items;
456 QSet<QString> devices = availableDevices;
458 while (!bookmark.
isNull()) {
461 bool deviceAvailable = devices.remove(udi);
465 if ((udi.isEmpty() && allowedHere) || deviceAvailable) {
467 if (deviceAvailable) {
473 connect(item, SIGNAL(itemChanged(
QString)),
474 q, SLOT(_k_itemChanged(
QString)));
478 bookmark = root.
next(bookmark);
482 foreach (
const QString &udi, devices) {
487 connect(item, SIGNAL(itemChanged(
QString)),
488 q, SLOT(_k_itemChanged(
QString)));
497 void KFilePlacesModel::Private::reloadAndSignal()
499 bookmarkManager->emitChanged(bookmarkManager->root());
504 return Qt::ActionMask;
509 Qt::ItemFlags res = Qt::ItemIsSelectable|Qt::ItemIsEnabled;
512 res|= Qt::ItemIsDragEnabled;
514 if (!index.isValid())
515 res|= Qt::ItemIsDropEnabled;
522 return QString(
"application/x-kfileplacesmodel-")+QString::number((qptrdiff)
self);
539 QDataStream stream(&itemData, QIODevice::WriteOnly);
541 foreach (
const QModelIndex &
index, indexes) {
543 if (itemUrl.isValid())
545 stream << index.row();
548 QMimeData *
mimeData =
new QMimeData();
559 int row,
int column,
const QModelIndex &parent)
561 if (action == Qt::IgnoreAction)
567 if (row==-1 && parent.isValid()) {
581 afterBookmark = lastItem->
bookmark();
588 afterBookmark = afterItem->
bookmark();
595 QDataStream stream(&itemData, QIODevice::ReadOnly);
603 d->bookmarkManager->root().moveBookmark(bookmark, afterBookmark);
605 }
else if (data->hasFormat(
"text/uri-list")) {
611 foreach (
const KUrl &
url, urls) {
616 kWarning() <<
"URL not added to Places as mimetype could not be determined!";
620 if (!mimetype->is(
"inode/directory")) {
627 mimetype->iconName(url));
629 afterBookmark = bookmark;
634 kWarning() <<
": received wrong mimedata, " << data->formats();
638 d->reloadAndSignal();
646 addPlace(text, url, iconName, appName, QModelIndex());
651 const QModelIndex &after)
654 text, url, iconName);
656 if (!appName.isEmpty()) {
660 if (after.isValid()) {
662 d->bookmarkManager->root().moveBookmark(bookmark, item->
bookmark());
665 d->reloadAndSignal();
671 if (!index.isValid())
return;
679 if (bookmark.
isNull())
return;
686 d->reloadAndSignal();
687 emit dataChanged(index, index);
692 if (!index.isValid())
return;
700 if (bookmark.
isNull())
return;
702 d->bookmarkManager->root().deleteBookmark(bookmark);
703 d->reloadAndSignal();
708 if (!index.isValid())
return;
714 if (bookmark.
isNull())
return;
718 d->reloadAndSignal();
719 emit dataChanged(index, index);
727 for (
int i=0; i<rows; ++i) {
748 bool hotpluggable =
false;
749 bool removable =
false;
761 text =
i18n(
"&Release '%1'", label);
762 }
else if (removable || hotpluggable) {
763 text =
i18n(
"&Safely Remove '%1'", label);
764 iconName =
"media-eject";
766 text =
i18n(
"&Unmount '%1'", label);
767 iconName =
"media-eject";
770 if (!iconName.isEmpty()) {
821 QString message =
i18n(
"The device '%1' is not a disk and cannot be ejected.", label);
836 d->setupInProgress[access] =
index;
847 QPersistentModelIndex index = setupInProgress.take(q->sender());
849 if (!index.isValid()) {
854 emit q->setupDone(index,
true);
856 if (errorData.isValid()) {
857 emit q->errorMessage(
i18n(
"An error occurred while accessing '%1', the system responded: %2",
859 errorData.toString()));
861 emit q->errorMessage(
i18n(
"An error occurred while accessing '%1'",
864 emit q->setupDone(index,
false);
871 if (error && errorData.isValid()) {
872 emit q->errorMessage(errorData.toString());
876 #include "kfileplacesmodel.moc"