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