X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/59723fca41a44e4d1ee753e93589027cbdf8d20d..64afe7b22622f79b34aafd54501b08120ab2fc5c:/src/kitemviews/kfileitemmodel.cpp diff --git a/src/kitemviews/kfileitemmodel.cpp b/src/kitemviews/kfileitemmodel.cpp index c0dedff39..734950257 100644 --- a/src/kitemviews/kfileitemmodel.cpp +++ b/src/kitemviews/kfileitemmodel.cpp @@ -21,7 +21,6 @@ #include "kfileitemmodel.h" -#include #include #include #include @@ -152,7 +151,12 @@ int KFileItemModel::count() const QHash KFileItemModel::data(int index) const { if (index >= 0 && index < count()) { - return m_itemData.at(index)->values; + ItemData* data = m_itemData.at(index); + if (data->values.isEmpty()) { + data->values = retrieveData(data->item, data->parent); + } + + return data->values; } return QHash(); } @@ -163,7 +167,7 @@ bool KFileItemModel::setData(int index, const QHash& value return false; } - QHash currentValues = m_itemData.at(index)->values; + QHash currentValues = data(index); // Determine which roles have been changed QSet changedRoles; @@ -190,11 +194,7 @@ bool KFileItemModel::setData(int index, const QHash& value m_itemData[index]->item.setUrl(url); } - emit itemsChanged(KItemRangeList() << KItemRange(index, 1), changedRoles); - - if (changedRoles.contains(sortRole())) { - m_resortAllItemsTimer->start(); - } + emitItemsChangedAndTriggerResorting(KItemRangeList() << KItemRange(index, 1), changedRoles); return true; } @@ -236,7 +236,7 @@ bool KFileItemModel::showDirectoriesOnly() const return m_dirLister->dirOnlyMode(); } -QMimeData* KFileItemModel::createMimeData(const QSet& indexes) const +QMimeData* KFileItemModel::createMimeData(const KItemSet& indexes) const { QMimeData* data = new QMimeData(); @@ -246,11 +246,23 @@ QMimeData* KFileItemModel::createMimeData(const QSet& indexes) const KUrl::List urls; KUrl::List mostLocalUrls; bool canUseMostLocalUrls = true; + const ItemData* lastAddedItem = 0; - QSetIterator it(indexes); - while (it.hasNext()) { - const int index = it.next(); - const KFileItem item = fileItem(index); + foreach (int index, indexes) { + const ItemData* itemData = m_itemData.at(index); + const ItemData* parent = itemData->parent; + + while (parent && parent != lastAddedItem) { + parent = parent->parent; + } + + if (parent && parent == lastAddedItem) { + // A parent of 'itemData' has been added already. + continue; + } + + lastAddedItem = itemData; + const KFileItem& item = itemData->item; if (!item.isNull()) { urls << item.targetUrl(); @@ -263,9 +275,7 @@ QMimeData* KFileItemModel::createMimeData(const QSet& indexes) const } 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); @@ -278,12 +288,12 @@ int KFileItemModel::indexForKeyboardSearch(const QString& text, int startFromInd { startFromIndex = qMax(0, startFromIndex); for (int i = startFromIndex; i < count(); ++i) { - if (data(i)["text"].toString().startsWith(text, Qt::CaseInsensitive)) { + if (fileItem(i).text().startsWith(text, Qt::CaseInsensitive)) { return i; } } for (int i = 0; i < startFromIndex; ++i) { - if (data(i)["text"].toString().startsWith(text, Qt::CaseInsensitive)) { + if (fileItem(i).text().startsWith(text, Qt::CaseInsensitive)) { return i; } } @@ -414,6 +424,15 @@ void KFileItemModel::setRoles(const QSet& roles) kWarning() << "TODO: Emitting itemsChanged() with no information what has changed!"; emit itemsChanged(KItemRangeList() << KItemRange(0, count()), QSet()); } + + // Clear the 'values' of all filtered items. They will be re-populated with the + // correct roles the next time 'values' will be accessed via data(int). + QHash::iterator filteredIt = m_filteredItems.begin(); + const QHash::iterator filteredEnd = m_filteredItems.end(); + while (filteredIt != filteredEnd) { + (*filteredIt)->values.clear(); + ++filteredIt; + } } QSet KFileItemModel::roles() const @@ -439,15 +458,37 @@ bool KFileItemModel::setExpanded(int index, bool expanded) if (expanded) { m_expandedDirs.insert(targetUrl, url); m_dirLister->openUrl(url, KDirLister::Keep); + + const KUrl::List previouslyExpandedChildren = m_itemData.at(index)->values.value("previouslyExpandedChildren").value(); + foreach (const KUrl& url, previouslyExpandedChildren) { + m_urlsToExpand.insert(url); + } } else { m_expandedDirs.remove(targetUrl); m_dirLister->stop(url); - removeFilteredChildren(KFileItemList() << item); + const int parentLevel = expandedParentsCount(index); + const int itemCount = m_itemData.count(); + const int firstChildIndex = index + 1; + + KUrl::List expandedChildren; + + int childIndex = firstChildIndex; + while (childIndex < itemCount && expandedParentsCount(childIndex) > parentLevel) { + ItemData* itemData = m_itemData.at(childIndex); + if (itemData->values.value("isExpanded").toBool()) { + const KUrl targetUrl = itemData->item.targetUrl(); + m_expandedDirs.remove(targetUrl); + expandedChildren.append(targetUrl); + } + ++childIndex; + } + const int childrenCount = childIndex - firstChildIndex; + + removeFilteredChildren(KItemRangeList() << KItemRange(index, 1 + childrenCount)); + removeItems(KItemRangeList() << KItemRange(firstChildIndex, childrenCount), DeleteItemData); - const KFileItemList itemsToRemove = childItems(item); - removeFilteredChildren(itemsToRemove); - removeItems(itemsToRemove, DeleteItemData); + m_itemData.at(index)->values.insert("previouslyExpandedChildren", expandedChildren); } return true; @@ -464,7 +505,9 @@ bool KFileItemModel::isExpanded(int index) const bool KFileItemModel::isExpandable(int index) const { if (index >= 0 && index < count()) { - return m_itemData.at(index)->values.value("isExpandable").toBool(); + // Call data (instead of accessing m_itemData directly) + // to ensure that the value is initialized. + return data(index).value("isExpandable").toBool(); } return false; } @@ -472,10 +515,7 @@ bool KFileItemModel::isExpandable(int index) const 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 expandedParentsCount(m_itemData.at(index)); } return 0; } @@ -551,21 +591,25 @@ void KFileItemModel::applyFilters() { // Check which shown items from m_itemData must get // hidden and hence moved to m_filteredItems. - KFileItemList newFilteredItems; + QVector newFilteredIndexes; + + const int itemCount = m_itemData.count(); + for (int index = 0; index < itemCount; ++index) { + ItemData* itemData = m_itemData.at(index); - foreach (ItemData* itemData, m_itemData) { // Only filter non-expanded items as child items may never // exist without a parent item if (!itemData->values.value("isExpanded").toBool()) { const KFileItem item = itemData->item; if (!m_filter.matches(item)) { - newFilteredItems.append(item); + newFilteredIndexes.append(index); m_filteredItems.insert(item, itemData); } } } - removeItems(newFilteredItems, KeepItemData); + const KItemRangeList removedRanges = KItemRangeList::fromSortedContainer(newFilteredIndexes); + removeItems(removedRanges, KeepItemData); // Check which hidden items from m_filteredItems should // get visible again and hence removed from m_filteredItems. @@ -584,22 +628,24 @@ void KFileItemModel::applyFilters() insertItems(newVisibleItems); } -void KFileItemModel::removeFilteredChildren(const KFileItemList& parentsList) +void KFileItemModel::removeFilteredChildren(const KItemRangeList& itemRanges) { - if (m_filteredItems.isEmpty()) { + if (m_filteredItems.isEmpty() || !m_requestRole[ExpandedParentsCountRole]) { + // There are either no filtered items, or it is not possible to expand + // folders -> there cannot be any filtered children. return; } - // First, we put the parent items into a set to provide fast lookup - // while iterating over m_filteredItems and prevent quadratic - // complexity if there are N parents and N filtered items. - const QSet parents = parentsList.toSet(); + QSet parents; + foreach (const KItemRange& range, itemRanges) { + for (int index = range.index; index < range.index + range.count; ++index) { + parents.insert(m_itemData.at(index)); + } + } QHash::iterator it = m_filteredItems.begin(); while (it != m_filteredItems.end()) { - const ItemData* parent = it.value()->parent; - - if (parent && parents.contains(parent->item)) { + if (parents.contains(it.value()->parent)) { delete it.value(); it = m_filteredItems.erase(it); } else { @@ -627,7 +673,7 @@ QList KFileItemModel::rolesInformation() // menus tries to put the actions into sub menus otherwise. info.group = QString(); } - info.requiresNepomuk = map[i].requiresNepomuk; + info.requiresBaloo = map[i].requiresBaloo; info.requiresIndexer = map[i].requiresIndexer; rolesInfo.append(info); } @@ -689,7 +735,6 @@ void KFileItemModel::resortAllItems() oldUrls.append(itemData->item.url()); } - m_groups.clear(); m_items.clear(); // Resort the items @@ -698,20 +743,45 @@ void KFileItemModel::resortAllItems() m_items.insert(m_itemData.at(i)->item.url(), i); } - // Determine the indexes that have been moved - QList movedToIndexes; - movedToIndexes.reserve(itemCount); - for (int i = 0; i < itemCount; i++) { - const int newIndex = m_items.value(oldUrls.at(i)); - movedToIndexes.append(newIndex); + // Determine the first index that has been moved. + int firstMovedIndex = 0; + while (firstMovedIndex < itemCount + && firstMovedIndex == m_items.value(oldUrls.at(firstMovedIndex))) { + ++firstMovedIndex; } - // Don't check whether items have really been moved and always emit a - // itemsMoved() signal after resorting: In case of grouped items - // the groups might change even if the items themselves don't change their - // position. Let the receiver of the signal decide whether a check for moved - // items makes sense. - emit itemsMoved(KItemRange(0, itemCount), movedToIndexes); + const bool itemsHaveMoved = firstMovedIndex < itemCount; + if (itemsHaveMoved) { + m_groups.clear(); + + int lastMovedIndex = itemCount - 1; + while (lastMovedIndex > firstMovedIndex + && lastMovedIndex == m_items.value(oldUrls.at(lastMovedIndex))) { + --lastMovedIndex; + } + + Q_ASSERT(firstMovedIndex <= lastMovedIndex); + + // Create a list movedToIndexes, which has the property that + // movedToIndexes[i] is the new index of the item with the old index + // firstMovedIndex + i. + const int movedItemsCount = lastMovedIndex - firstMovedIndex + 1; + QList movedToIndexes; + movedToIndexes.reserve(movedItemsCount); + for (int i = firstMovedIndex; i <= lastMovedIndex; ++i) { + const int newIndex = m_items.value(oldUrls.at(i)); + movedToIndexes.append(newIndex); + } + + emit itemsMoved(KItemRange(firstMovedIndex, movedItemsCount), movedToIndexes); + } else if (groupedSorting()) { + // The groups might have changed even if the order of the items has not. + const QList > oldGroups = m_groups; + m_groups.clear(); + if (groups() != oldGroups) { + emit groupsChanged(); + } + } #ifdef KFILEITEMMODEL_DEBUG kDebug() << "[TIME] Resorting of" << itemCount << "items:" << timer.elapsed(); @@ -825,29 +895,49 @@ void KFileItemModel::slotItemsDeleted(const KFileItemList& items) { dispatchPendingItemsToInsert(); - KFileItemList itemsToRemove = items; - if (m_requestRole[ExpandedParentsCountRole]) { - // Assure that removing a parent item also results in removing all children - foreach (const KFileItem& item, items) { - itemsToRemove.append(childItems(item)); - } - } + QVector indexesToRemove; + indexesToRemove.reserve(items.count()); - if (!m_filteredItems.isEmpty()) { - foreach (const KFileItem& item, itemsToRemove) { + foreach (const KFileItem& item, items) { + const KUrl url = item.url(); + const int index = m_items.value(url, -1); + if (index >= 0) { + indexesToRemove.append(index); + } else { + // Probably the item has been filtered. QHash::iterator it = m_filteredItems.find(item); if (it != m_filteredItems.end()) { delete it.value(); m_filteredItems.erase(it); } } + } + + std::sort(indexesToRemove.begin(), indexesToRemove.end()); - if (m_requestRole[ExpandedParentsCountRole]) { - removeFilteredChildren(itemsToRemove); + if (m_requestRole[ExpandedParentsCountRole] && !m_expandedDirs.isEmpty()) { + // Assure that removing a parent item also results in removing all children + QVector indexesToRemoveWithChildren; + indexesToRemoveWithChildren.reserve(m_items.count()); + + const int itemCount = m_itemData.count(); + foreach (int index, indexesToRemove) { + indexesToRemoveWithChildren.append(index); + + const int parentLevel = expandedParentsCount(index); + int childIndex = index + 1; + while (childIndex < itemCount && expandedParentsCount(childIndex) > parentLevel) { + indexesToRemoveWithChildren.append(childIndex); + ++childIndex; + } } + + indexesToRemove = indexesToRemoveWithChildren; } - removeItems(itemsToRemove, DeleteItemData); + const KItemRangeList itemRanges = KItemRangeList::fromSortedContainer(indexesToRemove); + removeFilteredChildren(itemRanges); + removeItems(itemRanges, DeleteItemData); } void KFileItemModel::slotRefreshItems(const QList >& items) @@ -888,6 +978,20 @@ void KFileItemModel::slotRefreshItems(const QList >& m_items.remove(oldItem.url()); m_items.insert(newItem.url(), index); indexes.append(index); + } else { + // Check if 'oldItem' is one of the filtered items. + QHash::iterator it = m_filteredItems.find(oldItem); + if (it != m_filteredItems.end()) { + ItemData* itemData = it.value(); + itemData->item = newItem; + + // The data stored in 'values' might have changed. Therefore, we clear + // 'values' and re-populate it the next time it is requested via data(int). + itemData->values.clear(); + + m_filteredItems.erase(it); + m_filteredItems.insert(newItem, itemData); + } } } @@ -899,35 +1003,8 @@ void KFileItemModel::slotRefreshItems(const QList >& // Extract the item-ranges out of the changed indexes qSort(indexes); - - KItemRangeList itemRangeList; - int previousIndex = indexes.at(0); - int rangeIndex = previousIndex; - int rangeCount = 1; - - 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, changedRoles); - - if (changedRoles.contains(sortRole())) { - resortAllItems(); - } + const KItemRangeList itemRangeList = KItemRangeList::fromSortedContainer(indexes); + emitItemsChangedAndTriggerResorting(itemRangeList, changedRoles); } void KFileItemModel::slotClear() @@ -990,6 +1067,15 @@ void KFileItemModel::insertItems(QList& newItems) #endif m_groups.clear(); + prepareItemsForSorting(newItems); + + if (m_sortRole == NameRole && m_naturalSorting) { + // Natural sorting of items can be very slow. However, it becomes much + // faster if the input sequence is already mostly sorted. Therefore, we + // first sort 'newItems' according to the QStrings returned by + // KFileItem::text() using QString::operator<(), which is quite fast. + parallelMergeSort(newItems.begin(), newItems.end(), nameLessThan, QThread::idealThreadCount()); + } sort(newItems.begin(), newItems.end()); @@ -1064,53 +1150,21 @@ void KFileItemModel::insertItems(QList& newItems) #endif } -static KItemRangeList sortedIndexesToKItemRangeList(const QList& sortedNumbers) +void KFileItemModel::removeItems(const KItemRangeList& itemRanges, RemoveItemsBehavior behavior) { - if (sortedNumbers.empty()) { - return KItemRangeList(); - } - - KItemRangeList result; - - QList::const_iterator it = sortedNumbers.begin(); - int index = *it; - int count = 1; - - ++it; - - QList::const_iterator end = sortedNumbers.end(); - while (it != end) { - if (*it == index + count) { - ++count; - } else { - result << KItemRange(index, count); - index = *it; - count = 1; - } - ++it; + if (itemRanges.isEmpty()) { + return; } - result << KItemRange(index, count); - return result; -} - -void KFileItemModel::removeItems(const KFileItemList& items, RemoveItemsBehavior behavior) -{ -#ifdef KFILEITEMMODEL_DEBUG - kDebug() << "Removing " << items.count() << "items"; -#endif - m_groups.clear(); - // Step 1: Determine the indexes of the removed items, remove them from - // the hash m_items, and free the ItemData. - QList indexesToRemove; - indexesToRemove.reserve(items.count()); - foreach (const KFileItem& item, items) { - const KUrl url = item.url(); - const int index = m_items.value(url, -1); - if (index >= 0) { - indexesToRemove.append(index); + // Step 1: Remove the items from the hash m_items, and free the ItemData. + int removedItemsCount = 0; + foreach (const KItemRange& range, itemRanges) { + removedItemsCount += range.count; + + for (int index = range.index; index < range.index + range.count; ++index) { + const KUrl url = m_itemData.at(index)->item.url(); // Prevent repeated expensive rehashing by using QHash::erase(), // rather than QHash::remove(). @@ -1125,14 +1179,7 @@ void KFileItemModel::removeItems(const KFileItemList& items, RemoveItemsBehavior } } - if (indexesToRemove.isEmpty()) { - return; - } - - std::sort(indexesToRemove.begin(), indexesToRemove.end()); - // Step 2: Remove the ItemData pointers from the list m_itemData. - const KItemRangeList itemRanges = sortedIndexesToKItemRangeList(indexesToRemove); int target = itemRanges.at(0).index; int source = itemRanges.at(0).index + itemRanges.at(0).count; int nextRange = 1; @@ -1150,7 +1197,7 @@ void KFileItemModel::removeItems(const KFileItemList& items, RemoveItemsBehavior } } - m_itemData.erase(m_itemData.end() - indexesToRemove.count(), m_itemData.end()); + m_itemData.erase(m_itemData.end() - removedItemsCount, m_itemData.end()); // Step 3: Adjust indexes in the hash m_items, starting from the // index of the first removed item. @@ -1180,7 +1227,6 @@ QList KFileItemModel::createItemDataList(const KUrl& foreach (const KFileItem& item, items) { ItemData* itemData = new ItemData(); itemData->item = item; - itemData->values = retrieveData(item, parentItem); itemData->parent = parentItem; itemDataList.append(itemData); } @@ -1188,23 +1234,141 @@ QList KFileItemModel::createItemDataList(const KUrl& return itemDataList; } +void KFileItemModel::prepareItemsForSorting(QList& itemDataList) +{ + switch (m_sortRole) { + case PermissionsRole: + case OwnerRole: + case GroupRole: + case DestinationRole: + case PathRole: + // These roles can be determined with retrieveData, and they have to be stored + // in the QHash "values" for the sorting. + foreach (ItemData* itemData, itemDataList) { + if (itemData->values.isEmpty()) { + itemData->values = retrieveData(itemData->item, itemData->parent); + } + } + break; + + case TypeRole: + // At least store the data including the file type for items with known MIME type. + foreach (ItemData* itemData, itemDataList) { + if (itemData->values.isEmpty()) { + const KFileItem item = itemData->item; + if (item.isDir() || item.isMimeTypeKnown()) { + itemData->values = retrieveData(itemData->item, itemData->parent); + } + } + } + break; + + default: + // The other roles are either resolved by KFileItemModelRolesUpdater + // (this includes the SizeRole for directories), or they do not need + // to be stored in the QHash "values" for sorting because the data can + // be retrieved directly from the KFileItem (NameRole, SizeRole for files, + // DateRole). + break; + } +} + +int KFileItemModel::expandedParentsCount(const ItemData* data) +{ + // The hash 'values' is only guaranteed to contain the key "expandedParentsCount" + // if the corresponding item is expanded, and it is not a top-level item. + const ItemData* parent = data->parent; + if (parent) { + if (parent->parent) { + Q_ASSERT(parent->values.contains("expandedParentsCount")); + return parent->values.value("expandedParentsCount").toInt() + 1; + } else { + return 1; + } + } else { + return 0; + } +} + void KFileItemModel::removeExpandedItems() { - KFileItemList expandedItems; + QVector indexesToRemove; 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("expandedParentsCount").toInt() > 0) { - expandedItems.append(itemData->item); + if (itemData->parent) { + indexesToRemove.append(i); } } - // The m_expandedParentsCountRoot may not get reset before all items with - // a bigger count have been removed. - removeItems(expandedItems, DeleteItemData); - + removeItems(KItemRangeList::fromSortedContainer(indexesToRemove), DeleteItemData); m_expandedDirs.clear(); + + // Also remove all filtered items which have a parent. + QHash::iterator it = m_filteredItems.begin(); + const QHash::iterator end = m_filteredItems.end(); + + while (it != end) { + if (it.value()->parent) { + delete it.value(); + it = m_filteredItems.erase(it); + } else { + ++it; + } + } +} + +void KFileItemModel::emitItemsChangedAndTriggerResorting(const KItemRangeList& itemRanges, const QSet& changedRoles) +{ + emit itemsChanged(itemRanges, changedRoles); + + // Trigger a resorting if necessary. Note that this can happen even if the sort + // role has not changed at all because the file name can be used as a fallback. + if (changedRoles.contains(sortRole()) || changedRoles.contains(roleForType(NameRole))) { + foreach (const KItemRange& range, itemRanges) { + bool needsResorting = false; + + const int first = range.index; + const int last = range.index + range.count - 1; + + // Resorting the model is necessary if + // (a) The first item in the range is "lessThan" its predecessor, + // (b) the successor of the last item is "lessThan" the last item, or + // (c) the internal order of the items in the range is incorrect. + if (first > 0 + && lessThan(m_itemData.at(first), m_itemData.at(first - 1))) { + needsResorting = true; + } else if (last < count() - 1 + && lessThan(m_itemData.at(last + 1), m_itemData.at(last))) { + needsResorting = true; + } else { + for (int index = first; index < last; ++index) { + if (lessThan(m_itemData.at(index + 1), m_itemData.at(index))) { + needsResorting = true; + break; + } + } + } + + if (needsResorting) { + m_resortAllItemsTimer->start(); + return; + } + } + } + + if (groupedSorting() && changedRoles.contains(sortRole())) { + // The position is still correct, but the groups might have changed + // if the changed item is either the first or the last item in a + // group. + // In principle, we could try to find out if the item really is the + // first or last one in its group and then update the groups + // (possibly with a delayed timer to make sure that we don't + // re-calculate the groups very often if items are updated one by + // one), but starting m_resortAllItemsTimer is easier. + m_resortAllItemsTimer->start(); + } } void KFileItemModel::resetRoles() @@ -1348,7 +1512,7 @@ QHash KFileItemModel::retrieveData(const KFileItem& item, if (m_requestRole[ExpandedParentsCountRole]) { if (parent) { - const int level = parent->values["expandedParentsCount"].toInt() + 1; + const int level = expandedParentsCount(parent) + 1; data.insert(sharedValue("expandedParentsCount"), level); } } @@ -1359,6 +1523,9 @@ QHash KFileItemModel::retrieveData(const KFileItem& item, if (m_requestRole[TypeRole]) { data.insert(sharedValue("type"), item.mimeComment()); } + } else if (m_requestRole[TypeRole] && isDir) { + static const QString folderMimeType = item.mimeComment(); + data.insert(sharedValue("type"), folderMimeType); } return data; @@ -1369,8 +1536,8 @@ bool KFileItemModel::lessThan(const ItemData* a, const ItemData* b) const int result = 0; if (a->parent != b->parent) { - const int expansionLevelA = a->values.value("expandedParentsCount").toInt(); - const int expansionLevelB = b->values.value("expandedParentsCount").toInt(); + const int expansionLevelA = expandedParentsCount(a); + const int expansionLevelB = expandedParentsCount(b); // 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. @@ -1390,7 +1557,7 @@ bool KFileItemModel::lessThan(const ItemData* a, const ItemData* b) const a = a->parent; } - Q_ASSERT(a->values.value("expandedParentsCount").toInt() == b->values.value("expandedParentsCount").toInt()); + Q_ASSERT(expandedParentsCount(a) == expandedParentsCount(b)); // Compare the last parents of a and b which are different. while (a->parent != b->parent) { @@ -1600,7 +1767,7 @@ QList > KFileItemModel::nameRoleGroups() const continue; } - const QString name = m_itemData.at(i)->values.value("text").toString(); + const QString name = m_itemData.at(i)->item.text(); // Use the first character of the name as group indication QChar newFirstChar = name.at(0).toUpper(); @@ -1883,23 +2050,6 @@ QList > KFileItemModel::genericStringRoleGroups(const QByte return groups; } -KFileItemList KFileItemModel::childItems(const KFileItem& item) const -{ - KFileItemList items; - - int index = m_items.value(item.url(), -1); - if (index >= 0) { - const int parentLevel = m_itemData.at(index)->values.value("expandedParentsCount").toInt(); - ++index; - while (index < m_itemData.count() && m_itemData.at(index)->values.value("expandedParentsCount").toInt() > parentLevel) { - items.append(m_itemData.at(index)->item); - ++index; - } - } - - return items; -} - void KFileItemModel::emitSortProgress(int resolvedCount) { // Be tolerant against a resolvedCount with a wrong range. @@ -1931,7 +2081,7 @@ void KFileItemModel::emitSortProgress(int resolvedCount) const KFileItemModel::RoleInfoMap* KFileItemModel::rolesInfoMap(int& count) { static const RoleInfoMap rolesInfoMap[] = { - // | role | roleType | role translation | group translation | requires Nepomuk | requires indexer + // | role | roleType | role translation | group translation | requires Baloo | requires indexer { 0, NoRole, 0, 0, 0, 0, false, false }, { "text", NameRole, I18N_NOOP2_NOSTRIP("@label", "Name"), 0, 0, false, false }, { "size", SizeRole, I18N_NOOP2_NOSTRIP("@label", "Size"), 0, 0, false, false }, @@ -1965,7 +2115,15 @@ void KFileItemModel::determineMimeTypes(const KFileItemList& items, int timeout) QElapsedTimer timer; timer.start(); foreach (const KFileItem& item, items) { // krazy:exclude=foreach - item.determineMimeType(); + // Only determine mime types for files here. For directories, + // KFileItem::determineMimeType() reads the .directory file inside to + // load the icon, but this is not necessary at all if we just need the + // type. Some special code for setting the correct mime type for + // directories is in retrieveData(). + if (!item.isDir()) { + item.determineMimeType(); + } + if (timer.elapsed() > timeout) { // Don't block the user interface, let the remaining items // be resolved asynchronously. @@ -2018,7 +2176,7 @@ bool KFileItemModel::isConsistent() const 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) { + if (expandedParentsCount(data) != expandedParentsCount(parent) + 1) { qWarning() << "expandedParentsCount is inconsistent for parent" << parent->item << "and child" << data->item; return false; }