]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/kitemviews/kfileitemmodel.cpp
Re-organize the code that compares expanded items
[dolphin.git] / src / kitemviews / kfileitemmodel.cpp
index ab39e55e592f8af0b2aa234b5b52f6b4551b492a..60fc27546bb435e5d73f7378be41334cd50eec49 100644 (file)
@@ -1,5 +1,6 @@
 /***************************************************************************
  *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *   Copyright (C) 2013 by Frank Reininghaus <frank78ac@googlemail.com>    *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
  *   it under the terms of the GNU General Public License as published by  *
@@ -987,6 +988,7 @@ void KFileItemModel::insertItems(const KFileItemList& items)
     // The indexes of all m_items must be adjusted, not only the index
     // of the new items
     const int itemDataCount = m_itemData.count();
+    m_items.reserve(itemDataCount);
     for (int i = 0; i < itemDataCount; ++i) {
         m_items.insert(m_itemData.at(i)->item.url(), i);
     }
@@ -999,7 +1001,7 @@ void KFileItemModel::insertItems(const KFileItemList& items)
 #endif
 }
 
-static KItemRangeList sortedIndexesToKItemRangeList(const QList<int> sortedNumbers)
+static KItemRangeList sortedIndexesToKItemRangeList(const QList<int>& sortedNumbers)
 {
     if (sortedNumbers.empty()) {
         return KItemRangeList();
@@ -1031,10 +1033,6 @@ static KItemRangeList sortedIndexesToKItemRangeList(const QList<int> sortedNumbe
 
 void KFileItemModel::removeItems(const KFileItemList& items)
 {
-    if (items.isEmpty()) {
-        return;
-    }
-
 #ifdef KFILEITEMMODEL_DEBUG
     kDebug() << "Removing " << items.count() << "items";
 #endif
@@ -1059,11 +1057,13 @@ void KFileItemModel::removeItems(const KFileItemList& items)
             ItemData* data = m_itemData.at(index);
             delete data;
             m_itemData[index] = 0;
-        } else {
-            kWarning() << "Item that should be deleted has not been found!";
         }
     }
 
+    if (indexesToRemove.isEmpty()) {
+        return;
+    }
+
     std::sort(indexesToRemove.begin(), indexesToRemove.end());
 
     // Step 2: Remove the ItemData pointers from the list m_itemData.
@@ -1074,14 +1074,15 @@ void KFileItemModel::removeItems(const KFileItemList& items)
 
     const int oldItemDataCount = m_itemData.count();
     while (source < oldItemDataCount) {
-        if (nextRange < itemRanges.count() - 1 && source == itemRanges.at(nextRange).index) {
+        m_itemData[target] = m_itemData[source];
+        ++target;
+        ++source;
+
+        if (nextRange < itemRanges.count() && source == itemRanges.at(nextRange).index) {
             // Skip the items in the next removed range.
             source += itemRanges.at(nextRange).count;
             ++nextRange;
         }
-        m_itemData[target] = m_itemData[source];
-        ++target;
-        ++source;
     }
 
     m_itemData.erase(m_itemData.end() - indexesToRemove.count(), m_itemData.end());
@@ -1338,11 +1339,34 @@ bool KFileItemModel::lessThan(const ItemData* a, const ItemData* b) const
 {
     int result = 0;
 
-    if (m_expandedParentsCountRoot >= 0) {
-        result = expandedParentsCountCompare(a, b);
-        if (result != 0) {
-            // The items have parents with different expansion levels
-            return (sortOrder() == Qt::AscendingOrder) ? result < 0 : result > 0;
+    if (m_expandedParentsCountRoot >= 0 && a->parent != b->parent) {
+        const int expansionLevelA = a->values.value("expandedParentsCount").toInt();
+        const int expansionLevelB = b->values.value("expandedParentsCount").toInt();
+
+        // If b has a higher expansion level than a, check if a is a parent
+        // of b, and make sure that both expansion levels are equal otherwise.
+        for (int i = expansionLevelB; i > expansionLevelA; --i) {
+            if (b->parent == a) {
+                return true;
+            }
+            b = b->parent;
+        }
+
+        // If a has a higher expansion level than a, check if b is a parent
+        // of a, and make sure that both expansion levels are equal otherwise.
+        for (int i = expansionLevelA; i > expansionLevelB; --i) {
+            if (a->parent == b) {
+                return false;
+            }
+            a = a->parent;
+        }
+
+        Q_ASSERT(a->values.value("expandedParentsCount").toInt() == b->values.value("expandedParentsCount").toInt());
+
+        // Compare the last parents of a and b which are different.
+        while (a->parent != b->parent) {
+            a = a->parent;
+            b = b->parent;
         }
     }
 
@@ -1523,88 +1547,6 @@ int KFileItemModel::stringCompare(const QString& a, const QString& b) const
                             : QString::compare(a, b, Qt::CaseSensitive);
 }
 
-int KFileItemModel::expandedParentsCountCompare(const ItemData* a, const ItemData* b) const
-{
-    const KUrl urlA = a->item.url();
-    const KUrl urlB = b->item.url();
-    if (urlA.directory() == urlB.directory()) {
-        // Both items have the same directory as parent
-        return 0;
-    }
-
-    // Check whether one item is the parent of the other item
-    if (urlA.isParentOf(urlB)) {
-        return (sortOrder() == Qt::AscendingOrder) ? -1 : +1;
-    } else if (urlB.isParentOf(urlA)) {
-        return (sortOrder() == Qt::AscendingOrder) ? +1 : -1;
-    }
-
-    // Determine the maximum common path of both items and
-    // remember the index in 'index'
-    const QString pathA = urlA.path();
-    const QString pathB = urlB.path();
-
-    const int maxIndex = qMin(pathA.length(), pathB.length()) - 1;
-    int index = 0;
-    while (index <= maxIndex && pathA.at(index) == pathB.at(index)) {
-        ++index;
-    }
-    if (index > maxIndex) {
-        index = maxIndex;
-    }
-    while (index > 0 && (pathA.at(index) != QLatin1Char('/') || pathB.at(index) != QLatin1Char('/'))) {
-        --index;
-    }
-
-    // Determine the first sub-path after the common path and
-    // check whether it represents a directory or already a file
-    bool isDirA = true;
-    const QString subPathA = subPath(a->item, pathA, index, &isDirA);
-    bool isDirB = true;
-    const QString subPathB = subPath(b->item, pathB, index, &isDirB);
-
-    if (m_sortDirsFirst || m_sortRole == SizeRole) {
-        if (isDirA && !isDirB) {
-            return (sortOrder() == Qt::AscendingOrder) ? -1 : +1;
-        } else if (!isDirA && isDirB) {
-            return (sortOrder() == Qt::AscendingOrder) ? +1 : -1;
-        }
-    }
-
-    // Compare the items of the parents that represent the first
-    // different path after the common path.
-    const QString parentPathA = pathA.left(index) + subPathA;
-    const QString parentPathB = pathB.left(index) + subPathB;
-
-    const ItemData* parentA = a;
-    while (parentA && parentA->item.url().path() != parentPathA) {
-        parentA = parentA->parent;
-    }
-
-    const ItemData* parentB = b;
-    while (parentB && parentB->item.url().path() != parentPathB) {
-        parentB = parentB->parent;
-    }
-
-    if (parentA && parentB) {
-        return sortRoleCompare(parentA, parentB);
-    }
-
-    kWarning() << "Child items without parent detected:" << a->item.url() << b->item.url();
-    return QString::compare(urlA.url(), urlB.url(), Qt::CaseSensitive);
-}
-
-QString KFileItemModel::subPath(const KFileItem& item,
-                                const QString& itemPath,
-                                int start,
-                                bool* isDir) const
-{
-    Q_ASSERT(isDir);
-    const int pathIndex = itemPath.indexOf('/', start + 1);
-    *isDir = (pathIndex > 0) || item.isDir();
-    return itemPath.mid(start, pathIndex - start);
-}
-
 bool KFileItemModel::useMaximumUpdateInterval() const
 {
     return !m_dirLister->url().isLocalFile();
@@ -2018,12 +1960,12 @@ void KFileItemModel::determineMimeTypes(const KFileItemList& items, int timeout)
 
 bool KFileItemModel::isConsistent() const
 {
-    // Check that m_items and m_itemData are consistent, and that the items are sorted.
     if (m_items.count() != m_itemData.count()) {
         return false;
     }
 
     for (int i = 0; i < count(); ++i) {
+        // Check if m_items and m_itemData are consistent.
         const KFileItem item = fileItem(i);
         if (item.isNull()) {
             qWarning() << "Item" << i << "is null";
@@ -2036,11 +1978,28 @@ bool KFileItemModel::isConsistent() const
             return false;
         }
 
+        // Check if the items are sorted correctly.
         if (i > 0 && !lessThan(m_itemData.at(i - 1), m_itemData.at(i))) {
             qWarning() << "The order of items" << i - 1 << "and" << i << "is wrong:"
                 << fileItem(i - 1) << fileItem(i);
             return false;
         }
+
+        // Check if all parent-child relationships are consistent.
+        const ItemData* data = m_itemData.at(i);
+        const ItemData* parent = data->parent;
+        if (parent) {
+            if (data->values.value("expandedParentsCount").toInt() != parent->values.value("expandedParentsCount").toInt() + 1) {
+                qWarning() << "expandedParentsCount is inconsistent for parent" << parent->item << "and child" << data->item;
+                return false;
+            }
+
+            const int parentIndex = index(parent->item);
+            if (parentIndex >= i) {
+                qWarning() << "Index" << parentIndex << "of parent" << parent->item << "is not smaller than index" << i << "of child" << data->item;
+                return false;
+            }
+        }
     }
 
     return true;