QPropertyAnimation: fix binding loops

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

Task-number: QTBUG-116346
Change-Id: I04abc394f4406dc0fa75c55a9093e10c27a20c30
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
(cherry picked from commit b6b94111c77df60c425617d0d76a6574906294c0)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Ivan Solovev 2023-08-25 13:17:16 +02:00 committed by Qt Cherry-pick Bot
parent 84dbb356ef
commit fd7418cfb5

View File

@ -60,7 +60,8 @@ QT_BEGIN_NAMESPACE
void QPropertyAnimationPrivate::updateMetaProperty() void QPropertyAnimationPrivate::updateMetaProperty()
{ {
if (!targetObject || propertyName.value().isEmpty()) { const QObject *target = targetObject.valueBypassingBindings();
if (!target || propertyName.value().isEmpty()) {
propertyType = QMetaType::UnknownType; propertyType = QMetaType::UnknownType;
propertyIndex = -1; propertyIndex = -1;
return; return;
@ -68,19 +69,19 @@ void QPropertyAnimationPrivate::updateMetaProperty()
//propertyType will be set to a valid type only if there is a Q_PROPERTY //propertyType will be set to a valid type only if there is a Q_PROPERTY
//otherwise it will be set to QVariant::Invalid at the end of this function //otherwise it will be set to QVariant::Invalid at the end of this function
propertyType = targetObject->property(propertyName.value()).userType(); propertyType = target->property(propertyName.value()).userType();
propertyIndex = targetObject->metaObject()->indexOfProperty(propertyName.value()); propertyIndex = target->metaObject()->indexOfProperty(propertyName.value());
if (propertyType != QMetaType::UnknownType) if (propertyType != QMetaType::UnknownType)
convertValues(propertyType); convertValues(propertyType);
if (propertyIndex == -1) { if (propertyIndex == -1) {
//there is no Q_PROPERTY on the object //there is no Q_PROPERTY on the object
propertyType = QMetaType::UnknownType; propertyType = QMetaType::UnknownType;
if (!targetObject->dynamicPropertyNames().contains(propertyName)) if (!target->dynamicPropertyNames().contains(propertyName))
qWarning("QPropertyAnimation: you're trying to animate a non-existing property %s of " qWarning("QPropertyAnimation: you're trying to animate a non-existing property %s of "
"your QObject", "your QObject",
propertyName.value().constData()); propertyName.value().constData());
} else if (!targetObject->metaObject()->property(propertyIndex).isWritable()) { } else if (!target->metaObject()->property(propertyIndex).isWritable()) {
qWarning("QPropertyAnimation: you're trying to animate the non-writable property %s of " qWarning("QPropertyAnimation: you're trying to animate the non-writable property %s of "
"your QObject", "your QObject",
propertyName.value().constData()); propertyName.value().constData());
@ -163,15 +164,16 @@ void QPropertyAnimation::setTargetObject(QObject *target)
} }
d->targetObject.removeBindingUnlessInWrapper(); d->targetObject.removeBindingUnlessInWrapper();
if (d->targetObject == target) const QObject *oldTarget = d->targetObject.valueBypassingBindings();
if (oldTarget == target)
return; return;
if (d->targetObject != nullptr) if (oldTarget != nullptr)
QObject::disconnect(d->targetObject, &QObject::destroyed, this, nullptr); QObject::disconnect(oldTarget, &QObject::destroyed, this, nullptr);
d->targetObject.setValueBypassingBindings(target); d->targetObject.setValueBypassingBindings(target);
if (d->targetObject != nullptr) { if (target != nullptr) {
QObject::connect(d->targetObject, &QObject::destroyed, this, QObject::connect(target, &QObject::destroyed, this,
[d] { d->targetObjectDestroyed(); }); [d] { d->targetObjectDestroyed(); });
} }
d->updateMetaProperty(); d->updateMetaProperty();
@ -201,7 +203,7 @@ void QPropertyAnimation::setPropertyName(const QByteArray &propertyName)
d->propertyName.removeBindingUnlessInWrapper(); d->propertyName.removeBindingUnlessInWrapper();
if (d->propertyName == propertyName) if (d->propertyName.valueBypassingBindings() == propertyName)
return; return;
d->propertyName.setValueBypassingBindings(propertyName); d->propertyName.setValueBypassingBindings(propertyName);