QItemSelectionModel: fix binding loops

... by using valueBypassingBindings() when accessing the properties
from the setters.

Also adjust initModel() to use the raw pointers instead of accessing
the property when comparing the value and doing all connections.
This change is safe, because initModel() is a private method that is
only called from the constructors of the class and the setter.

Task-number: QTBUG-116346
Pick-to: 6.6 6.5
Change-Id: I6ecde571aeed74077099c6bf8f66736ba14d29f8
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
This commit is contained in:
Ivan Solovev 2023-09-06 11:32:27 +02:00
parent 76617b07cf
commit 9578485f35

View File

@ -551,40 +551,41 @@ void QItemSelection::split(const QItemSelectionRange &range,
void QItemSelectionModelPrivate::initModel(QAbstractItemModel *m)
{
Q_Q(QItemSelectionModel);
if (model == m)
const QAbstractItemModel *oldModel = model.valueBypassingBindings();
if (oldModel == m)
return;
if (model)
if (oldModel)
disconnectModel();
// Caller has to call notify(), unless calling during construction (the common case).
model.setValueBypassingBindings(m);
if (model.value()) {
if (m) {
connections = std::array<QMetaObject::Connection, 12> {
QObjectPrivate::connect(model, &QAbstractItemModel::rowsAboutToBeRemoved,
QObjectPrivate::connect(m, &QAbstractItemModel::rowsAboutToBeRemoved,
this, &QItemSelectionModelPrivate::rowsAboutToBeRemoved),
QObjectPrivate::connect(model, &QAbstractItemModel::columnsAboutToBeRemoved,
QObjectPrivate::connect(m, &QAbstractItemModel::columnsAboutToBeRemoved,
this, &QItemSelectionModelPrivate::columnsAboutToBeRemoved),
QObjectPrivate::connect(model, &QAbstractItemModel::rowsAboutToBeInserted,
QObjectPrivate::connect(m, &QAbstractItemModel::rowsAboutToBeInserted,
this, &QItemSelectionModelPrivate::rowsAboutToBeInserted),
QObjectPrivate::connect(model, &QAbstractItemModel::columnsAboutToBeInserted,
QObjectPrivate::connect(m, &QAbstractItemModel::columnsAboutToBeInserted,
this, &QItemSelectionModelPrivate::columnsAboutToBeInserted),
QObjectPrivate::connect(model, &QAbstractItemModel::rowsAboutToBeMoved,
QObjectPrivate::connect(m, &QAbstractItemModel::rowsAboutToBeMoved,
this, &QItemSelectionModelPrivate::triggerLayoutToBeChanged),
QObjectPrivate::connect(model, &QAbstractItemModel::columnsAboutToBeMoved,
QObjectPrivate::connect(m, &QAbstractItemModel::columnsAboutToBeMoved,
this, &QItemSelectionModelPrivate::triggerLayoutToBeChanged),
QObjectPrivate::connect(model, &QAbstractItemModel::rowsMoved,
QObjectPrivate::connect(m, &QAbstractItemModel::rowsMoved,
this, &QItemSelectionModelPrivate::triggerLayoutChanged),
QObjectPrivate::connect(model, &QAbstractItemModel::columnsMoved,
QObjectPrivate::connect(m, &QAbstractItemModel::columnsMoved,
this, &QItemSelectionModelPrivate::triggerLayoutChanged),
QObjectPrivate::connect(model, &QAbstractItemModel::layoutAboutToBeChanged,
QObjectPrivate::connect(m, &QAbstractItemModel::layoutAboutToBeChanged,
this, &QItemSelectionModelPrivate::layoutAboutToBeChanged),
QObjectPrivate::connect(model, &QAbstractItemModel::layoutChanged,
QObjectPrivate::connect(m, &QAbstractItemModel::layoutChanged,
this, &QItemSelectionModelPrivate::layoutChanged),
QObject::connect(model, &QAbstractItemModel::modelReset,
QObject::connect(m, &QAbstractItemModel::modelReset,
q, &QItemSelectionModel::reset),
QObjectPrivate::connect(model, &QAbstractItemModel::destroyed,
QObjectPrivate::connect(m, &QAbstractItemModel::destroyed,
this, &QItemSelectionModelPrivate::modelDestroyed)
};
}
@ -1887,7 +1888,7 @@ void QItemSelectionModel::setModel(QAbstractItemModel *model)
{
Q_D(QItemSelectionModel);
d->model.removeBindingUnlessInWrapper();
if (d->model == model)
if (d->model.valueBypassingBindings() == model)
return;
d->initModel(model);
d->model.notify();