]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/kitemviews/kfileitemmodel.cpp
Compact view: Padding- and margin-improvements for grouped alignments
[dolphin.git] / src / kitemviews / kfileitemmodel.cpp
index 3fd40e9d453c35c2949f2182fba2062655430322..ede3c36239ab2997fd18560eac3ffa39ad048919 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <KDirLister>
 #include <KDirModel>
+#include <KGlobalSettings>
 #include <KLocale>
 #include <KStringHandler>
 #include <KDebug>
@@ -33,7 +34,7 @@
 KFileItemModel::KFileItemModel(KDirLister* dirLister, QObject* parent) :
     KItemModelBase("name", parent),
     m_dirLister(dirLister),
-    m_naturalSorting(true),
+    m_naturalSorting(KGlobalSettings::naturalSorting()),
     m_sortFoldersFirst(true),
     m_sortRole(NameRole),
     m_roles(),
@@ -49,7 +50,7 @@ KFileItemModel::KFileItemModel(KDirLister* dirLister, QObject* parent) :
     m_pendingItemsToInsert(),
     m_pendingEmitLoadingCompleted(false),
     m_groups(),
-    m_rootExpansionLevel(UninitializedRootExpansionLevel),
+    m_expandedParentsCountRoot(UninitializedExpandedParentsCountRoot),
     m_expandedUrls(),
     m_urlsToExpand()
 {
@@ -63,7 +64,7 @@ KFileItemModel::KFileItemModel(KDirLister* dirLister, QObject* parent) :
     Q_ASSERT(dirLister);
 
     connect(dirLister, SIGNAL(canceled()), this, SLOT(slotCanceled()));
-    connect(dirLister, SIGNAL(completed()), this, SLOT(slotCompleted()));
+    connect(dirLister, SIGNAL(completed(KUrl)), 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> >)));
@@ -95,6 +96,8 @@ KFileItemModel::KFileItemModel(KDirLister* dirLister, QObject* parent) :
     connect(m_resortAllItemsTimer, SIGNAL(timeout()), this, SLOT(resortAllItems()));
 
     Q_ASSERT(m_minimumUpdateIntervalTimer->interval() <= m_maximumUpdateIntervalTimer->interval());
+    
+    connect(KGlobalSettings::self(), SIGNAL(naturalSortingChanged()), this, SLOT(slotNaturalSortingChanged()));
 }
 
 KFileItemModel::~KFileItemModel()
@@ -183,6 +186,20 @@ bool KFileItemModel::showHiddenFiles() const
     return dirLister ? dirLister->showingDotFiles() : false;
 }
 
