• Skip to content
  • Skip to link menu
KDE 4.7 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             // TODO: use KIO::stat in order to get the UDS_DISPLAY_NAME too
00613             KMimeType::Ptr mimetype = KMimeType::mimeType(KIO::NetAccess::mimetype(url, 0));
00614 
00615             if (!mimetype) {
00616                 kWarning() << "URL not added to Places as mimetype could not be determined!";
00617                 continue;
00618             }
00619 
00620             if (!mimetype->is("inode/directory")) {
00621                 // Only directories are allowed
00622                 continue;
00623             }
00624 
00625             KBookmark bookmark = KFilePlacesItem::createBookmark(d->bookmarkManager,
00626                                                                  url.fileName(), url,
00627                                                                  mimetype->iconName(url));
00628             group.moveBookmark(bookmark, afterBookmark);
00629             afterBookmark = bookmark;
00630         }
00631 
00632     } else {
00633         // Oops, shouldn't happen thanks to mimeTypes()
00634         kWarning() << ": received wrong mimedata, " << data->formats();
00635         return false;
00636     }
00637 
00638     d->reloadAndSignal();
00639 
00640     return true;
00641 }
00642 
00643 void KFilePlacesModel::addPlace(const QString &text, const KUrl &url,
00644                                 const QString &iconName, const QString &appName)
00645 {
00646     addPlace(text, url, iconName, appName, QModelIndex());
00647 }
00648 
00649 void KFilePlacesModel::addPlace(const QString &text, const KUrl &url,
00650                                 const QString &iconName, const QString &appName,
00651                                 const QModelIndex &after)
00652 {
00653     KBookmark bookmark = KFilePlacesItem::createBookmark(d->bookmarkManager,
00654                                                          text, url, iconName);
00655 
00656     if (!appName.isEmpty()) {
00657         bookmark.setMetaDataItem("OnlyInApp", appName);
00658     }
00659 
00660     if (after.isValid()) {
00661         KFilePlacesItem *item = static_cast<KFilePlacesItem*>(after.internalPointer());
00662         d->bookmarkManager->root().moveBookmark(bookmark, item->bookmark());
00663     }
00664 
00665     d->reloadAndSignal();
00666 }
00667 
00668 void KFilePlacesModel::editPlace(const QModelIndex &index, const QString &text, const KUrl &url,
00669                                  const QString &iconName, const QString &appName)
00670 {
00671     if (!index.isValid()) return;
00672 
00673     KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer());
00674 
00675     if (item->isDevice()) return;
00676 
00677     KBookmark bookmark = item->bookmark();
00678 
00679     if (bookmark.isNull()) return;
00680 
00681     bookmark.setFullText(text);
00682     bookmark.setUrl(url);
00683     bookmark.setIcon(iconName);
00684     bookmark.setMetaDataItem("OnlyInApp", appName);
00685 
00686     d->reloadAndSignal();
00687     emit dataChanged(index, index);
00688 }
00689 
00690 void KFilePlacesModel::removePlace(const QModelIndex &index) const
00691 {
00692     if (!index.isValid()) return;
00693 
00694     KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer());
00695 
00696     if (item->isDevice()) return;
00697 
00698     KBookmark bookmark = item->bookmark();
00699 
00700     if (bookmark.isNull()) return;
00701 
00702     d->bookmarkManager->root().deleteBookmark(bookmark);
00703     d->reloadAndSignal();
00704 }
00705 
00706 void KFilePlacesModel::setPlaceHidden(const QModelIndex &index, bool hidden)
00707 {
00708     if (!index.isValid()) return;
00709 
00710     KFilePlacesItem *item = static_cast<KFilePlacesItem*>(index.internalPointer());
00711 
00712     KBookmark bookmark = item->bookmark();
00713 
00714     if (bookmark.isNull()) return;
00715 
00716     bookmark.setMetaDataItem("IsHidden", (hidden ? "true" : "false"));
00717 
00718     d->reloadAndSignal();
00719     emit dataChanged(index, index);
00720 }
00721 
00722 int KFilePlacesModel::hiddenCount() const
00723 {
00724     int rows = rowCount();
00725     int hidden = 0;
00726 
00727     for (int i=0; i<rows; ++i) {
00728         if (isHidden(index(i, 0))) {
00729             hidden++;
00730         }
00731     }
00732 
00733     return hidden;
00734 }
00735 
00736 QAction *KFilePlacesModel::teardownActionForIndex(const QModelIndex &index) const
00737 {
00738     Solid::Device device = deviceForIndex(index);
00739 
00740     if (device.is<Solid::StorageAccess>() && device.as<Solid::StorageAccess>()->isAccessible()) {
00741 
00742         Solid::StorageDrive *drive = device.as<Solid::StorageDrive>();
00743 
00744         if (drive==0) {
00745             drive = device.parent().as<Solid::StorageDrive>();
00746         }
00747 
00748         bool hotpluggable = false;
00749         bool removable = false;
00750 
00751         if (drive!=0) {
00752             hotpluggable = drive->isHotpluggable();
00753             removable = drive->isRemovable();
00754         }
00755 
00756         QString iconName;
00757         QString text;
00758         QString label = data(index, Qt::DisplayRole).toString().replace('&',"&&");
00759 
00760         if (device.is<Solid::OpticalDisc>()) {
00761             text = i18n("&Release '%1'", label);
00762         } else if (removable || hotpluggable) {
00763             text = i18n("&Safely Remove '%1'", label);
00764             iconName = "media-eject";
00765         } else {
00766             text = i18n("&Unmount '%1'", label);
00767             iconName = "media-eject";
00768         }
00769 
00770         if (!iconName.isEmpty()) {
00771             return new QAction(KIcon(iconName), text, 0);
00772         } else {
00773             return new QAction(text, 0);
00774         }
00775     }
00776 
00777     return 0;
00778 }
00779 
00780 QAction *KFilePlacesModel::ejectActionForIndex(const QModelIndex &index) const
00781 {
00782     Solid::Device device = deviceForIndex(index);
00783 
00784     if (device.is<Solid::OpticalDisc>()) {
00785 
00786         QString label = data(index, Qt::DisplayRole).toString().replace('&',"&&");
00787         QString text = i18n("&Eject '%1'", label);
00788 
00789         return new QAction(KIcon("media-eject"), text, 0);
00790     }
00791 
00792     return 0;
00793 }
00794 
00795 void KFilePlacesModel::requestTeardown(const QModelIndex &index)
00796 {
00797     Solid::Device device = deviceForIndex(index);
00798     Solid::StorageAccess *access = device.as<Solid::StorageAccess>();
00799 
00800     if (access!=0) {
00801         connect(access, SIGNAL(teardownDone(Solid::ErrorType, QVariant, const QString &)),
00802                 this, SLOT(_k_storageTeardownDone(Solid::ErrorType, QVariant)));
00803 
00804         access->teardown();
00805     }
00806 }
00807 
00808 void KFilePlacesModel::requestEject(const QModelIndex &index)
00809 {
00810     Solid::Device device = deviceForIndex(index);
00811 
00812     Solid::OpticalDrive *drive = device.parent().as<Solid::OpticalDrive>();
00813 
00814     if (drive!=0) {
00815         connect(drive, SIGNAL(ejectDone(Solid::ErrorType, QVariant, const QString &)),
00816                 this, SLOT(_k_storageTeardownDone(Solid::ErrorType, QVariant)));
00817 
00818         drive->eject();
00819     } else {
00820         QString label = data(index, Qt::DisplayRole).toString().replace('&',"&&");
00821         QString message = i18n("The device '%1' is not a disk and cannot be ejected.", label);
00822         emit errorMessage(message);
00823     }
00824 }
00825 
00826 void KFilePlacesModel::requestSetup(const QModelIndex &index)
00827 {
00828     Solid::Device device = deviceForIndex(index);
00829 
00830     if (device.is<Solid::StorageAccess>()
00831      && !d->setupInProgress.contains(device.as<Solid::StorageAccess>())
00832      && !device.as<Solid::StorageAccess>()->isAccessible()) {
00833 
00834         Solid::StorageAccess *access = device.as<Solid::StorageAccess>();
00835 
00836         d->setupInProgress[access] = index;
00837 
00838         connect(access, SIGNAL(setupDone(Solid::ErrorType, QVariant, const QString &)),
00839                 this, SLOT(_k_storageSetupDone(Solid::ErrorType, QVariant)));
00840 
00841         access->setup();
00842     }
00843 }
00844 
00845 void KFilePlacesModel::Private::_k_storageSetupDone(Solid::ErrorType error, QVariant errorData)
00846 {
00847     QPersistentModelIndex index = setupInProgress.take(q->sender());
00848 
00849     if (!index.isValid()) {
00850         return;
00851     }
00852 
00853     if (!error) {
00854         emit q->setupDone(index, true);
00855     } else {
00856         if (errorData.isValid()) {
00857             emit q->errorMessage(i18n("An error occurred while accessing '%1', the system responded: %2",
00858                                       q->text(index),
00859                                       errorData.toString()));
00860         } else {
00861             emit q->errorMessage(i18n("An error occurred while accessing '%1'",
00862                                       q->text(index)));
00863         }
00864         emit q->setupDone(index, false);
00865     }
00866 
00867 }
00868 
00869 void KFilePlacesModel::Private::_k_storageTeardownDone(Solid::ErrorType error, QVariant errorData)
00870 {
00871     if (error && errorData.isValid()) {
00872         emit q->errorMessage(errorData.toString());
00873     }
00874 }
00875 
00876 #include "kfileplacesmodel.moc"

KFile

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • 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.5
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