perf(SortFilterProxyModel): Improve sorting performance

Implement strict less in lessThan override. This function is used as the < operator when sorting.

+ avoid row invalidation if the model component is not ready
+ `Sorter::invalidate` is virtual. It provides more control to the derived classes
This commit is contained in:
Alex Jbanca 2024-01-29 21:49:42 +02:00
parent 70b76297fd
commit dae1dcaa13
No known key found for this signature in database
GPG Key ID: 6004079575C21C5D
5 changed files with 18 additions and 15 deletions

View File

@ -350,10 +350,10 @@ bool QQmlSortFilterProxyModel::lessThan(const QModelIndex& source_left, const QM
{
if (m_completed) {
if (!m_sortRoleName.isEmpty()) {
if (QSortFilterProxyModel::lessThan(source_left, source_right))
return m_ascendingSortOrder;
if (QSortFilterProxyModel::lessThan(source_right, source_left))
return !m_ascendingSortOrder;
if (m_ascendingSortOrder)
return QSortFilterProxyModel::lessThan(source_left, source_right);
else
return QSortFilterProxyModel::lessThan(source_right, source_left);
}
auto sortedSorters = m_sorters;
std::stable_sort(sortedSorters.begin(),
@ -364,8 +364,7 @@ bool QQmlSortFilterProxyModel::lessThan(const QModelIndex& source_left, const QM
for(auto sorter : sortedSorters) {
if (sorter->enabled()) {
int comparison = sorter->compareRows(source_left, source_right, *this);
if (comparison != 0)
return comparison < 0;
return comparison == -1;
}
}
}

View File

@ -59,6 +59,7 @@ void ExpressionSorter::setExpression(const QQmlScriptString& scriptString)
void ExpressionSorter::proxyModelCompleted(const QQmlSortFilterProxyModel& proxyModel)
{
Sorter::proxyModelCompleted(proxyModel);
updateContext(proxyModel);
}

View File

@ -48,6 +48,8 @@ int FilterSorter::compare(const QModelIndex& sourceLeft, const QModelIndex& sour
void FilterSorter::proxyModelCompleted(const QQmlSortFilterProxyModel& proxyModel)
{
Sorter::proxyModelCompleted(proxyModel);
for (Filter* filter : qAsConst(m_filters))
filter->proxyModelCompleted(proxyModel);
}

View File

@ -107,21 +107,20 @@ void Sorter::setPriority(int priority)
int Sorter::compareRows(const QModelIndex &source_left, const QModelIndex &source_right, const QQmlSortFilterProxyModel& proxyModel) const
{
int comparison = compare(source_left, source_right, proxyModel);
return (m_sortOrder == Qt::AscendingOrder) ? comparison : -comparison;
if (m_sortOrder == Qt::AscendingOrder)
return compare(source_left, source_right, proxyModel);
else
return compare(source_right, source_left, proxyModel);
}
int Sorter::compare(const QModelIndex &sourceLeft, const QModelIndex &sourceRight, const QQmlSortFilterProxyModel& proxyModel) const
{
if (lessThan(sourceLeft, sourceRight, proxyModel))
return -1;
if (lessThan(sourceRight, sourceLeft, proxyModel))
return 1;
return 0;
return lessThan(sourceLeft, sourceRight, proxyModel) ? -1 : 1;
}
void Sorter::proxyModelCompleted(const QQmlSortFilterProxyModel& proxyModel)
{
m_proxyCompleted = true;
Q_UNUSED(proxyModel)
}
@ -135,7 +134,7 @@ bool Sorter::lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRi
void Sorter::invalidate()
{
if (m_enabled)
if (m_enabled && m_proxyCompleted)
Q_EMIT invalidated();
}

View File

@ -45,12 +45,14 @@ Q_SIGNALS:
protected:
virtual int compare(const QModelIndex& sourceLeft, const QModelIndex& sourceRight, const QQmlSortFilterProxyModel& proxyModel) const;
virtual bool lessThan(const QModelIndex& sourceLeft, const QModelIndex& sourceRight, const QQmlSortFilterProxyModel& proxyModel) const;
void invalidate();
virtual void invalidate();
private:
bool m_enabled = true;
Qt::SortOrder m_sortOrder = Qt::AscendingOrder;
int m_priority = 0;
bool m_proxyCompleted = false;
};
}