]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/kitemviews/kfileitemmodel.cpp
KFileItemModel: emit itemsChanged() signal
[dolphin.git] / src / kitemviews / kfileitemmodel.cpp
index ddc56209b8df72e1f319838640cb2e17f0dfd6a0..ff0c4a02d9d0394832df493d42be6e0bd4392ded 100644 (file)
 #include "kfileitemmodel.h"
 
 #include <KDirLister>
+#include <KDirModel>
 #include <KLocale>
 #include <KStringHandler>
 #include <KDebug>
 
+#include <QMimeData>
 #include <QTimer>
 
 #define KFILEITEMMODEL_DEBUG
@@ -43,7 +45,6 @@ KFileItemModel::KFileItemModel(KDirLister* dirLister, QObject* parent) :
     m_minimumUpdateIntervalTimer(0),
     m_maximumUpdateIntervalTimer(0),
     m_pendingItemsToInsert(),
-    m_pendingItemsToDelete(),
     m_rootExpansionLevel(-1)
 {
     resetRoles();
@@ -56,6 +57,7 @@ KFileItemModel::KFileItemModel(KDirLister* dirLister, QObject* parent) :
     connect(dirLister, SIGNAL(completed()), this, SLOT(slotCompleted()));
     connect(dirLister, SIGNAL(newItems(KFileItemList)), this, SLOT(slotNewItems(KFileItemList)));
     connect(dirLister, SIGNAL(itemsDeleted(KFileItemList)), this, SLOT(slotItemsDeleted(KFileItemList)));
+    connect(dirLister, SIGNAL(refreshItems(QList<QPair<KFileItem,KFileItem> >)), this, SLOT(slotRefreshItems(QList<QPair<KFileItem,KFileItem> >)));
     connect(dirLister, SIGNAL(clear()), this, SLOT(slotClear()));
     connect(dirLister, SIGNAL(clear(KUrl)), this, SLOT(slotClear(KUrl)));
 
@@ -65,14 +67,14 @@ KFileItemModel::KFileItemModel(KDirLister* dirLister, QObject* parent) :
     m_minimumUpdateIntervalTimer = new QTimer(this);
     m_minimumUpdateIntervalTimer->setInterval(1000);
     m_minimumUpdateIntervalTimer->setSingleShot(true);
-    connect(m_minimumUpdateIntervalTimer, SIGNAL(timeout()), this, SLOT(dispatchPendingItems()));
+    connect(m_minimumUpdateIntervalTimer, SIGNAL(timeout()), this, SLOT(dispatchPendingItemsToInsert()));
 
     // For slow KIO-slaves like used for searching it makes sense to show results periodically even
     // before the completed() or canceled() signal has been emitted.
     m_maximumUpdateIntervalTimer = new QTimer(this);
     m_maximumUpdateIntervalTimer->setInterval(2000);
     m_maximumUpdateIntervalTimer->setSingleShot(true);
-    connect(m_maximumUpdateIntervalTimer, SIGNAL(timeout()), this, SLOT(dispatchPendingItems()));
+    connect(m_maximumUpdateIntervalTimer, SIGNAL(timeout()), this, SLOT(dispatchPendingItemsToInsert()));
 
     Q_ASSERT(m_minimumUpdateIntervalTimer->interval() <= m_maximumUpdateIntervalTimer->interval());
 }
@@ -132,6 +134,68 @@ bool KFileItemModel::supportsSorting() const
     return true;
 }
 
