Skip to content

Commit

Permalink
Improve handling of QTBUG-57971 (ListModel initializing roles on firs…
Browse files Browse the repository at this point in the history
…t insertion)

So far the provided workaround was missing some corner cases when there
is more than one SFPM (or other proxies) in a chain, providing some
custom roles like proxy roles in SFPM. Detailed explanation provided as
a comment directly in the source.
  • Loading branch information
micieslak committed Sep 13, 2024
1 parent b176bad commit d6df62f
Showing 1 changed file with 32 additions and 3 deletions.
35 changes: 32 additions & 3 deletions qqmlsortfilterproxymodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -380,10 +380,39 @@ void QQmlSortFilterProxyModel::resetInternalData()

void QQmlSortFilterProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
{
if (sourceModel && sourceModel->roleNames().isEmpty()) { // workaround for when a model has no roles and roles are added when the model is populated (ListModel)
// QTBUG-57971
connect(sourceModel, &QAbstractItemModel::rowsInserted, this, &QQmlSortFilterProxyModel::initRoles);
// QML built-in type ListModel behaves in a specific way regarding roles
// initialization (QTBUG-57971). Empty model has no roles, they become
// available after first insertion. However modelAboutToBeReset/modelReset
// is not emited. It means that roles may change not only in between model
// resets but also on the first insertion.
// In a simple case, where ListModel (or other model behaving in that way)
// is direct source of SFPM, situation is relatively simple - if source
// has no roles, SFPM should try to initialize them on first insertion
// However this behavior has far-reaching consequences, because the
// ListModel-like model may not be a direct source for SFPM. E.g. there may
// by another SFPM in between, with proxy roles defined:
//
// ListModel -> SFPM 1 (with proxy roles) -> SFPM 2
//
// In such scenario SFPM 2 will always have model with roles as it's source
// (at least proxy roles). It means that on first insertion right after
// SFPM creation or after source model reset it's necessary to re-initialize
// role names if the source was empty before insertion.

if (sourceModel && sourceModel->rowCount() == 0)
connect(sourceModel, &QAbstractItemModel::rowsInserted, this,
&QQmlSortFilterProxyModel::initRoles, Qt::UniqueConnection);

if (sourceModel) {
connect(sourceModel, &QAbstractItemModel::modelReset, this, [sourceModel, this]() {
if (sourceModel->rowCount() != 0)
return;

connect(sourceModel, &QAbstractItemModel::rowsInserted, this,
&QQmlSortFilterProxyModel::initRoles, Qt::UniqueConnection);
});
}

QSortFilterProxyModel::setSourceModel(sourceModel);
}

Expand Down

0 comments on commit d6df62f

Please sign in to comment.