QQmlDelegateModel: De-bounce initialization of two-way bindings
When installing the reverse binding on a QQmlDelegateModelItem, the
binding is evaluated right away and tries to write the model data. We
don't want that since we know that the model data already contains the
same value.
Use a temporary filtering metaobject to block writes to this property
while installing the reverse binding. This causes the bounced write to
fail.
Amends commit 4bd5b31279
Pick-to: 6.10
Task-number: QTBUG-132420
Change-Id: Ib001f669046635cc3ae830154f22d95ee1d3924c
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
This commit is contained in:
parent
7873f3484c
commit
c5832c09c6
|
@ -953,7 +953,8 @@ public:
|
|||
, access(access)
|
||||
{}
|
||||
|
||||
void operator()(const QMetaObject *modelMetaObject, QObject *modelObject) const
|
||||
template<typename ModelObjectType>
|
||||
void operator()(const QMetaObject *modelMetaObject, ModelObjectType *modelObject) const
|
||||
{
|
||||
const int end = modelMetaObject->propertyCount() + modelMetaObject->propertyOffset();
|
||||
for (int i = modelMetaObject->propertyOffset(); i < end; ++i) {
|
||||
|
@ -982,7 +983,18 @@ public:
|
|||
QQmlAnyBinding reverse = QQmlPropertyToPropertyBinding::create(
|
||||
engine, targetProp, sourceProp);
|
||||
reverse.setSticky();
|
||||
reverse.installOn(sourceProp);
|
||||
if constexpr (std::is_base_of_v<QQmlDelegateModelItem, ModelObjectType>) {
|
||||
// Temporarily take away the metaobject so that the property can't actually be
|
||||
// written. It shouldn't be written since we've just synchronized it the other way
|
||||
// when installing the "forward" binding.
|
||||
QQmlDelegateModelReadOnlyMetaObject readonly(modelObject, i);
|
||||
reverse.installOn(sourceProp);
|
||||
} else {
|
||||
// It's only not a QQmlDelegateModelItem if the model is actually an ObjectModel.
|
||||
// In that case, we hope that the generic equality check when setting a property
|
||||
// is enough to de-bounce it.
|
||||
reverse.installOn(sourceProp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -344,7 +344,6 @@ void tst_QQmlRangeModel::intRange()
|
|||
QCOMPARE(currentItem->property("currentValue"), oldValue);
|
||||
|
||||
// nothing happened so far, so there shouldn't have been any calls to setData
|
||||
QEXPECT_FAIL("ReadWrite", "Unexpected call to setData", Continue);
|
||||
QCOMPARE(model.setDataCalls, QList<int>{});
|
||||
model.setDataCalls.clear();
|
||||
model.dataCalls.clear();
|
||||
|
@ -383,14 +382,6 @@ void tst_QQmlRangeModel::objectRange()
|
|||
std::vector<Entry *> objects{entry.get()};
|
||||
RangeModel model(&objects);
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
// with ReadWrite, spurious call to setData(RangeModelDataRole) during loading
|
||||
if (writeBack) {
|
||||
QTest::ignoreMessage(QtCriticalMsg,
|
||||
QRegularExpression("Not able to assign QVariant\\(.*\\) to Entry*"));
|
||||
}
|
||||
#endif
|
||||
|
||||
auto view = makeView({
|
||||
{"delegateModelAccess", delegateModelAccess},
|
||||
{"model", QVariant::fromValue(&model)}
|
||||
|
@ -405,7 +396,6 @@ void tst_QQmlRangeModel::objectRange()
|
|||
QVERIFY(model.dataCalls.contains(Qt::RangeModelDataRole));
|
||||
model.dataCalls.clear();
|
||||
// there shouldn't have been any attempts to write yet
|
||||
QEXPECT_FAIL("ReadWrite", "Premature calls to setData()", Continue);
|
||||
QCOMPARE(model.setDataCalls, QList<int>{});
|
||||
model.setDataCalls.clear();
|
||||
|
||||
|
|
Loading…
Reference in New Issue