+QMimeData* KFileItemModel::createMimeData(const QSet<int>& indexes) const
+{
+    QMimeData* data = new QMimeData();
+
+    // The following code has been taken from KDirModel::mimeData()
+    // (kdelibs/kio/kio/kdirmodel.cpp)
+    // Copyright (C) 2006 David Faure <faure@kde.org>
+    KUrl::List urls;
+    KUrl::List mostLocalUrls;
+    bool canUseMostLocalUrls = true;
+
+    QSetIterator<int> it(indexes);
+    while (it.hasNext()) {
+        const int index = it.next();
+        const KFileItem item = fileItem(index);
+        if (!item.isNull()) {
+            urls << item.url();
+
+            bool isLocal;
+            mostLocalUrls << item.mostLocalUrl(isLocal);
+            if (!isLocal) {
+                canUseMostLocalUrls = false;
+            }
+        }
+    }
+
+    const bool different = canUseMostLocalUrls && mostLocalUrls != urls;
+    urls = KDirModel::simplifiedUrlList(urls); // TODO: Check if we still need KDirModel for this in KDE 5.0
+    if (different) {
+        mostLocalUrls = KDirModel::simplifiedUrlList(mostLocalUrls);
+        urls.populateMimeData(mostLocalUrls, data);
+    } else {
+        urls.populateMimeData(data);
+    }
+
+    return data;
+}
+
+int KFileItemModel::indexForKeyboardSearch(const QString& text, int startFromIndex) const
+{
+    startFromIndex = qMax(0, startFromIndex);
+    for (int i = startFromIndex; i < count(); i++) {
+        if (data(i)["name"].toString().startsWith(text, Qt::CaseInsensitive)) {
+            kDebug() << data(i)["name"].toString();
+            return i;
+        }
+    }
+    for (int i = 0; i < startFromIndex; i++) {
+        if (data(i)["name"].toString().startsWith(text, Qt::CaseInsensitive)) {
+            kDebug() << data(i)["name"].toString();
+            return i;
+        }
+    }
+    return -1;
+}
+
+bool KFileItemModel::supportsDropping(int index) const
+{
+    const KFileItem item = fileItem(index);
+    return item.isNull() ? false : item.isDir();
+}
+
 KFileItem KFileItemModel::fileItem(int index) const
 {
     if (index >= 0 && index < count()) {
@@ -141,13 +205,31 @@ KFileItem KFileItemModel::fileItem(int index) const
     return KFileItem();
 }
 
+KFileItem KFileItemModel::fileItem(const KUrl& url) const
+{
+    const int index = m_items.value(url, -1);
+    if (index >= 0) {
+        return m_sortedItems.at(index);
+    }
+    return KFileItem();
+}
+
 int KFileItemModel::index(const KFileItem& item) const
 {
     if (item.isNull()) {
         return -1;
     }
 
-    return m_items.value(item, -1);
+    return m_items.value(item.url(), -1);
+}
+
+KUrl KFileItemModel::rootDirectory() const
+{
+    const KDirLister* dirLister = m_dirLister.data();
+    if (dirLister) {
+        return dirLister->url();
+    }
+    return KUrl();
 }
 
 void KFileItemModel::clear()
@@ -288,7 +370,7 @@ void KFileItemModel::onSortRoleChanged(const QByteArray& current, const QByteArr
     int index = 0;
     foreach (const KFileItem& item, sortedItems) {
         m_sortedItems.append(item);
-        m_items.insert(item, index);
+        m_items.insert(item.url(), index);
         m_data.append(retrieveData(item));
 
         ++index;
@@ -305,7 +387,7 @@ void KFileItemModel::slotCompleted()
         return;
     }
 
-    dispatchPendingItems();
+    dispatchPendingItemsToInsert();
     m_minimumUpdateIntervalTimer->start();
 }
 
@@ -313,15 +395,11 @@ void KFileItemModel::slotCanceled()
 {
     m_minimumUpdateIntervalTimer->stop();
     m_maximumUpdateIntervalTimer->stop();
-    dispatchPendingItems();
+    dispatchPendingItemsToInsert();
 }
 
 void KFileItemModel::slotNewItems(const KFileItemList& items)
 {
-    if (!m_pendingItemsToDelete.isEmpty()) {
-        removeItems(m_pendingItemsToDelete);
-        m_pendingItemsToDelete.clear();
-    }
     m_pendingItemsToInsert.append(items);
 
     if (useMaximumUpdateInterval() && !m_maximumUpdateIntervalTimer->isActive()) {
@@ -337,7 +415,56 @@ void KFileItemModel::slotItemsDeleted(const KFileItemList& items)
         insertItems(m_pendingItemsToInsert);
         m_pendingItemsToInsert.clear();
     }
-    m_pendingItemsToDelete.append(items);
+    removeItems(items);
+}
+
+void KFileItemModel::slotRefreshItems(const QList<QPair<KFileItem, KFileItem> >& items)
+{
+    Q_ASSERT(!items.isEmpty());
+#ifdef KFILEITEMMODEL_DEBUG
+    kDebug() << "Refreshing" << items.count() << "items";
+#endif
+
+    // Get the indexes of all items that have been refreshed
+    QList<int> indexes;
+    indexes.reserve(items.count());
+
+    QListIterator<QPair<KFileItem, KFileItem> > it(items);
+    while (it.hasNext()) {
+        const QPair<KFileItem, KFileItem>& itemPair = it.next();
+        const int index = m_items.value(itemPair.second.url(), -1);
+        if (index >= 0) {
+            indexes.append(index);
+        }
+    }
+
+    // Extract the item-ranges out of the changed indexes
+    qSort(indexes);
+
+    KItemRangeList itemRangeList;
+    int rangeIndex = 0;
+    int rangeCount = 1;
+    int previousIndex = indexes.at(0);
+
+    const int maxIndex = indexes.count() - 1;
+    for (int i = 1; i <= maxIndex; ++i) {
+        const int currentIndex = indexes.at(i);
+        if (currentIndex == previousIndex + 1) {
+            ++rangeCount;
+        } else {
+            itemRangeList.append(KItemRange(rangeIndex, rangeCount));
+
+            rangeIndex = currentIndex;
+            rangeCount = 1;
+        }
+        previousIndex = currentIndex;
+    }
+
+    if (rangeCount > 0) {
+        itemRangeList.append(KItemRange(rangeIndex, rangeCount));
+    }
+
+    emit itemsChanged(itemRangeList, QSet<QByteArray>());
 }
 
 void KFileItemModel::slotClear()
@@ -349,7 +476,6 @@ void KFileItemModel::slotClear()
     m_minimumUpdateIntervalTimer->stop();
     m_maximumUpdateIntervalTimer->stop();
     m_pendingItemsToInsert.clear();
-    m_pendingItemsToDelete.clear();
 
     m_rootExpansionLevel = -1;
 
@@ -367,16 +493,11 @@ void KFileItemModel::slotClear(const KUrl& url)
     Q_UNUSED(url);
 }
 