+void KFileItemModel::setShowFoldersOnly(bool enabled)
+{
+    KDirLister* dirLister = m_dirLister.data();
+    if (dirLister) {
+        dirLister->setDirOnlyMode(enabled);
+    }
+}
+
+bool KFileItemModel::showFoldersOnly() const
+{
+    KDirLister* dirLister = m_dirLister.data();
+    return dirLister ? dirLister->dirOnlyMode() : false;
+}
+
 QMimeData* KFileItemModel::createMimeData(const QSet<int>& indexes) const
 {
     QMimeData* data = new QMimeData();
@@ -240,7 +257,7 @@ int KFileItemModel::indexForKeyboardSearch(const QString& text, int startFromInd
 bool KFileItemModel::supportsDropping(int index) const
 {
     const KFileItem item = fileItem(index);
-    return item.isNull() ? false : item.isDir();
+    return item.isNull() ? false : item.isDir() || item.isDesktopFile();
 }
 
 QString KFileItemModel::roleDescription(const QByteArray& role) const
@@ -248,22 +265,22 @@ QString KFileItemModel::roleDescription(const QByteArray& role) const
     QString descr;
 
     switch (roleIndex(role)) {
-    case NameRole:           descr = i18nc("@item:intable", "Name"); break;
-    case SizeRole:           descr = i18nc("@item:intable", "Size"); break;
-    case DateRole:           descr = i18nc("@item:intable", "Date"); break;
-    case PermissionsRole:    descr = i18nc("@item:intable", "Permissions"); break;
-    case OwnerRole:          descr = i18nc("@item:intable", "Owner"); break;
-    case GroupRole:          descr = i18nc("@item:intable", "Group"); break;
-    case TypeRole:           descr = i18nc("@item:intable", "Type"); break;
-    case DestinationRole:    descr = i18nc("@item:intable", "Destination"); break;
-    case PathRole:           descr = i18nc("@item:intable", "Path"); break;
-    case CommentRole:        descr = i18nc("@item:intable", "Comment"); break;
-    case TagsRole:           descr = i18nc("@item:intable", "Tags"); break;
-    case RatingRole:         descr = i18nc("@item:intable", "Rating"); break;
-    case NoRole:             break;
-    case IsDirRole:          break;
-    case IsExpandedRole:     break;
-    case ExpansionLevelRole: break;
+    case NameRole:        descr = i18nc("@item:intable", "Name"); break;
+    case SizeRole:        descr = i18nc("@item:intable", "Size"); break;
+    case DateRole:        descr = i18nc("@item:intable", "Date"); break;
+    case PermissionsRole: descr = i18nc("@item:intable", "Permissions"); break;
+    case OwnerRole:       descr = i18nc("@item:intable", "Owner"); break;
+    case GroupRole:       descr = i18nc("@item:intable", "Group"); break;
+    case TypeRole:        descr = i18nc("@item:intable", "Type"); break;
+    case DestinationRole: descr = i18nc("@item:intable", "Destination"); break;
+    case PathRole:        descr = i18nc("@item:intable", "Path"); break;
+    case CommentRole:     descr = i18nc("@item:intable", "Comment"); break;
+    case TagsRole:        descr = i18nc("@item:intable", "Tags"); break;
+    case RatingRole:      descr = i18nc("@item:intable", "Rating"); break;
+    case NoRole:          break;
+    case IsDirRole:       break;
+    case IsExpandedRole:  break;
+    case ExpandedParentsCountRole: break;
     default:                 Q_ASSERT(false); break;
     }
 
@@ -278,22 +295,22 @@ QList<QPair<int, QVariant> > KFileItemModel::groups() const
         timer.start();
 #endif
         switch (roleIndex(sortRole())) {
-        case NameRole:           m_groups = nameRoleGroups(); break;
-        case SizeRole:           m_groups = sizeRoleGroups(); break;
-        case DateRole:           m_groups = dateRoleGroups(); break;
-        case PermissionsRole:    m_groups = permissionRoleGroups(); break;
-        case OwnerRole:          m_groups = genericStringRoleGroups("owner"); break;
-        case GroupRole:          m_groups = genericStringRoleGroups("group"); break;
-        case TypeRole:           m_groups = genericStringRoleGroups("type"); break;
-        case DestinationRole:    m_groups = genericStringRoleGroups("destination"); break;
-        case PathRole:           m_groups = genericStringRoleGroups("path"); break;
-        case CommentRole:        m_groups = genericStringRoleGroups("comment"); break;
-        case TagsRole:           m_groups = genericStringRoleGroups("tags"); break;
-        case RatingRole:         m_groups = ratingRoleGroups(); break;
-        case NoRole:             break;
-        case IsDirRole:          break;
-        case IsExpandedRole:     break;
-        case ExpansionLevelRole: break;
+        case NameRole:        m_groups = nameRoleGroups(); break;
+        case SizeRole:        m_groups = sizeRoleGroups(); break;
+        case DateRole:        m_groups = dateRoleGroups(); break;
+        case PermissionsRole: m_groups = permissionRoleGroups(); break;
+        case OwnerRole:       m_groups = genericStringRoleGroups("owner"); break;
+        case GroupRole:       m_groups = genericStringRoleGroups("group"); break;
+        case TypeRole:        m_groups = genericStringRoleGroups("type"); break;
+        case DestinationRole: m_groups = genericStringRoleGroups("destination"); break;
+        case PathRole:        m_groups = genericStringRoleGroups("path"); break;
+        case CommentRole:     m_groups = genericStringRoleGroups("comment"); break;
+        case TagsRole:        m_groups = genericStringRoleGroups("tags"); break;
+        case RatingRole:      m_groups = ratingRoleGroups(); break;
+        case NoRole:          break;
+        case IsDirRole:       break;
+        case IsExpandedRole:  break;
+        case ExpandedParentsCountRole: break;
         default:                 Q_ASSERT(false); break;
         }
 
@@ -358,8 +375,8 @@ void KFileItemModel::setRoles(const QSet<QByteArray>& roles)
     m_roles = roles;
 
     if (count() > 0) {
-        const bool supportedExpanding = m_requestRole[ExpansionLevelRole];
-        const bool willSupportExpanding = roles.contains("expansionLevel");
+        const bool supportedExpanding = m_requestRole[ExpandedParentsCountRole];
+        const bool willSupportExpanding = roles.contains("expandedParentsCount");
         if (supportedExpanding && !willSupportExpanding) {
             // No expanding is supported anymore. Take care to delete all items that have an expansion level
             // that is not 0 (and hence are part of an expanded item).
@@ -422,9 +439,9 @@ bool KFileItemModel::setExpanded(int index, bool expanded)
         }
 
         KFileItemList itemsToRemove;
-        const int expansionLevel = data(index)["expansionLevel"].toInt();
+        const int expandedParentsCount = data(index)["expandedParentsCount"].toInt();
         ++index;
-        while (index < count() && data(index)["expansionLevel"].toInt() > expansionLevel) {
+        while (index < count() && data(index)["expandedParentsCount"].toInt() > expandedParentsCount) {
             itemsToRemove.append(m_itemData.at(index)->item);
             ++index;
         }
@@ -451,6 +468,17 @@ bool KFileItemModel::isExpandable(int index) const
     return false;
 }
 
+int KFileItemModel::expandedParentsCount(int index) const
+{
+    if (index >= 0 && index < count()) {
+        const int parentsCount = m_itemData.at(index)->values.value("expandedParentsCount").toInt();
+        if (parentsCount > 0) {
+            return parentsCount;
+        }
+    }
+    return 0;
+}
+
 QSet<KUrl> KFileItemModel::expandedUrls() const
 {
     return m_expandedUrls;
@@ -461,29 +489,24 @@ void KFileItemModel::restoreExpandedUrls(const QSet<KUrl>& urls)
     m_urlsToExpand = urls;
 }
 
-void KFileItemModel::setExpanded(const QSet<KUrl>& urls)
+void KFileItemModel::expandParentItems(const KUrl& url)
 {
     const KDirLister* dirLister = m_dirLister.data();
     if (!dirLister) {
         return;
     }
 
-    const int pos = dirLister->url().url().length();
+    const int pos = dirLister->url().path().length();
 
-    // Assure that each sub-path of the URLs that should be
-    // expanded is added to m_urlsToExpand too. KDirLister
+    // Assure that each sub-path of the URL that should be
+    // expanded is added to m_urlsToExpand. KDirLister
     // does not care whether the parent-URL has already been
     // expanded.
-    QSetIterator<KUrl> it1(urls);
-    while (it1.hasNext()) {
-        const KUrl& url = it1.next();
-
-        KUrl urlToExpand = dirLister->url();
-        const QStringList subDirs = url.url().mid(pos).split(QDir::separator());
-        for (int i = 0; i < subDirs.count(); ++i) {
-            urlToExpand.addPath(subDirs.at(i));
-            m_urlsToExpand.insert(urlToExpand);
-        }
+    KUrl urlToExpand = dirLister->url();
+    const QStringList subDirs = url.path().mid(pos).split(QDir::separator());
+    for (int i = 0; i < subDirs.count() - 1; ++i) {
+        urlToExpand.addPath(subDirs.at(i));
+        m_urlsToExpand.insert(urlToExpand);
     }
 
     // KDirLister::open() must called at least once to trigger an initial
@@ -675,7 +698,7 @@ void KFileItemModel::slotNewItems(const KFileItemList& items)
 {
     Q_ASSERT(!items.isEmpty());
 
-    if (m_requestRole[ExpansionLevelRole] && m_rootExpansionLevel >= 0) {
+    if (m_requestRole[ExpandedParentsCountRole] && m_expandedParentsCountRoot >= 0) {
         // To be able to compare whether the new items may be inserted as children
         // of a parent item the pending items must be added to the model first.
         dispatchPendingItemsToInsert();
@@ -735,7 +758,7 @@ void KFileItemModel::slotItemsDeleted(const KFileItemList& items)
     dispatchPendingItemsToInsert();
 
     KFileItemList itemsToRemove = items;
-    if (m_requestRole[ExpansionLevelRole] && m_rootExpansionLevel >= 0) {
+    if (m_requestRole[ExpandedParentsCountRole] && m_expandedParentsCountRoot >= 0) {
         // Assure that removing a parent item also results in removing all children
         foreach (const KFileItem& item, items) {
             itemsToRemove.append(childItems(item));
@@ -830,7 +853,7 @@ void KFileItemModel::slotClear()
     m_resortAllItemsTimer->stop();
     m_pendingItemsToInsert.clear();
 
-    m_rootExpansionLevel = UninitializedRootExpansionLevel;
+    m_expandedParentsCountRoot = UninitializedExpandedParentsCountRoot;
 
     const int removedCount = m_itemData.count();
     if (removedCount > 0) {
@@ -848,6 +871,12 @@ void KFileItemModel::slotClear(const KUrl& url)
     Q_UNUSED(url);
 }
 
+void KFileItemModel::slotNaturalSortingChanged()
+{
+    m_naturalSorting = KGlobalSettings::naturalSorting();
+    resortAllItems();
+}
+
 void KFileItemModel::dispatchPendingItemsToInsert()
 {
     if (!m_pendingItemsToInsert.isEmpty()) {
@@ -1013,7 +1042,7 @@ void KFileItemModel::removeItems(const KFileItemList& items)
     }
 
     if (count() <= 0) {
-        m_rootExpansionLevel = UninitializedRootExpansionLevel;
+        m_expandedParentsCountRoot = UninitializedExpandedParentsCountRoot;
     }
 
     itemRanges << KItemRange(removedAtIndex, removedCount);
@@ -1031,8 +1060,8 @@ QList<KFileItemModel::ItemData*> KFileItemModel::createItemDataList(const KFileI
         itemData->values = retrieveData(item);
         itemData->parent = 0;
 
-        const bool determineParent = m_requestRole[ExpansionLevelRole]
-                                     && itemData->values["expansionLevel"].toInt() > 0;
+        const bool determineParent = m_requestRole[ExpandedParentsCountRole]
+                                     && itemData->values["expandedParentsCount"].toInt() > 0;
         if (determineParent) {
             KUrl parentUrl = item.url().upUrl();
             parentUrl.adjustPath(KUrl::RemoveTrailingSlash);
@@ -1057,17 +1086,17 @@ void KFileItemModel::removeExpandedItems()
     const int maxIndex = m_itemData.count() - 1;
     for (int i = 0; i <= maxIndex; ++i) {
         const ItemData* itemData = m_itemData.at(i);
-        if (itemData->values.value("expansionLevel").toInt() > 0) {
+        if (itemData->values.value("expandedParentsCount").toInt() > 0) {
             expandedItems.append(itemData->item);
         }
     }
 
-    // The m_rootExpansionLevel may not get reset before all items with
-    // a bigger expansionLevel have been removed.
-    Q_ASSERT(m_rootExpansionLevel >= 0);
+    // The m_expandedParentsCountRoot may not get reset before all items with
+    // a bigger count have been removed.
+    Q_ASSERT(m_expandedParentsCountRoot >= 0);
     removeItems(expandedItems);
 
-    m_rootExpansionLevel = UninitializedRootExpansionLevel;
+    m_expandedParentsCountRoot = UninitializedExpandedParentsCountRoot;
     m_expandedUrls.clear();
 }
 
@@ -1097,11 +1126,35 @@ KFileItemModel::Role KFileItemModel::roleIndex(const QByteArray& role) const
         rolesHash.insert("isDir", IsDirRole);
         rolesHash.insert("isExpanded", IsExpandedRole);
         rolesHash.insert("isExpandable", IsExpandableRole);
-        rolesHash.insert("expansionLevel", ExpansionLevelRole);
+        rolesHash.insert("expandedParentsCount", ExpandedParentsCountRole);
     }
     return rolesHash.value(role, NoRole);
 }
 
+QByteArray KFileItemModel::roleByteArray(Role role) const
+{
+    static const char* const roles[RolesCount] = {
+        0, // NoRole
+        "name",
+        "size",
+        "date",
+        "permissions",
+        "owner",
+        "group",
+        "type",
+        "destination",
+        "path",
+        "comment",
+        "tags",
+        "rating",
+        "isDir",
+        "isExpanded",
+        "isExpandable",
+        "expandedParentsCount"
+    };
+    return roles[role];
+}
+
 QHash<QByteArray, QVariant> KFileItemModel::retrieveData(const KFileItem& item) const
 {    
     // It is important to insert only roles that are fast to retrieve. E.g.
@@ -1177,32 +1230,28 @@ QHash<QByteArray, QVariant> KFileItemModel::retrieveData(const KFileItem& item)
         data.insert("isExpandable", item.isDir() && item.url() == item.targetUrl());
     }
 
-    if (m_requestRole[ExpansionLevelRole]) {
-        if (m_rootExpansionLevel == UninitializedRootExpansionLevel && m_dirLister.data()) {
+    if (m_requestRole[ExpandedParentsCountRole]) {
+        if (m_expandedParentsCountRoot == UninitializedExpandedParentsCountRoot && m_dirLister.data()) {
             const KUrl rootUrl = m_dirLister.data()->url();
             const QString protocol = rootUrl.protocol();
-            const bool forceRootExpansionLevel = (protocol == QLatin1String("trash") ||
-                                                  protocol == QLatin1String("nepomuk") ||
-                                                  protocol == QLatin1String("remote") ||
-                                                  protocol.contains(QLatin1String("search")));
-            if (forceRootExpansionLevel) {
-                m_rootExpansionLevel = ForceRootExpansionLevel;
+            const bool forceExpandedParentsCountRoot = (protocol == QLatin1String("trash") ||
+                                                        protocol == QLatin1String("nepomuk") ||
+                                                        protocol == QLatin1String("remote") ||
+                                                        protocol.contains(QLatin1String("search")));
+            if (forceExpandedParentsCountRoot) {
+                m_expandedParentsCountRoot = ForceExpandedParentsCountRoot;
             } else {
-                const QString rootDir = rootUrl.directory(KUrl::AppendTrailingSlash);
-                m_rootExpansionLevel = rootDir.count('/');
-                if (m_rootExpansionLevel == 1) {
-                    // Special case: The root is already reached and no parent is available
-                    --m_rootExpansionLevel;
-                }
+                const QString rootDir = rootUrl.path(KUrl::AddTrailingSlash);
+                m_expandedParentsCountRoot = rootDir.count('/');
             }
         }
 
-        if (m_rootExpansionLevel == ForceRootExpansionLevel) {
-            data.insert("expansionLevel", -1);
+        if (m_expandedParentsCountRoot == ForceExpandedParentsCountRoot) {
+            data.insert("expandedParentsCount", -1);
         } else {
             const QString dir = item.url().directory(KUrl::AppendTrailingSlash);
-            const int level = dir.count('/') - m_rootExpansionLevel - 1;
-            data.insert("expansionLevel", level);
+            const int level = dir.count('/') - m_expandedParentsCountRoot;
+            data.insert("expandedParentsCount", level);
         }
     }
 
@@ -1221,8 +1270,8 @@ bool KFileItemModel::lessThan(const ItemData* a, const ItemData* b) const
 {
     int result = 0;
 
-    if (m_rootExpansionLevel >= 0) {
-        result = expansionLevelsCompare(a, b);
+    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;
@@ -1255,62 +1304,69 @@ int KFileItemModel::sortRoleCompare(const ItemData* a, const ItemData* b) const
     case NameRole:
         // The name role is handled as default fallback after the switch
         break;
-
-    case DateRole: {
-        const KDateTime dateTimeA = itemA.time(KFileItem::ModificationTime);
-        const KDateTime dateTimeB = itemB.time(KFileItem::ModificationTime);
-        if (dateTimeA < dateTimeB) {
-            result = -1;
-        } else if (dateTimeA > dateTimeB) {
-            result = +1;
-        }
-        break;
-    }
-
+        
     case SizeRole: {
         if (itemA.isDir()) {
-            Q_ASSERT(itemB.isDir()); // see "if (m_sortFoldersFirst || m_sortRole == SizeRole)" above
+            // See "if (m_sortFoldersFirst || m_sortRole == SizeRole)" in KFileItemModel::lessThan():
+            Q_ASSERT(itemB.isDir());
 
             const QVariant valueA = a->values.value("size");
             const QVariant valueB = b->values.value("size");
-
-            if (valueA.isNull()) {
+            if (valueA.isNull() && valueB.isNull()) {
+                result = 0;
+            } else if (valueA.isNull()) {
                 result = -1;
             } else if (valueB.isNull()) {
                 result = +1;
             } else {
-                result = valueA.value<KIO::filesize_t>() - valueB.value<KIO::filesize_t>();
+                result = valueA.toInt() - valueB.toInt();
             }
         } else {
-            Q_ASSERT(!itemB.isDir()); // see "if (m_sortFoldersFirst || m_sortRole == SizeRole)" above
-            result = itemA.size() - itemB.size();
+            // See "if (m_sortFoldersFirst || m_sortRole == SizeRole)" in KFileItemModel::lessThan():
+            Q_ASSERT(!itemB.isDir());
+            const KIO::filesize_t sizeA = itemA.size();
+            const KIO::filesize_t sizeB = itemB.size();
+            if (sizeA > sizeB) {
+                result = +1;
+            } else if (sizeA < sizeB) {
+                result = -1;
+            } else {
+                result = 0;
+            }
         }
         break;
     }
 
-    case TypeRole: {
-        result = QString::compare(a->values.value("type").toString(),
-                                  b->values.value("type").toString());
+    case DateRole: {
+        const KDateTime dateTimeA = itemA.time(KFileItem::ModificationTime);
+        const KDateTime dateTimeB = itemB.time(KFileItem::ModificationTime);
+        if (dateTimeA < dateTimeB) {
+            result = -1;
+        } else if (dateTimeA > dateTimeB) {
+            result = +1;
+        }
         break;
     }
-
-    case CommentRole: {
-        result = QString::compare(a->values.value("comment").toString(),
-                                  b->values.value("comment").toString());
+    
+    case RatingRole: {
+        result = a->values.value("rating").toInt() - b->values.value("rating").toInt();
         break;
     }
-
+    
+    case PermissionsRole:
+    case OwnerRole:
+    case GroupRole:
+    case TypeRole:
+    case DestinationRole:
+    case PathRole:
+    case CommentRole:
     case TagsRole: {
-        result = QString::compare(a->values.value("tags").toString(),
-                                  b->values.value("tags").toString());
-        break;
-    }
-
-    case RatingRole: {
-        result = a->values.value("rating").toInt() - b->values.value("rating").toInt();
+        const QByteArray role = roleByteArray(m_sortRole);
+        result = QString::compare(a->values.value(role).toString(),
+                                  b->values.value(role).toString());
         break;
     }
-
+        
     default:
         break;
     }
@@ -1483,7 +1539,7 @@ int KFileItemModel::stringCompare(const QString& a, const QString& b) const
                             : QString::compare(a, b, Qt::CaseSensitive);
 }
 
-int KFileItemModel::expansionLevelsCompare(const ItemData* a, const ItemData* b) const
+int KFileItemModel::expandedParentsCountCompare(const ItemData* a, const ItemData* b) const
 {
     const KUrl urlA = a->item.url();
     const KUrl urlB = b->item.url();
@@ -1890,9 +1946,9 @@ KFileItemList KFileItemModel::childItems(const KFileItem& item) const
 
     int index = m_items.value(item.url(), -1);
     if (index >= 0) {
-        const int parentLevel = m_itemData.at(index)->values.value("expansionLevel").toInt();
+        const int parentLevel = m_itemData.at(index)->values.value("expandedParentsCount").toInt();
         ++index;
-        while (index < m_itemData.count() && m_itemData.at(index)->values.value("expansionLevel").toInt() > parentLevel) {
+        while (index < m_itemData.count() && m_itemData.at(index)->values.value("expandedParentsCount").toInt() > parentLevel) {
             items.append(m_itemData.at(index)->item);
             ++index;
         }