27 #include <QtCore/QDir>
30 #include <QtCore/QMimeData>
31 #include <QtCore/QTimer>
32 #include <QtCore/QFile>
33 #include <QtGui/QColor>
34 #include <QtGui/QAction>
67 delete sharedBookmarks;
73 QList<KFilePlacesItem*> items;
74 QSet<QString> availableDevices;
81 void reloadAndSignal();
82 QList<KFilePlacesItem *> loadBookmarkList();
84 void _k_initDeviceList();
85 void _k_deviceAdded(
const QString &udi);
86 void _k_deviceRemoved(
const QString &udi);
87 void _k_itemChanged(
const QString &udi);
88 void _k_reloadBookmarks();
108 if (root.
first().
isNull() || !QFile::exists(file)) {
119 "Home",
I18N_NOOP2(
"KFile System Bookmarks",
"Home"),
122 "Network",
I18N_NOOP2(
"KFile System Bookmarks",
"Network"),
123 KUrl(
"remote:/"),
"network-workgroup");
124 #if defined(_WIN32_WCE)
126 foreach (
const QFileInfo& info, QDir::drives() ) {
127 QString driveIcon =
"drive-harddisk";
129 info.absoluteFilePath(), info.absoluteFilePath(),
130 KUrl(info.absoluteFilePath()), driveIcon);
132 #elif !defined(Q_OS_WIN)
134 "Root",
I18N_NOOP2(
"KFile System Bookmarks",
"Root"),
135 KUrl(
"/"),
"folder-red");
138 "Trash",
I18N_NOOP2(
"KFile System Bookmarks",
"Trash"),
139 KUrl(
"trash:/"),
"user-trash");
146 d->bookmarkManager->saveAs(file);
152 QString predicate(
"[[[[ StorageVolume.ignored == false AND [ StorageVolume.usage == 'FileSystem' OR StorageVolume.usage == 'Encrypted' ]]"
154 "[ IS StorageAccess AND StorageDrive.driveType == 'Floppy' ]]"
156 "OpticalDisc.availableContent & 'Audio' ]"
158 "StorageAccess.ignored == false ]");
161 predicate.prepend(
"[");
162 predicate.append(
" OR PortableMediaPlayer.supportedProtocols == 'mtp']");
167 Q_ASSERT(d->predicate.isValid());
170 this, SLOT(_k_reloadBookmarks()));
171 connect(d->bookmarkManager, SIGNAL(bookmarksChanged(
QString)),
172 this, SLOT(_k_reloadBookmarks()));
174 d->_k_reloadBookmarks();
175 QTimer::singleShot(0,
this, SLOT(_k_initDeviceList()));
195 return KIcon(
data(index, Qt::DecorationRole).value<QIcon>());
200 return data(index, Qt::DisplayRole).toString();
210 if (!index.isValid())
220 if (!index.isValid())
234 if (!index.isValid())
248 if (!index.isValid())
252 return item->
data(role);
257 if (row<0 || column!=0 || row>=d->items.size())
258 return QModelIndex();
260 if (parent.isValid())
261 return QModelIndex();
263 return createIndex(row, column, d->items.at(row));
269 return QModelIndex();
274 if (parent.isValid())
277 return d->items.size();
295 for (
int row = 0; row<d->items.size(); ++row) {
300 const int length = itemUrl.
prettyUrl().length();
301 if (length > maxLength) {
309 return QModelIndex();
311 return createIndex(foundRow, 0, d->items[foundRow]);
314 void KFilePlacesModel::Private::_k_initDeviceList()
318 connect(notifier, SIGNAL(deviceAdded(
QString)),
319 q, SLOT(_k_deviceAdded(
QString)));
320 connect(notifier, SIGNAL(deviceRemoved(
QString)),
321 q, SLOT(_k_deviceRemoved(
QString)));
326 availableDevices << device.
udi();
329 _k_reloadBookmarks();
332 void KFilePlacesModel::Private::_k_deviceAdded(
const QString &udi)
336 if (predicate.matches(d)) {
337 availableDevices << udi;
338 _k_reloadBookmarks();
342 void KFilePlacesModel::Private::_k_deviceRemoved(
const QString &udi)
344 if (availableDevices.contains(udi)) {
345 availableDevices.remove(udi);
346 _k_reloadBookmarks();
350 void KFilePlacesModel::Private::_k_itemChanged(
const QString &
id)
352 for (
int row = 0; row<items.size(); ++row) {
353 if (items.at(row)->id()==id) {
354 QModelIndex index = q->index(row, 0);
355 emit q->dataChanged(index, index);
360 void KFilePlacesModel::Private::_k_reloadBookmarks()
362 QList<KFilePlacesItem*> currentItems = loadBookmarkList();
364 QList<KFilePlacesItem*>::Iterator it_i = items.begin();
365 QList<KFilePlacesItem*>::Iterator it_c = currentItems.begin();
367 QList<KFilePlacesItem*>::Iterator end_i = items.end();
368 QList<KFilePlacesItem*>::Iterator end_c = currentItems.end();
370 while (it_i!=end_i || it_c!=end_c) {
371 if (it_i==end_i && it_c!=end_c) {
372 int row = items.count();
374 q->beginInsertRows(QModelIndex(), row, row);
375 it_i = items.insert(it_i, *it_c);
377 it_c = currentItems.erase(it_c);
380 end_c = currentItems.end();
383 }
else if (it_i!=end_i && it_c==end_c) {
384 int row = items.indexOf(*it_i);
386 q->beginRemoveRows(QModelIndex(), row, row);
388 it_i = items.erase(it_i);
391 end_c = currentItems.end();
394 }
else if ((*it_i)->id()==(*it_c)->id()) {
395 bool shouldEmit = !((*it_i)->bookmark()==(*it_c)->bookmark());
396 (*it_i)->setBookmark((*it_c)->bookmark());
398 int row = items.indexOf(*it_i);
399 QModelIndex idx = q->index(row, 0);
400 emit q->dataChanged(idx, idx);
404 }
else if ((*it_i)->id()!=(*it_c)->id()) {
405 int row = items.indexOf(*it_i);
407 if (it_i+1!=end_i && (*(it_i+1))->
id()==(*it_c)->id()) {
408 q->beginRemoveRows(QModelIndex(), row, row);
410 it_i = items.erase(it_i);
413 end_c = currentItems.end();
416 q->beginInsertRows(QModelIndex(), row, row);
417 it_i = items.insert(it_i, *it_c);
419 it_c = currentItems.erase(it_c);
422 end_c = currentItems.end();
428 qDeleteAll(currentItems);
429 currentItems.clear();
432 QList<KFilePlacesItem *> KFilePlacesModel::Private::loadBookmarkList()
434 QList<KFilePlacesItem*> items;
438 QSet<QString> devices = availableDevices;
440 while (!bookmark.
isNull()) {
443 bool deviceAvailable = devices.remove(udi);
447 if ((udi.isEmpty() && allowedHere) || deviceAvailable) {
449 if (deviceAvailable) {
455 connect(item, SIGNAL(itemChanged(
QString)),
456 q, SLOT(_k_itemChanged(
QString)));
460 bookmark = root.
next(bookmark);
464 foreach (
const QString &udi, devices) {
469 connect(item, SIGNAL(itemChanged(
QString)),
470 q, SLOT(_k_itemChanged(
QString)));
479 void KFilePlacesModel::Private::reloadAndSignal()
481 bookmarkManager->emitChanged(bookmarkManager->root());
486 return Qt::ActionMask;
491 Qt::ItemFlags res = Qt::ItemIsSelectable|Qt::ItemIsEnabled;
494 res|= Qt::ItemIsDragEnabled;
496 if (!index.isValid())
497 res|= Qt::ItemIsDropEnabled;
504 return QString(
"application/x-kfileplacesmodel-")+QString::number((qptrdiff)
self);
521 QDataStream stream(&itemData, QIODevice::WriteOnly);
523 foreach (
const QModelIndex &
index, indexes) {
525 if (itemUrl.isValid())
527 stream << index.row();
530 QMimeData *
mimeData =
new QMimeData();
541 int row,
int column,
const QModelIndex &parent)
543 if (action == Qt::IgnoreAction)
549 if (row==-1 && parent.isValid()) {
563 afterBookmark = lastItem->
bookmark();
570 afterBookmark = afterItem->
bookmark();
577 QDataStream stream(&itemData, QIODevice::ReadOnly);
585 d->bookmarkManager->root().moveBookmark(bookmark, afterBookmark);
587 }
else if (data->hasFormat(
"text/uri-list")) {
593 foreach (
const KUrl &
url, urls) {
598 kWarning() <<
"URL not added to Places as mimetype could not be determined!";
602 if (!mimetype->is(
"inode/directory")) {
609 mimetype->iconName(url));
611 afterBookmark = bookmark;
616 kWarning() <<
": received wrong mimedata, " << data->formats();
620 d->reloadAndSignal();
628 addPlace(text, url, iconName, appName, QModelIndex());
633 const QModelIndex &after)
636 text, url, iconName);
638 if (!appName.isEmpty()) {
642 if (after.isValid()) {
644 d->bookmarkManager->root().moveBookmark(bookmark, item->
bookmark());
647 d->reloadAndSignal();
653 if (!index.isValid())
return;
661 if (bookmark.
isNull())
return;
668 d->reloadAndSignal();
669 emit dataChanged(index, index);
674 if (!index.isValid())
return;
682 if (bookmark.
isNull())
return;
684 d->bookmarkManager->root().deleteBookmark(bookmark);
685 d->reloadAndSignal();
690 if (!index.isValid())
return;
696 if (bookmark.
isNull())
return;
700 d->reloadAndSignal();
701 emit dataChanged(index, index);
709 for (
int i=0; i<rows; ++i) {
730 bool hotpluggable =
false;
731 bool removable =
false;
743 text =
i18n(
"&Release '%1'", label);
744 }
else if (removable || hotpluggable) {
745 text =
i18n(
"&Safely Remove '%1'", label);
746 iconName =
"media-eject";
748 text =
i18n(
"&Unmount '%1'", label);
749 iconName =
"media-eject";
752 if (!iconName.isEmpty()) {
803 QString message =
i18n(
"The device '%1' is not a disk and cannot be ejected.", label);
818 d->setupInProgress[access] =
index;
829 QPersistentModelIndex index = setupInProgress.take(q->sender());
831 if (!index.isValid()) {
836 emit q->setupDone(index,
true);
838 if (errorData.isValid()) {
839 emit q->errorMessage(
i18n(
"An error occurred while accessing '%1', the system responded: %2",
841 errorData.toString()));
843 emit q->errorMessage(
i18n(
"An error occurred while accessing '%1'",
846 emit q->setupDone(index,
false);
853 if (error && errorData.isValid()) {
854 emit q->errorMessage(errorData.toString());
858 #include "kfileplacesmodel.moc"