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");
122 #if defined(_WIN32_WCE)
124 foreach (
const QFileInfo& info, QDir::drives() ) {
125 QString driveIcon =
"drive-harddisk";
127 info.absoluteFilePath(), info.absoluteFilePath(),
128 KUrl(info.absoluteFilePath()), driveIcon);
130 #elif !defined(Q_OS_WIN)
132 "Root",
I18N_NOOP2(
"KFile System Bookmarks",
"Root"),
133 KUrl(
"/"),
"folder-red");
136 "Trash",
I18N_NOOP2(
"KFile System Bookmarks",
"Trash"),
137 KUrl(
"trash:/"),
"user-trash");
144 d->bookmarkManager->saveAs(file);
151 "[[[[ StorageVolume.ignored == false AND [ StorageVolume.usage == 'FileSystem' OR StorageVolume.usage == 'Encrypted' ]]"
153 "[ IS StorageAccess AND StorageDrive.driveType == 'Floppy' ]]"
155 "OpticalDisc.availableContent & 'Audio' ]"
157 "StorageAccess.ignored == false ]");
158 Q_ASSERT(d->predicate.isValid());
161 this, SLOT(_k_reloadBookmarks()));
162 connect(d->bookmarkManager, SIGNAL(bookmarksChanged(
QString)),
163 this, SLOT(_k_reloadBookmarks()));
165 d->_k_reloadBookmarks();
166 QTimer::singleShot(0,
this, SLOT(_k_initDeviceList()));
186 return KIcon(
data(index, Qt::DecorationRole).value<QIcon>());
191 return data(index, Qt::DisplayRole).toString();
201 if (!index.isValid())
211 if (!index.isValid())
225 if (!index.isValid())
239 if (!index.isValid())
243 return item->
data(role);
248 if (row<0 || column!=0 || row>=d->items.size())
249 return QModelIndex();
251 if (parent.isValid())
252 return QModelIndex();
254 return createIndex(row, column, d->items.at(row));
260 return QModelIndex();
265 if (parent.isValid())
268 return d->items.size();
286 for (
int row = 0; row<d->items.size(); ++row) {
291 const int length = itemUrl.
prettyUrl().length();
292 if (length > maxLength) {
300 return QModelIndex();
302 return createIndex(foundRow, 0, d->items[foundRow]);
305 void KFilePlacesModel::Private::_k_initDeviceList()
309 connect(notifier, SIGNAL(deviceAdded(
QString)),
310 q, SLOT(_k_deviceAdded(
QString)));
311 connect(notifier, SIGNAL(deviceRemoved(
QString)),
312 q, SLOT(_k_deviceRemoved(
QString)));
317 availableDevices << device.
udi();
320 _k_reloadBookmarks();
323 void KFilePlacesModel::Private::_k_deviceAdded(
const QString &udi)
327 if (predicate.matches(d)) {
328 availableDevices << udi;
329 _k_reloadBookmarks();
333 void KFilePlacesModel::Private::_k_deviceRemoved(
const QString &udi)
335 if (availableDevices.contains(udi)) {
336 availableDevices.remove(udi);
337 _k_reloadBookmarks();
341 void KFilePlacesModel::Private::_k_itemChanged(
const QString &
id)
343 for (
int row = 0; row<items.size(); ++row) {
344 if (items.at(row)->id()==id) {
345 QModelIndex index = q->index(row, 0);
346 emit q->dataChanged(index, index);
351 void KFilePlacesModel::Private::_k_reloadBookmarks()
353 QList<KFilePlacesItem*> currentItems = loadBookmarkList();
355 QList<KFilePlacesItem*>::Iterator it_i = items.begin();
356 QList<KFilePlacesItem*>::Iterator it_c = currentItems.begin();
358 QList<KFilePlacesItem*>::Iterator end_i = items.end();
359 QList<KFilePlacesItem*>::Iterator end_c = currentItems.end();
361 while (it_i!=end_i || it_c!=end_c) {
362 if (it_i==end_i && it_c!=end_c) {
363 int row = items.count();
365 q->beginInsertRows(QModelIndex(), row, row);
366 it_i = items.insert(it_i, *it_c);
368 it_c = currentItems.erase(it_c);
371 end_c = currentItems.end();
374 }
else if (it_i!=end_i && it_c==end_c) {
375 int row = items.indexOf(*it_i);
377 q->beginRemoveRows(QModelIndex(), row, row);
379 it_i = items.erase(it_i);
382 end_c = currentItems.end();
385 }
else if ((*it_i)->id()==(*it_c)->id()) {
386 bool shouldEmit = !((*it_i)->bookmark()==(*it_c)->bookmark());
387 (*it_i)->setBookmark((*it_c)->bookmark());
389 int row = items.indexOf(*it_i);
390 QModelIndex idx = q->index(row, 0);
391 emit q->dataChanged(idx, idx);
395 }
else if ((*it_i)->id()!=(*it_c)->id()) {
396 int row = items.indexOf(*it_i);
398 if (it_i+1!=end_i && (*(it_i+1))->
id()==(*it_c)->id()) {
399 q->beginRemoveRows(QModelIndex(), row, row);
401 it_i = items.erase(it_i);
404 end_c = currentItems.end();
407 q->beginInsertRows(QModelIndex(), row, row);
408 it_i = items.insert(it_i, *it_c);
410 it_c = currentItems.erase(it_c);
413 end_c = currentItems.end();
419 qDeleteAll(currentItems);
420 currentItems.clear();
423 QList<KFilePlacesItem *> KFilePlacesModel::Private::loadBookmarkList()
425 QList<KFilePlacesItem*> items;
429 QSet<QString> devices = availableDevices;
431 while (!bookmark.
isNull()) {
434 bool deviceAvailable = devices.remove(udi);
438 if ((udi.isEmpty() && allowedHere) || deviceAvailable) {
440 if (deviceAvailable) {
446 connect(item, SIGNAL(itemChanged(
QString)),
447 q, SLOT(_k_itemChanged(
QString)));
451 bookmark = root.
next(bookmark);
455 foreach (
const QString &udi, devices) {
460 connect(item, SIGNAL(itemChanged(
QString)),
461 q, SLOT(_k_itemChanged(
QString)));
470 void KFilePlacesModel::Private::reloadAndSignal()
472 bookmarkManager->emitChanged(bookmarkManager->root());
477 return Qt::ActionMask;
482 Qt::ItemFlags res = Qt::ItemIsSelectable|Qt::ItemIsEnabled;
485 res|= Qt::ItemIsDragEnabled;
487 if (!index.isValid())
488 res|= Qt::ItemIsDropEnabled;
495 return QString(
"application/x-kfileplacesmodel-")+QString::number((qptrdiff)
self);
512 QDataStream stream(&itemData, QIODevice::WriteOnly);
514 foreach (
const QModelIndex &
index, indexes) {
516 if (itemUrl.isValid())
518 stream << index.row();
521 QMimeData *
mimeData =
new QMimeData();
532 int row,
int column,
const QModelIndex &parent)
534 if (action == Qt::IgnoreAction)
540 if (row==-1 && parent.isValid()) {
554 afterBookmark = lastItem->
bookmark();
561 afterBookmark = afterItem->
bookmark();
568 QDataStream stream(&itemData, QIODevice::ReadOnly);
576 d->bookmarkManager->root().moveBookmark(bookmark, afterBookmark);
578 }
else if (data->hasFormat(
"text/uri-list")) {
584 foreach (
const KUrl &
url, urls) {
589 kWarning() <<
"URL not added to Places as mimetype could not be determined!";
593 if (!mimetype->is(
"inode/directory")) {
600 mimetype->iconName(url));
602 afterBookmark = bookmark;
607 kWarning() <<
": received wrong mimedata, " << data->formats();
611 d->reloadAndSignal();
619 addPlace(text, url, iconName, appName, QModelIndex());
624 const QModelIndex &after)
627 text, url, iconName);
629 if (!appName.isEmpty()) {
633 if (after.isValid()) {
635 d->bookmarkManager->root().moveBookmark(bookmark, item->
bookmark());
638 d->reloadAndSignal();
644 if (!index.isValid())
return;
652 if (bookmark.
isNull())
return;
659 d->reloadAndSignal();
660 emit dataChanged(index, index);
665 if (!index.isValid())
return;
673 if (bookmark.
isNull())
return;
675 d->bookmarkManager->root().deleteBookmark(bookmark);
676 d->reloadAndSignal();
681 if (!index.isValid())
return;
687 if (bookmark.
isNull())
return;
691 d->reloadAndSignal();
692 emit dataChanged(index, index);
700 for (
int i=0; i<rows; ++i) {
721 bool hotpluggable =
false;
722 bool removable =
false;
734 text =
i18n(
"&Release '%1'", label);
735 }
else if (removable || hotpluggable) {
736 text =
i18n(
"&Safely Remove '%1'", label);
737 iconName =
"media-eject";
739 text =
i18n(
"&Unmount '%1'", label);
740 iconName =
"media-eject";
743 if (!iconName.isEmpty()) {
794 QString message =
i18n(
"The device '%1' is not a disk and cannot be ejected.", label);
809 d->setupInProgress[access] =
index;
820 QPersistentModelIndex index = setupInProgress.take(q->sender());
822 if (!index.isValid()) {
827 emit q->setupDone(index,
true);
829 if (errorData.isValid()) {
830 emit q->errorMessage(
i18n(
"An error occurred while accessing '%1', the system responded: %2",
832 errorData.toString()));
834 emit q->errorMessage(
i18n(
"An error occurred while accessing '%1'",
837 emit q->setupDone(index,
false);
844 if (error && errorData.isValid()) {
845 emit q->errorMessage(errorData.toString());
849 #include "kfileplacesmodel.moc"