aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmlproperty.cpp
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2022-06-21 16:25:45 +0200
committerUlf Hermann <ulf.hermann@qt.io>2022-06-24 14:47:46 +0200
commit1b6069798aa7088457eb5e033aa2fa1d809ec3e4 (patch)
tree6a84044bf7435f2f934c21d5db43239ba5528f73 /src/qml/qml/qqmlproperty.cpp
parent34e40275acd87e2d6cbcb28d5288074184cbe98f (diff)
Allow resetting value type properties
Fixes: QTBUG-60909 Change-Id: I589c0b30cead134f746def2ffc853ff43d2598e0 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Sami Shalayel <sami.shalayel@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/qml/qqmlproperty.cpp')
-rw-r--r--src/qml/qml/qqmlproperty.cpp146
1 files changed, 103 insertions, 43 deletions
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index f2b4cc85ed..6925af297f 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -1259,67 +1259,118 @@ bool QQmlPropertyPrivate::writeValueProperty(const QVariant &value, QQmlProperty
return writeValueProperty(object, core, valueTypeData, value, effectiveContext(), flags);
}
-bool
-QQmlPropertyPrivate::writeValueProperty(QObject *object,
- const QQmlPropertyData &core,
- const QQmlPropertyData &valueTypeData,
- const QVariant &value,
- const QQmlRefPointer<QQmlContextData> &context,
- QQmlPropertyData::WriteFlags flags)
+static void removeValuePropertyBinding(
+ QObject *object, const QQmlPropertyData &core,
+ const QQmlPropertyData &valueTypeData, QQmlPropertyData::WriteFlags flags)
{
// Remove any existing bindings on this property
- if (!(flags & QQmlPropertyData::DontRemoveBinding) && object)
- removeBinding(object, encodedIndex(core, valueTypeData));
-
- bool rv = false;
- if (valueTypeData.isValid()) {
- auto doWrite = [&](QQmlGadgetPtrWrapper *wrapper) {
- wrapper->read(object, core.coreIndex());
- rv = write(wrapper, valueTypeData, value, context, flags);
- wrapper->write(object, core.coreIndex(), flags);
- };
-
- QQmlGadgetPtrWrapper *wrapper = context
- ? QQmlGadgetPtrWrapper::instance(context->engine(), core.propType())
- : nullptr;
- if (wrapper) {
- doWrite(wrapper);
- } else if (QQmlValueType *valueType = QQmlMetaType::valueType(core.propType())) {
- QQmlGadgetPtrWrapper wrapper(valueType, nullptr);
- doWrite(&wrapper);
- }
-
- } else {
- rv = write(object, core, value, context, flags);
+ if (!(flags & QQmlPropertyData::DontRemoveBinding) && object) {
+ QQmlPropertyPrivate::removeBinding(
+ object, QQmlPropertyPrivate::encodedIndex(core, valueTypeData));
}
+}
+template<typename Op>
+bool changePropertyAndWriteBack(
+ QObject *object, int coreIndex, QQmlGadgetPtrWrapper *wrapper,
+ QQmlPropertyData::WriteFlags flags, Op op)
+{
+ wrapper->read(object, coreIndex);
+ const bool rv = op(wrapper);
+ wrapper->write(object, coreIndex, flags);
return rv;
}
-bool QQmlPropertyPrivate::write(
- QObject *object, const QQmlPropertyData &property, const QVariant &value,
- const QQmlRefPointer<QQmlContextData> &context, QQmlPropertyData::WriteFlags flags)
+template<typename Op>
+bool changeThroughGadgetPtrWrapper(
+ QObject *object, const QQmlPropertyData &core,
+ const QQmlRefPointer<QQmlContextData> &context, QQmlPropertyData::WriteFlags flags,
+ Op op)
{
- const QMetaType propertyMetaType = property.propType();
- const QMetaType variantMetaType = value.metaType();
+ if (QQmlGadgetPtrWrapper *wrapper = context
+ ? QQmlGadgetPtrWrapper::instance(context->engine(), core.propType())
+ : nullptr) {
+ return changePropertyAndWriteBack(object, core.coreIndex(), wrapper, flags, op);
+ }
+
+ if (QQmlValueType *valueType = QQmlMetaType::valueType(core.propType())) {
+ QQmlGadgetPtrWrapper wrapper(valueType, nullptr);
+ return changePropertyAndWriteBack(object, core.coreIndex(), &wrapper, flags, op);
+ }
+
+ return false;
+}
+
+bool QQmlPropertyPrivate::writeValueProperty(
+ QObject *object, const QQmlPropertyData &core, const QQmlPropertyData &valueTypeData,
+ const QVariant &value, const QQmlRefPointer<QQmlContextData> &context,
+ QQmlPropertyData::WriteFlags flags)
+{
+ removeValuePropertyBinding(object, core, valueTypeData, flags);
+
+ if (!valueTypeData.isValid())
+ return write(object, core, value, context, flags);
+
+ return changeThroughGadgetPtrWrapper(object, core, context, flags,
+ [&](QQmlGadgetPtrWrapper *wrapper) {
+ return write(wrapper, valueTypeData, value, context, flags);
+ });
+}
+
+bool QQmlPropertyPrivate::resetValueProperty(
+ QObject *object, const QQmlPropertyData &core, const QQmlPropertyData &valueTypeData,
+ const QQmlRefPointer<QQmlContextData> &context, QQmlPropertyData::WriteFlags flags)
+{
+ removeValuePropertyBinding(object, core, valueTypeData, flags);
+
+ if (!valueTypeData.isValid())
+ return reset(object, core, flags);
+
+ return changeThroughGadgetPtrWrapper(object, core, context, flags,
+ [&](QQmlGadgetPtrWrapper *wrapper) {
+ return reset(wrapper, valueTypeData, flags);
+ });
+}
+
+// We need to prevent new-style bindings from being removed.
+struct BindingFixer
+{
+ Q_DISABLE_COPY_MOVE(BindingFixer);
+
+ BindingFixer(QObject *object, const QQmlPropertyData &property,
+ QQmlPropertyData::WriteFlags flags)
+ {
+ if (!property.isBindable() || !(flags & QQmlPropertyData::DontRemoveBinding))
+ return;
- // we need to prevent new-style bindings from being removed
- QUntypedPropertyBinding untypedBinding;
- if (property.isBindable() && (flags & QQmlPropertyData::DontRemoveBinding)) {
QUntypedBindable bindable;
void *argv[] = {&bindable};
QMetaObject::metacall(object, QMetaObject::BindableProperty, property.coreIndex(), argv);
untypedBinding = bindable.binding();
- auto priv = QPropertyBindingPrivate::get(untypedBinding);
- if (priv)
- priv->setSticky(true);
+ if (auto priv = QPropertyBindingPrivate::get(untypedBinding))
+ priv->setSticky(true);
}
- auto bindingFixer = qScopeGuard([&](){
+
+ ~BindingFixer()
+ {
if (untypedBinding.isNull())
return;
auto priv = QPropertyBindingPrivate::get(untypedBinding);
priv->setSticky(false);
- });
+ }
+
+private:
+ QUntypedPropertyBinding untypedBinding;
+};
+
+bool QQmlPropertyPrivate::write(
+ QObject *object, const QQmlPropertyData &property, const QVariant &value,
+ const QQmlRefPointer<QQmlContextData> &context, QQmlPropertyData::WriteFlags flags)
+{
+ const QMetaType propertyMetaType = property.propType();
+ const QMetaType variantMetaType = value.metaType();
+
+ const BindingFixer bindingFixer(object, property, flags);
if (property.isEnum()) {
QMetaProperty prop = object->metaObject()->property(property.coreIndex());
@@ -1565,6 +1616,15 @@ bool QQmlPropertyPrivate::write(
return true;
}
+bool QQmlPropertyPrivate::reset(
+ QObject *object, const QQmlPropertyData &property,
+ QQmlPropertyData::WriteFlags flags)
+{
+ const BindingFixer bindingFixer(object, property, flags);
+ property.resetProperty(object, flags);
+ return true;
+}
+
QQmlMetaObject QQmlPropertyPrivate::rawMetaObjectForType(QMetaType metaType)
{
if (metaType.flags() & QMetaType::PointerToQObject) {