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;
}
oldUrls.append(itemData->item.url());
}
- m_groups.clear();
m_items.clear();
// Resort the items
m_items.insert(m_itemData.at(i)->item.url(), i);
}
- // Determine the indexes that have been moved
- QList<int> 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<int> 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<QPair<int, QVariant> > oldGroups = m_groups;
+ m_groups.clear();
+ if (groups() != oldGroups) {
+ emit groupsChanged();
+ }
+ }
#ifdef KFILEITEMMODEL_DEBUG
kDebug() << "[TIME] Resorting of" << itemCount << "items:" << timer.elapsed();
// 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));
- }
-
+ const KItemRangeList itemRangeList = KItemRangeList::fromSortedContainer(indexes);
emitItemsChangedAndTriggerResorting(itemRangeList, changedRoles);
}
#endif
}
-static KItemRangeList sortedIndexesToKItemRangeList(const QList<int>& sortedNumbers)
-{
- if (sortedNumbers.empty()) {
- return KItemRangeList();
- }
-
- KItemRangeList result;
-
- QList<int>::const_iterator it = sortedNumbers.begin();
- int index = *it;
- int count = 1;
-
- ++it;
-
- QList<int>::const_iterator end = sortedNumbers.end();
- while (it != end) {
- if (*it == index + count) {
- ++count;
- } else {
- result << KItemRange(index, count);
- index = *it;
- count = 1;
- }
- ++it;
- }
-
- result << KItemRange(index, count);
- return result;
-}
-
void KFileItemModel::removeItems(const KFileItemList& items, RemoveItemsBehavior behavior)
{
#ifdef KFILEITEMMODEL_DEBUG
std::sort(indexesToRemove.begin(), indexesToRemove.end());
// Step 2: Remove the ItemData pointers from the list m_itemData.
- const KItemRangeList itemRanges = sortedIndexesToKItemRangeList(indexesToRemove);
+ const KItemRangeList itemRanges = KItemRangeList::fromSortedContainer(indexesToRemove);
int target = itemRanges.at(0).index;
int source = itemRanges.at(0).index + itemRanges.at(0).count;
int nextRange = 1;
return itemDataList;
}
+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;
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) {
+ if (itemData->parent) {
expandedItems.append(itemData->item);
}
}
- // The m_expandedParentsCountRoot may not get reset before all items with
- // a bigger count have been removed.
removeItems(expandedItems, DeleteItemData);
-
m_expandedDirs.clear();
+
+ // Also remove all filtered items which have a parent.
+ QHash<KFileItem, ItemData*>::iterator it = m_filteredItems.begin();
+ const QHash<KFileItem, ItemData*>::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<QByteArray>& changedRoles)
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);
}
}
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.
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) {
int index = m_items.value(item.url(), -1);
if (index >= 0) {
- const int parentLevel = m_itemData.at(index)->values.value("expandedParentsCount").toInt();
+ const int parentLevel = expandedParentsCount(index);
++index;
- while (index < m_itemData.count() && m_itemData.at(index)->values.value("expandedParentsCount").toInt() > parentLevel) {
+ while (index < m_itemData.count() && expandedParentsCount(index) > parentLevel) {
items.append(m_itemData.at(index)->item);
++index;
}
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;
}