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;
81 void reloadAndSignal();
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();
89 void _k_storageSetupDone(Solid::ErrorType error,
QVariant errorData);
90 void _k_storageTeardownDone(Solid::ErrorType error,
QVariant errorData);
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()
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();
440 while (!bookmark.
isNull()) {
443 bool deviceAvailable = devices.remove(udi);
445 bool allowedHere = appName.isEmpty() || (appName==KGlobal::mainComponent().componentName());
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 int destRow = row == -1 ? d->items.count() : row;
587 if (itemRow == destRow || itemRow + 1 == destRow) {
591 beginMoveRows(QModelIndex(), itemRow, itemRow, QModelIndex(), destRow);
592 d->bookmarkManager->root().moveBookmark(bookmark, afterBookmark);
600 d->items.move(itemRow, itemRow < destRow ? (destRow - 1) : destRow);
602 }
else if (data->hasFormat(
"text/uri-list")) {
608 foreach (
const KUrl &
url, urls) {
613 kWarning() <<
"URL not added to Places as mimetype could not be determined!";
617 if (!mimetype->is(
"inode/directory")) {
624 mimetype->iconName(url));
626 afterBookmark = bookmark;
631 kWarning() <<
": received wrong mimedata, " << data->formats();
635 d->reloadAndSignal();
643 addPlace(text, url, iconName, appName, QModelIndex());
648 const QModelIndex &after)
651 text, url, iconName);
653 if (!appName.isEmpty()) {
657 if (after.isValid()) {
659 d->bookmarkManager->root().moveBookmark(bookmark, item->
bookmark());
662 d->reloadAndSignal();
668 if (!index.isValid())
return;
676 if (bookmark.
isNull())
return;
683 d->reloadAndSignal();
684 emit dataChanged(index, index);
689 if (!index.isValid())
return;
697 if (bookmark.
isNull())
return;
699 d->bookmarkManager->root().deleteBookmark(bookmark);
700 d->reloadAndSignal();
705 if (!index.isValid())
return;
711 if (bookmark.
isNull())
return;
715 d->reloadAndSignal();
716 emit dataChanged(index, index);
724 for (
int i=0; i<rows; ++i) {
745 bool hotpluggable =
false;
746 bool removable =
false;
749 hotpluggable = drive->isHotpluggable();
750 removable = drive->isRemovable();
758 text =
i18n(
"&Release '%1'", label);
759 }
else if (removable || hotpluggable) {
760 text =
i18n(
"&Safely Remove '%1'", label);
761 iconName =
"media-eject";
763 text =
i18n(
"&Unmount '%1'", label);
764 iconName =
"media-eject";
767 if (!iconName.isEmpty()) {
798 connect(access, SIGNAL(teardownDone(Solid::ErrorType,
QVariant,
QString)),
799 this, SLOT(_k_storageTeardownDone(Solid::ErrorType,
QVariant)));
813 this, SLOT(_k_storageTeardownDone(Solid::ErrorType,
QVariant)));
818 QString message =
i18n(
"The device '%1' is not a disk and cannot be ejected.", label);
833 d->setupInProgress[access] =
index;
836 this, SLOT(_k_storageSetupDone(Solid::ErrorType,
QVariant)));
842 void KFilePlacesModel::Private::_k_storageSetupDone(Solid::ErrorType error,
QVariant errorData)
844 QPersistentModelIndex index = setupInProgress.take(q->sender());
846 if (!index.isValid()) {
851 emit q->setupDone(index,
true);
853 if (errorData.isValid()) {
854 emit q->errorMessage(
i18n(
"An error occurred while accessing '%1', the system responded: %2",
856 errorData.toString()));
858 emit q->errorMessage(
i18n(
"An error occurred while accessing '%1'",
861 emit q->setupDone(index,
false);
866 void KFilePlacesModel::Private::_k_storageTeardownDone(Solid::ErrorType error,
QVariant errorData)
868 if (error && errorData.isValid()) {
869 emit q->errorMessage(errorData.toString());
873 #include "kfileplacesmodel.moc"