• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

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

KFile

Skip menu "KFile"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal