KFile
kfileplacesmodel.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE project 00002 Copyright (C) 2007 Kevin Ottens <ervin@kde.org> 00003 Copyright (C) 2007 David Faure <faure@kde.org> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License version 2 as published by the Free Software Foundation. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public License 00015 along with this library; see the file COPYING.LIB. If not, write to 00016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00017 Boston, MA 02110-1301, USA. 00018 00019 */ 00020 #include "kfileplacesmodel.h" 00021 #include "kfileplacesitem_p.h" 00022 #include "kfileplacessharedbookmarks_p.h" 00023 00024 #ifdef _WIN32_WCE 00025 #include "Windows.h" 00026 #include "WinBase.h" 00027 #include <QtCore/QDir> 00028 #endif 00029 00030 #include <QtCore/QMimeData> 00031 #include <QtCore/QTimer> 00032 #include <QtCore/QFile> 00033 #include <QtGui/QColor> 00034 #include <QtGui/QAction> 00035 00036 #include <kfileitem.h> 00037 #include <kglobal.h> 00038 #include <klocale.h> 00039 #include <kuser.h> 00040 #include <kstandarddirs.h> 00041 #include <kcomponentdata.h> 00042 #include <kicon.h> 00043 #include <kmimetype.h> 00044 #include <kdebug.h> 00045 00046 #include <kbookmarkmanager.h> 00047 #include <kbookmark.h> 00048 00049 #include <kio/netaccess.h> 00050 #include <kprotocolinfo.h> 00051 00052 #include <solid/devicenotifier.h> 00053 #include <solid/storageaccess.h> 00054 #include <solid/storagedrive.h> 00055 #include <solid/storagevolume.h> 00056 #include <solid/opticaldrive.h> 00057 #include <solid/opticaldisc.h> 00058 #include <solid/portablemediaplayer.h> 00059 #include <solid/predicate.h> 00060 00061 class KFilePlacesModel::Private 00062 { 00063 public: 00064 Private(KFilePlacesModel *self) : q(self), bookmarkManager(0), sharedBookmarks(0) {} 00065 ~Private() 00066 { 00067 delete sharedBookmarks; 00068 qDeleteAll(items); 00069 } 00070 00071 KFilePlacesModel *q; 00072 00073 QList<KFilePlacesItem*> items; 00074 QSet<QString> availableDevices; 00075 QMap<QObject*, QPersistentModelIndex> setupInProgress; 00076 00077 Solid::Predicate predicate; 00078 KBookmarkManager *bookmarkManager; 00079 KFilePlacesSharedBookmarks * sharedBookmarks; 00080 00081 void reloadAndSignal(); 00082 QList<KFilePlacesItem *> loadBookmarkList(); 00083 00084 void _k_initDeviceList(); 00085 void _k_deviceAdded(const QString &udi); 00086 void _k_deviceRemoved(const QString &udi); 00087 void _k_itemChanged(const QString &udi); 00088 void _k_reloadBookmarks(); 00089 void _k_storageSetupDone(Solid::ErrorType error, QVariant errorData); 00090 void _k_storageTeardownDone(Solid::ErrorType error, QVariant errorData); 00091 }; 00092 00093 KFilePlacesModel::KFilePlacesModel(QObject *parent) 00094 : QAbstractItemModel(parent), d(new Private(this)) 00095 { 00096 const QString file = KStandardDirs::locateLocal("data", "kfileplaces/bookmarks.xml"); 00097 d->bookmarkManager = KBookmarkManager::managerForFile(file, "kfilePlaces"); 00098 00099 // Let's put some places in there if it's empty. We have a corner case here: 00100 // Given you have bookmarked some folders (which have been saved on 00101 // ~/.local/share/user-places.xbel (according to freedesktop bookmarks spec), and 00102 // deleted the home directory ~/.kde, the call managerForFile() will return the 00103 // bookmark manager for the fallback "kfilePlaces", making root.first().isNull() being 00104 // false (you have your own items bookmarked), resulting on only being added your own 00105 // bookmarks, and not the default ones too. So, we also check if kfileplaces/bookmarks.xml 00106 // file exists, and if it doesn't, we also add the default places. (ereslibre) 00107 KBookmarkGroup root = d->bookmarkManager->root(); 00108 if (root.first().isNull() || !QFile::exists(file)) { 00109 00110 // NOTE: The context for these I18N_NOOP2 calls has to be "KFile System Bookmarks". 00111 // The real i18nc call is made later, with this context, so the two must match. 00112 // 00113 // createSystemBookmark actually does nothing with its third argument, 00114 // but we have to give it something so the I18N_NOOP2 calls stay here for now. 00115 // 00116 // (coles, 13th May 2009) 00117 00118 KFilePlacesItem::createSystemBookmark(d->bookmarkManager, 00119 "Home", I18N_NOOP2("KFile System Bookmarks", "Home"), 00120 KUrl(KUser().homeDir()), "user-home"); 00121 KFilePlacesItem::createSystemBookmark(d->bookmarkManager, 00122 "Network", I18N_NOOP2("KFile System Bookmarks", "Network"), 00123 KUrl("remote:/"), "network-workgroup"); 00124 #if defined(_WIN32_WCE) 00125 // adding drives 00126 foreach ( const QFileInfo& info, QDir::drives() ) { 00127 QString driveIcon = "drive-harddisk"; 00128 KFilePlacesItem::createSystemBookmark(d->bookmarkManager, 00129 info.absoluteFilePath(), info.absoluteFilePath(), 00130 KUrl(info.absoluteFilePath()), driveIcon); 00131 } 00132 #elif !defined(Q_OS_WIN) 00133 KFilePlacesItem::createSystemBookmark(d->bookmarkManager, 00134 "Root", I18N_NOOP2("KFile System Bookmarks", "Root"), 00135 KUrl("/"), "folder-red"); 00136 #endif 00137 KFilePlacesItem::createSystemBookmark(d->bookmarkManager, 00138 "Trash", I18N_NOOP2("KFile System Bookmarks", "Trash"), 00139 KUrl("trash:/"), "user-trash"); 00140 00141 // Force bookmarks to be saved. If on open/save dialog and the bookmarks are not saved, QFile::exists 00142 // will always return false, which opening/closing all the time the open/save dialog would case the 00143 // bookmarks to be added once each time, having lots of times each bookmark. This forces the defaults 00144 // to be saved on the bookmarks.xml file. Of course, the complete list of bookmarks (those that come from 00145 // user-places.xbel will be filled later). (ereslibre) 00146 d->bookmarkManager->saveAs(file); 00147 } 00148 00149 // create after, so if we have own places, they are added afterwards, in case of equal priorities 00150 d->sharedBookmarks = new KFilePlacesSharedBookmarks(d->bookmarkManager); 00151 00152 QString predicate("[[[[ StorageVolume.ignored == false AND [ StorageVolume.usage == 'FileSystem' OR StorageVolume.usage == 'Encrypted' ]]" 00153 " OR " 00154 "[ IS StorageAccess AND StorageDrive.driveType == 'Floppy' ]]" 00155 " OR " 00156 "OpticalDisc.availableContent & 'Audio' ]" 00157 " OR " 00158 "StorageAccess.ignored == false ]"); 00159 00160 if (KProtocolInfo::isKnownProtocol("mtp")) { 00161 predicate.prepend("["); 00162 predicate.append(" OR PortableMediaPlayer.supportedProtocols == 'mtp']"); 00163 } 00164 00165 d->predicate = Solid::Predicate::fromString(predicate); 00166 00167 Q_ASSERT(d->predicate.isValid()); 00168 00169 connect(d->bookmarkManager, SIGNAL(changed(QString,QString)), 00170 this, SLOT(_k_reloadBookmarks())); 00171 connect(d->bookmarkManager, SIGNAL(bookmarksChanged(QString)), 00172 this, SLOT(_k_reloadBookmarks())); 00173 00174 d->_k_reloadBookmarks(); 00175 QTimer::singleShot(0, this, SLOT(_k_initDeviceList())); 00176 } 00177 00178 KFilePlacesModel::~KFilePlacesModel() 00179 { 00180 delete d; 00181 } 00182 00183 KUrl KFilePlacesModel::url(const QModelIndex &index) const 00184 { 00185 return KUrl(data(index, UrlRole).toUrl()); 00186 } 00187 00188 bool KFilePlacesModel::setupNeeded(const QModelIndex &index) const 00189 { 00190 return data(index, SetupNeededRole).toBool(); 00191 } 00192 00193 KIcon KFilePlacesModel::icon(const QModelIndex &index) const 00194 { 00195 return KIcon(data(index, Qt::DecorationRole).value<QIcon>()); 00196 } 00197 00198 QString KFilePlacesModel::text(const QModelIndex &index) const 00199 { 00200 return data(index, Qt::DisplayRole).toString(); 00201 } 00202 00203 bool KFilePlacesModel::isHidden(const QModelIndex &index) const 00204 { 00205 return data(index, HiddenRole).toBool(); 00206 } 00207 00208 bool KFilePlacesModel::isDevice(const QModelIndex &index) const 00209 { 00210 if (!index.isValid()) 00211 return false; 00212 00213 KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer()); 00214 00215 return item->isDevice(); 00216 } 00217 00218 Solid::Device KFilePlacesModel::deviceForIndex(const QModelIndex &index) const 00219 { 00220 if (!index.isValid()) 00221 return Solid::Device(); 00222 00223 KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer()); 00224 00225 if (item->isDevice()) { 00226 return item->device(); 00227 } else { 00228 return Solid::Device(); 00229 } 00230 } 00231 00232 KBookmark KFilePlacesModel::bookmarkForIndex(const QModelIndex &index) const 00233 { 00234 if (!index.isValid()) 00235 return KBookmark(); 00236 00237 KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer()); 00238 00239 if (!item->isDevice()) { 00240 return item->bookmark(); 00241 } else { 00242 return KBookmark(); 00243 } 00244 } 00245 00246 QVariant KFilePlacesModel::data(const QModelIndex &index, int role) const 00247 { 00248 if (!index.isValid()) 00249 return QVariant(); 00250 00251 KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer()); 00252 return item->data(role); 00253 } 00254 00255 QModelIndex KFilePlacesModel::index(int row, int column, const QModelIndex &parent) const 00256 { 00257 if (row<0 || column!=0 || row>=d->items.size()) 00258 return QModelIndex(); 00259 00260 if (parent.isValid()) 00261 return QModelIndex(); 00262 00263 return createIndex(row, column, d->items.at(row)); 00264 } 00265 00266 QModelIndex KFilePlacesModel::parent(const QModelIndex &child) const 00267 { 00268 Q_UNUSED(child); 00269 return QModelIndex(); 00270 } 00271 00272 int KFilePlacesModel::rowCount(const QModelIndex &parent) const 00273 { 00274 if (parent.isValid()) 00275 return 0; 00276 else 00277 return d->items.size(); 00278 } 00279 00280 int KFilePlacesModel::columnCount(const QModelIndex &parent) const 00281 { 00282 Q_UNUSED(parent) 00283 // We only know 1 piece of information for a particular entry 00284 return 1; 00285 } 00286 00287 QModelIndex KFilePlacesModel::closestItem(const KUrl &url) const 00288 { 00289 int foundRow = -1; 00290 int maxLength = 0; 00291 00292 // Search the item which is equal to the URL or at least is a parent URL. 00293 // If there are more than one possible item URL candidates, choose the item 00294 // which covers the bigger range of the URL. 00295 for (int row = 0; row<d->items.size(); ++row) { 00296 KFilePlacesItem *item = d->items[row]; 00297 KUrl itemUrl = KUrl(item->data(UrlRole).toUrl()); 00298 00299 if (itemUrl.isParentOf(url)) { 00300 const int length = itemUrl.prettyUrl().length(); 00301 if (length > maxLength) { 00302 foundRow = row; 00303 maxLength = length; 00304 } 00305 } 00306 } 00307 00308 if (foundRow==-1) 00309 return QModelIndex(); 00310 else 00311 return createIndex(foundRow, 0, d->items[foundRow]); 00312 } 00313 00314 void KFilePlacesModel::Private::_k_initDeviceList() 00315 { 00316 Solid::DeviceNotifier *notifier = Solid::DeviceNotifier::instance(); 00317 00318 connect(notifier, SIGNAL(deviceAdded(QString)), 00319 q, SLOT(_k_deviceAdded(QString))); 00320 connect(notifier, SIGNAL(deviceRemoved(QString)), 00321 q, SLOT(_k_deviceRemoved(QString))); 00322 00323 const QList<Solid::Device> &deviceList = Solid::Device::listFromQuery(predicate); 00324 00325 foreach(const Solid::Device &device, deviceList) { 00326 availableDevices << device.udi(); 00327 } 00328 00329 _k_reloadBookmarks(); 00330 } 00331 00332 void KFilePlacesModel::Private::_k_deviceAdded(const QString &udi) 00333 { 00334 Solid::Device d(udi); 00335 00336 if (predicate.matches(d)) { 00337 availableDevices << udi; 00338 _k_reloadBookmarks(); 00339 } 00340 } 00341 00342 void KFilePlacesModel::Private::_k_deviceRemoved(const QString &udi) 00343 { 00344 if (availableDevices.contains(udi)) { 00345 availableDevices.remove(udi); 00346 _k_reloadBookmarks(); 00347 } 00348 } 00349 00350 void KFilePlacesModel::Private::_k_itemChanged(const QString &id) 00351 { 00352 for (int row = 0; row<items.size(); ++row) { 00353 if (items.at(row)->id()==id) { 00354 QModelIndex index = q->index(row, 0); 00355 emit q->dataChanged(index, index); 00356 } 00357 } 00358 } 00359 00360 void KFilePlacesModel::Private::_k_reloadBookmarks() 00361 { 00362 QList<KFilePlacesItem*> currentItems = loadBookmarkList(); 00363 00364 QList<KFilePlacesItem*>::Iterator it_i = items.begin(); 00365 QList<KFilePlacesItem*>::Iterator it_c = currentItems.begin(); 00366 00367 QList<KFilePlacesItem*>::Iterator end_i = items.end(); 00368 QList<KFilePlacesItem*>::Iterator end_c = currentItems.end(); 00369 00370 while (it_i!=end_i || it_c!=end_c) { 00371 if (it_i==end_i && it_c!=end_c) { 00372 int row = items.count(); 00373 00374 q->beginInsertRows(QModelIndex(), row, row); 00375 it_i = items.insert(it_i, *it_c); 00376 ++it_i; 00377 it_c = currentItems.erase(it_c); 00378 00379 end_i = items.end(); 00380 end_c = currentItems.end(); 00381 q->endInsertRows(); 00382 00383 } else if (it_i!=end_i && it_c==end_c) { 00384 int row = items.indexOf(*it_i); 00385 00386 q->beginRemoveRows(QModelIndex(), row, row); 00387 delete *it_i; 00388 it_i = items.erase(it_i); 00389 00390 end_i = items.end(); 00391 end_c = currentItems.end(); 00392 q->endRemoveRows(); 00393 00394 } else if ((*it_i)->id()==(*it_c)->id()) { 00395 bool shouldEmit = !((*it_i)->bookmark()==(*it_c)->bookmark()); 00396 (*it_i)->setBookmark((*it_c)->bookmark()); 00397 if (shouldEmit) { 00398 int row = items.indexOf(*it_i); 00399 QModelIndex idx = q->index(row, 0); 00400 emit q->dataChanged(idx, idx); 00401 } 00402 ++it_i; 00403 ++it_c; 00404 } else if ((*it_i)->id()!=(*it_c)->id()) { 00405 int row = items.indexOf(*it_i); 00406 00407 if (it_i+1!=end_i && (*(it_i+1))->id()==(*it_c)->id()) { // if the next one matches, it's a remove 00408 q->beginRemoveRows(QModelIndex(), row, row); 00409 delete *it_i; 00410 it_i = items.erase(it_i); 00411 00412 end_i = items.end(); 00413 end_c = currentItems.end(); 00414 q->endRemoveRows(); 00415 } else { 00416 q->beginInsertRows(QModelIndex(), row, row); 00417 it_i = items.insert(it_i, *it_c); 00418 ++it_i; 00419 it_c = currentItems.erase(it_c); 00420 00421 end_i = items.end(); 00422 end_c = currentItems.end(); 00423 q->endInsertRows(); 00424 } 00425 } 00426 } 00427 00428 qDeleteAll(currentItems); 00429 currentItems.clear(); 00430 } 00431 00432 QList<KFilePlacesItem *> KFilePlacesModel::Private::loadBookmarkList() 00433 { 00434 QList<KFilePlacesItem*> items; 00435 00436 KBookmarkGroup root = bookmarkManager->root(); 00437 KBookmark bookmark = root.first(); 00438 QSet<QString> devices = availableDevices; 00439 00440 while (!bookmark.isNull()) { 00441 QString udi = bookmark.metaDataItem("UDI"); 00442 QString appName = bookmark.metaDataItem("OnlyInApp"); 00443 bool deviceAvailable = devices.remove(udi); 00444 00445 bool allowedHere = appName.isEmpty() || (appName==KGlobal::mainComponent().componentName()); 00446 00447 if ((udi.isEmpty() && allowedHere) || deviceAvailable) { 00448 KFilePlacesItem *item; 00449 if (deviceAvailable) { 00450 item = new KFilePlacesItem(bookmarkManager, bookmark.address(), udi); 00451 // TODO: Update bookmark internal element 00452 } else { 00453 item = new KFilePlacesItem(bookmarkManager, bookmark.address()); 00454 } 00455 connect(item, SIGNAL(itemChanged(QString)), 00456 q, SLOT(_k_itemChanged(QString))); 00457 items << item; 00458 } 00459 00460 bookmark = root.next(bookmark); 00461 } 00462 00463 // Add bookmarks for the remaining devices, they were previously unknown 00464 foreach (const QString &udi, devices) { 00465 bookmark = KFilePlacesItem::createDeviceBookmark(bookmarkManager, udi); 00466 if (!bookmark.isNull()) { 00467 KFilePlacesItem *item = new KFilePlacesItem(bookmarkManager, 00468 bookmark.address(), udi); 00469 connect(item, SIGNAL(itemChanged(QString)), 00470 q, SLOT(_k_itemChanged(QString))); 00471 // TODO: Update bookmark internal element 00472 items << item; 00473 } 00474 } 00475 00476 return items; 00477 } 00478 00479 void KFilePlacesModel::Private::reloadAndSignal() 00480 { 00481 bookmarkManager->emitChanged(bookmarkManager->root()); // ... we'll get relisted anyway 00482 } 00483 00484 Qt::DropActions KFilePlacesModel::supportedDropActions() const 00485 { 00486 return Qt::ActionMask; 00487 } 00488 00489 Qt::ItemFlags KFilePlacesModel::flags(const QModelIndex &index) const 00490 { 00491 Qt::ItemFlags res = Qt::ItemIsSelectable|Qt::ItemIsEnabled; 00492 00493 if (index.isValid()) 00494 res|= Qt::ItemIsDragEnabled; 00495 00496 if (!index.isValid()) 00497 res|= Qt::ItemIsDropEnabled; 00498 00499 return res; 00500 } 00501 00502 static QString _k_internalMimetype(const KFilePlacesModel * const self) 00503 { 00504 return QString("application/x-kfileplacesmodel-")+QString::number((qptrdiff)self); 00505 } 00506 00507 QStringList KFilePlacesModel::mimeTypes() const 00508 { 00509 QStringList types; 00510 00511 types << _k_internalMimetype(this) << "text/uri-list"; 00512 00513 return types; 00514 } 00515 00516 QMimeData *KFilePlacesModel::mimeData(const QModelIndexList &indexes) const 00517 { 00518 KUrl::List urls; 00519 QByteArray itemData; 00520 00521 QDataStream stream(&itemData, QIODevice::WriteOnly); 00522 00523 foreach (const QModelIndex &index, indexes) { 00524 KUrl itemUrl = url(index); 00525 if (itemUrl.isValid()) 00526 urls << itemUrl; 00527 stream << index.row(); 00528 } 00529 00530 QMimeData *mimeData = new QMimeData(); 00531 00532 if (!urls.isEmpty()) 00533 urls.populateMimeData(mimeData); 00534 00535 mimeData->setData(_k_internalMimetype(this), itemData); 00536 00537 return mimeData; 00538 } 00539 00540 bool KFilePlacesModel::dropMimeData(const QMimeData *data, Qt::DropAction action, 00541 int row, int column, const QModelIndex &parent) 00542 { 00543 if (action == Qt::IgnoreAction) 00544 return true; 00545 00546 if (column > 0) 00547 return false; 00548 00549 if (row==-1 && parent.isValid()) { 00550 return false; // Don't allow to move an item onto another one, 00551 // too easy for the user to mess something up 00552 // If we really really want to allow copying files this way, 00553 // let's do it in the views to get the good old drop menu 00554 } 00555 00556 00557 KBookmark afterBookmark; 00558 00559 if (row==-1) { 00560 // The dropped item is moved or added to the last position 00561 00562 KFilePlacesItem *lastItem = d->items.last(); 00563 afterBookmark = lastItem->bookmark(); 00564 00565 } else { 00566 // The dropped item is moved or added before position 'row', ie after position 'row-1' 00567 00568 if (row>0) { 00569 KFilePlacesItem *afterItem = d->items[row-1]; 00570 afterBookmark = afterItem->bookmark(); 00571 } 00572 } 00573 00574 if (data->hasFormat(_k_internalMimetype(this))) { 00575 // The operation is an internal move 00576 QByteArray itemData = data->data(_k_internalMimetype(this)); 00577 QDataStream stream(&itemData, QIODevice::ReadOnly); 00578 int itemRow; 00579 00580 stream >> itemRow; 00581 00582 KFilePlacesItem *item = d->items[itemRow]; 00583 KBookmark bookmark = item->bookmark(); 00584 00585 d->bookmarkManager->root().moveBookmark(bookmark, afterBookmark); 00586 00587 } else if (data->hasFormat("text/uri-list")) { 00588 // The operation is an add 00589 KUrl::List urls = KUrl::List::fromMimeData(data); 00590 00591 KBookmarkGroup group = d->bookmarkManager->root(); 00592 00593 foreach (const KUrl &url, urls) { 00594 // TODO: use KIO::stat in order to get the UDS_DISPLAY_NAME too 00595 KMimeType::Ptr mimetype = KMimeType::mimeType(KIO::NetAccess::mimetype(url, 0)); 00596 00597 if (!mimetype) { 00598 kWarning() << "URL not added to Places as mimetype could not be determined!"; 00599 continue; 00600 } 00601 00602 if (!mimetype->is("inode/directory")) { 00603 // Only directories are allowed 00604 continue; 00605 } 00606 00607 KBookmark bookmark = KFilePlacesItem::createBookmark(d->bookmarkManager, 00608 url.fileName(), url, 00609 mimetype->iconName(url)); 00610 group.moveBookmark(bookmark, afterBookmark); 00611 afterBookmark = bookmark; 00612 } 00613 00614 } else { 00615 // Oops, shouldn't happen thanks to mimeTypes() 00616 kWarning() << ": received wrong mimedata, " << data->formats(); 00617 return false; 00618 } 00619 00620 d->reloadAndSignal(); 00621 00622 return true; 00623 } 00624 00625 void KFilePlacesModel::addPlace(const QString &text, const KUrl &url, 00626 const QString &iconName, const QString &appName) 00627 { 00628 addPlace(text, url, iconName, appName, QModelIndex()); 00629 } 00630 00631 void KFilePlacesModel::addPlace(const QString &text, const KUrl &url, 00632 const QString &iconName, const QString &appName, 00633 const QModelIndex &after) 00634 { 00635 KBookmark bookmark = KFilePlacesItem::createBookmark(d->bookmarkManager, 00636 text, url, iconName); 00637 00638 if (!appName.isEmpty()) { 00639 bookmark.setMetaDataItem("OnlyInApp", appName); 00640 } 00641 00642 if (after.isValid()) { 00643 KFilePlacesItem *item = static_cast<KFilePlacesItem*>(after.internalPointer()); 00644 d->bookmarkManager->root().moveBookmark(bookmark, item->bookmark()); 00645 } 00646 00647 d->reloadAndSignal(); 00648 } 00649 00650 void KFilePlacesModel::editPlace(const QModelIndex &index, const QString &text, const KUrl &url, 00651 const QString &iconName, const QString &appName) 00652 { 00653 if (!index.isValid()) return; 00654 00655 KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer()); 00656 00657 if (item->isDevice()) return; 00658 00659 KBookmark bookmark = item->bookmark(); 00660 00661 if (bookmark.isNull()) return; 00662 00663 bookmark.setFullText(text); 00664 bookmark.setUrl(url); 00665 bookmark.setIcon(iconName); 00666 bookmark.setMetaDataItem("OnlyInApp", appName); 00667 00668 d->reloadAndSignal(); 00669 emit dataChanged(index, index); 00670 } 00671 00672 void KFilePlacesModel::removePlace(const QModelIndex &index) const 00673 { 00674 if (!index.isValid()) return; 00675 00676 KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer()); 00677 00678 if (item->isDevice()) return; 00679 00680 KBookmark bookmark = item->bookmark(); 00681 00682 if (bookmark.isNull()) return; 00683 00684 d->bookmarkManager->root().deleteBookmark(bookmark); 00685 d->reloadAndSignal(); 00686 } 00687 00688 void KFilePlacesModel::setPlaceHidden(const QModelIndex &index, bool hidden) 00689 { 00690 if (!index.isValid()) return; 00691 00692 KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer()); 00693 00694 KBookmark bookmark = item->bookmark(); 00695 00696 if (bookmark.isNull()) return; 00697 00698 bookmark.setMetaDataItem("IsHidden", (hidden ? "true" : "false")); 00699 00700 d->reloadAndSignal(); 00701 emit dataChanged(index, index); 00702 } 00703 00704 int KFilePlacesModel::hiddenCount() const 00705 { 00706 int rows = rowCount(); 00707 int hidden = 0; 00708 00709 for (int i=0; i<rows; ++i) { 00710 if (isHidden(index(i, 0))) { 00711 hidden++; 00712 } 00713 } 00714 00715 return hidden; 00716 } 00717 00718 QAction *KFilePlacesModel::teardownActionForIndex(const QModelIndex &index) const 00719 { 00720 Solid::Device device = deviceForIndex(index); 00721 00722 if (device.is<Solid::StorageAccess>() && device.as<Solid::StorageAccess>()->isAccessible()) { 00723 00724 Solid::StorageDrive *drive = device.as<Solid::StorageDrive>(); 00725 00726 if (drive==0) { 00727 drive = device.parent().as<Solid::StorageDrive>(); 00728 } 00729 00730 bool hotpluggable = false; 00731 bool removable = false; 00732 00733 if (drive!=0) { 00734 hotpluggable = drive->isHotpluggable(); 00735 removable = drive->isRemovable(); 00736 } 00737 00738 QString iconName; 00739 QString text; 00740 QString label = data(index, Qt::DisplayRole).toString().replace('&',"&&"); 00741 00742 if (device.is<Solid::OpticalDisc>()) { 00743 text = i18n("&Release '%1'", label); 00744 } else if (removable || hotpluggable) { 00745 text = i18n("&Safely Remove '%1'", label); 00746 iconName = "media-eject"; 00747 } else { 00748 text = i18n("&Unmount '%1'", label); 00749 iconName = "media-eject"; 00750 } 00751 00752 if (!iconName.isEmpty()) { 00753 return new QAction(KIcon(iconName), text, 0); 00754 } else { 00755 return new QAction(text, 0); 00756 } 00757 } 00758 00759 return 0; 00760 } 00761 00762 QAction *KFilePlacesModel::ejectActionForIndex(const QModelIndex &index) const 00763 { 00764 Solid::Device device = deviceForIndex(index); 00765 00766 if (device.is<Solid::OpticalDisc>()) { 00767 00768 QString label = data(index, Qt::DisplayRole).toString().replace('&',"&&"); 00769 QString text = i18n("&Eject '%1'", label); 00770 00771 return new QAction(KIcon("media-eject"), text, 0); 00772 } 00773 00774 return 0; 00775 } 00776 00777 void KFilePlacesModel::requestTeardown(const QModelIndex &index) 00778 { 00779 Solid::Device device = deviceForIndex(index); 00780 Solid::StorageAccess *access = device.as<Solid::StorageAccess>(); 00781 00782 if (access!=0) { 00783 connect(access, SIGNAL(teardownDone(Solid::ErrorType,QVariant,QString)), 00784 this, SLOT(_k_storageTeardownDone(Solid::ErrorType,QVariant))); 00785 00786 access->teardown(); 00787 } 00788 } 00789 00790 void KFilePlacesModel::requestEject(const QModelIndex &index) 00791 { 00792 Solid::Device device = deviceForIndex(index); 00793 00794 Solid::OpticalDrive *drive = device.parent().as<Solid::OpticalDrive>(); 00795 00796 if (drive!=0) { 00797 connect(drive, SIGNAL(ejectDone(Solid::ErrorType,QVariant,QString)), 00798 this, SLOT(_k_storageTeardownDone(Solid::ErrorType,QVariant))); 00799 00800 drive->eject(); 00801 } else { 00802 QString label = data(index, Qt::DisplayRole).toString().replace('&',"&&"); 00803 QString message = i18n("The device '%1' is not a disk and cannot be ejected.", label); 00804 emit errorMessage(message); 00805 } 00806 } 00807 00808 void KFilePlacesModel::requestSetup(const QModelIndex &index) 00809 { 00810 Solid::Device device = deviceForIndex(index); 00811 00812 if (device.is<Solid::StorageAccess>() 00813 && !d->setupInProgress.contains(device.as<Solid::StorageAccess>()) 00814 && !device.as<Solid::StorageAccess>()->isAccessible()) { 00815 00816 Solid::StorageAccess *access = device.as<Solid::StorageAccess>(); 00817 00818 d->setupInProgress[access] = index; 00819 00820 connect(access, SIGNAL(setupDone(Solid::ErrorType,QVariant,QString)), 00821 this, SLOT(_k_storageSetupDone(Solid::ErrorType,QVariant))); 00822 00823 access->setup(); 00824 } 00825 } 00826 00827 void KFilePlacesModel::Private::_k_storageSetupDone(Solid::ErrorType error, QVariant errorData) 00828 { 00829 QPersistentModelIndex index = setupInProgress.take(q->sender()); 00830 00831 if (!index.isValid()) { 00832 return; 00833 } 00834 00835 if (!error) { 00836 emit q->setupDone(index, true); 00837 } else { 00838 if (errorData.isValid()) { 00839 emit q->errorMessage(i18n("An error occurred while accessing '%1', the system responded: %2", 00840 q->text(index), 00841 errorData.toString())); 00842 } else { 00843 emit q->errorMessage(i18n("An error occurred while accessing '%1'", 00844 q->text(index))); 00845 } 00846 emit q->setupDone(index, false); 00847 } 00848 00849 } 00850 00851 void KFilePlacesModel::Private::_k_storageTeardownDone(Solid::ErrorType error, QVariant errorData) 00852 { 00853 if (error && errorData.isValid()) { 00854 emit q->errorMessage(errorData.toString()); 00855 } 00856 } 00857 00858 #include "kfileplacesmodel.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2019 The KDE developers.
Generated on Mon Jan 21 2019 12:40:57 by doxygen 1.7.5.1 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2019 The KDE developers.
Generated on Mon Jan 21 2019 12:40:57 by doxygen 1.7.5.1 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.