-void KFileItemModel::dispatchPendingItems()
+void KFileItemModel::dispatchPendingItemsToInsert()
 {
     if (!m_pendingItemsToInsert.isEmpty()) {
-        Q_ASSERT(m_pendingItemsToDelete.isEmpty());
         insertItems(m_pendingItemsToInsert);
         m_pendingItemsToInsert.clear();
-    } else if (!m_pendingItemsToDelete.isEmpty()) {
-        Q_ASSERT(m_pendingItemsToInsert.isEmpty());
-        removeItems(m_pendingItemsToDelete);
-        m_pendingItemsToDelete.clear();
     }
 }
 
@@ -442,7 +563,7 @@ void KFileItemModel::insertItems(const KFileItemList& items)
     // The indexes of all m_items must be adjusted, not only the index
     // of the new items
     for (int i = 0; i < m_sortedItems.count(); ++i) {
-        m_items.insert(m_sortedItems.at(i), i);
+        m_items.insert(m_sortedItems.at(i).url(), i);
     }
 
     itemRanges << KItemRange(insertedAtIndex, insertedCount);
@@ -477,7 +598,7 @@ void KFileItemModel::removeItems(const KFileItemList& items)
     foreach (const KFileItem& itemToRemove, sortedItems) {
         const int previousTargetIndex = targetIndex;
         while (targetIndex < m_sortedItems.count()) {
-            if (m_sortedItems.at(targetIndex) == itemToRemove) {
+            if (m_sortedItems.at(targetIndex).url() == itemToRemove.url()) {
                 break;
             }
             ++targetIndex;
@@ -504,7 +625,7 @@ void KFileItemModel::removeItems(const KFileItemList& items)
     // Delete the items
     for (int i = indexesToRemove.count() - 1; i >= 0; --i) {
         const int indexToRemove = indexesToRemove.at(i);
-        m_items.remove(m_sortedItems.at(indexToRemove));
+        m_items.remove(m_sortedItems.at(indexToRemove).url());
         m_sortedItems.removeAt(indexToRemove);
         m_data.removeAt(indexToRemove);
     }
@@ -512,7 +633,7 @@ void KFileItemModel::removeItems(const KFileItemList& items)
     // The indexes of all m_items must be adjusted, not only the index
     // of the removed items
     for (int i = 0; i < m_sortedItems.count(); ++i) {
-        m_items.insert(m_sortedItems.at(i), i);
+        m_items.insert(m_sortedItems.at(i).url(), i);
     }
 
     if (count() <= 0) {
@@ -831,7 +952,7 @@ int KFileItemModel::expansionLevelsCompare(const KFileItem& a, const KFileItem&
     if (index > maxIndex) {
         index = maxIndex;
     }
-    while (pathA.at(index) != QLatin1Char('/') && index > 0) {
+    while ((pathA.at(index) != QLatin1Char('/') || pathB.at(index) != QLatin1Char('/')) && index > 0) {
         --index;
     }