ItemModels: Cache last-known child index

Instead of caching the last index of a search for a child item, cache
the index of the child in the child item. When the item model is not
changed, the index is valid. Otherwise, the index can only change when
items get inserted or removed before the child. So in that case, start
searching in the vicinity of the previously known index.

As an example: a selectAll() on the view will always hit the cached
index, so no search is performed for any item in the model/view.

Task-number: QTBUG-61368
Change-Id: I85d085299987237fae23451d9e8bbb6060464ef2
Reviewed-by: David Faure <david.faure@kdab.com>
bb10
Erik Verbruggen 2018-04-24 17:06:49 +02:00
parent e3a1b18bc3
commit 74be42ca59
2 changed files with 25 additions and 11 deletions

View File

@ -142,6 +142,8 @@ void QStandardItemPrivate::setChild(int row, int column, QStandardItem *item,
oldItem->d_func()->setModel(0);
delete oldItem;
children.replace(index, item);
if (item)
item->d_func()->lastKnownIndex = index;
if (model && emitChanged)
emit model->layoutChanged();
@ -475,6 +477,8 @@ bool QStandardItemPrivate::insertRows(int row, const QList<QStandardItem*> &item
item->d_func()->parent = q;
int index = childIndex(i + row, 0);
children.replace(index, item);
if (item)
item->d_func()->lastKnownIndex = index;
}
if (model)
model->d_func()->rowsInserted(q, row, count);
@ -512,6 +516,8 @@ bool QStandardItemPrivate::insertRows(int row, int count, const QList<QStandardI
}
}
children.replace(index, item);
if (item)
item->d_func()->lastKnownIndex = index;
++index;
}
}
@ -558,6 +564,8 @@ bool QStandardItemPrivate::insertColumns(int column, int count, const QList<QSta
int c = column + (i % count);
int index = childIndex(r, c);
children.replace(index, item);
if (item)
item->d_func()->lastKnownIndex = index;
}
}
if (model)

View File

@ -114,7 +114,7 @@ public:
rows(0),
columns(0),
q_ptr(0),
lastIndexOf(-1)
lastKnownIndex(-1)
{ }
inline int childIndex(int row, int column) const {
@ -126,32 +126,38 @@ public:
}
inline int childIndex(const QStandardItem *child) const {
const int lastChild = children.size() - 1;
if (lastIndexOf == -1)
lastIndexOf = lastChild / 2;
// assuming the item is in the vicinity of the last search, iterate forwards and
int &childsLastIndexInParent = child->d_func()->lastKnownIndex;
if (childsLastIndexInParent != -1 && childsLastIndexInParent <= lastChild) {
if (children.at(childsLastIndexInParent) == child)
return childsLastIndexInParent;
} else {
childsLastIndexInParent = lastChild / 2;
}
// assuming the item is in the vicinity of the previous index, iterate forwards and
// backwards through the children
int backwardIter = lastIndexOf - 1;
int forwardIter = lastIndexOf;
int backwardIter = childsLastIndexInParent - 1;
int forwardIter = childsLastIndexInParent;
Q_FOREVER {
if (forwardIter <= lastChild) {
if (children.at(forwardIter) == child) {
lastIndexOf = forwardIter;
childsLastIndexInParent = forwardIter;
break;
}
++forwardIter;
} else if (backwardIter < 0) {
lastIndexOf = -1;
childsLastIndexInParent = -1;
break;
}
if (backwardIter >= 0) {
if (children.at(backwardIter) == child) {
lastIndexOf = backwardIter;
childsLastIndexInParent = backwardIter;
break;
}
--backwardIter;
}
}
return lastIndexOf;
return childsLastIndexInParent;
}
QPair<int, int> position() const;
void setChild(int row, int column, QStandardItem *item,
@ -192,7 +198,7 @@ public:
QStandardItem *q_ptr;
mutable int lastIndexOf;
mutable int lastKnownIndex; // this is a cached value
};
class QStandardItemModelPrivate : public QAbstractItemModelPrivate