From ba561efa9d4e94032e7b546e92a3dc66c06bec52 Mon Sep 17 00:00:00 2001 From: Fabian Kosmale Date: Fri, 23 Apr 2021 14:51:40 +0200 Subject: [PATCH] Add QUntypedBindable::metaType function This enables checking the metaType of a QUntypedBindable in the public interface. In addition, work around an oversight that can only be fully addressed in Qt 7: The metatype function pointer does not take a QUntypedPropertyData * parameter. However, we need this functionality for an efficient QBindable proxy implementation in declarative (which is needed to implement interceptors there). To work-aronud this in Qt 6, reuse the value getter and turn it into a metatype getter if the value pointer is flagged. Change-Id: Ia3cce08ea761fce57bce59e02212525b996f2fee Reviewed-by: Ulf Hermann --- src/corelib/kernel/qproperty.cpp | 10 ++++++++++ src/corelib/kernel/qproperty.h | 25 +++++++++++++++++++++---- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/corelib/kernel/qproperty.cpp b/src/corelib/kernel/qproperty.cpp index 607048d94b..a1b2f83c5b 100644 --- a/src/corelib/kernel/qproperty.cpp +++ b/src/corelib/kernel/qproperty.cpp @@ -1005,6 +1005,16 @@ QString QPropertyBindingError::description() const Returns \c true if the underlying property has a binding. */ +/*! + \fn QMetaType QUntypedBindable::metaType() const + \since 6.2 + + Returns the metatype of the property from which the QUntypedBindable was created. + If the bindable is invalid, an invalid metatype will be returned. + + \sa isValid(), QUntypedPropertyBinding::valueMetaType() +*/ + /*! \class QBindable \inmodule QtCore diff --git a/src/corelib/kernel/qproperty.h b/src/corelib/kernel/qproperty.h index 9be10c0a31..7924049698 100644 --- a/src/corelib/kernel/qproperty.h +++ b/src/corelib/kernel/qproperty.h @@ -484,6 +484,8 @@ struct QBindableInterface MakeBinding makeBinding; SetObserver setObserver; GetMetaType metaType; + + static constexpr quintptr MetaTypeAccessorFlag = 0x1; }; template @@ -650,9 +652,9 @@ public: #endif return false; } - if (!binding.isNull() && binding.valueMetaType() != iface->metaType()) { + if (!binding.isNull() && binding.valueMetaType() != metaType()) { #ifndef QT_NO_DEBUG - QtPrivate::BindableWarnings::printMetaTypeMismatch(iface->metaType(), binding.valueMetaType()); + QtPrivate::BindableWarnings::printMetaTypeMismatch(metaType(), binding.valueMetaType()); #endif return false; } @@ -664,6 +666,21 @@ public: return !binding().isNull(); } + QMetaType metaType() const + { + if (!(iface && data)) + return QMetaType(); + if (iface->metaType) + return iface->metaType(); + // ### Qt 7: Change the metatype function to take data as its argument + // special casing for QML's proxy bindable: allow multiplexing in the getter + // function to retrieve the metatype from data + Q_ASSERT(iface->getter); + QMetaType result; + iface->getter(data, reinterpret_cast(quintptr(&result) | QtPrivate::QBindableInterface::MetaTypeAccessorFlag)); + return result; + } + }; template @@ -678,7 +695,7 @@ public: using QUntypedBindable::QUntypedBindable; explicit QBindable(const QUntypedBindable &b) : QUntypedBindable(b) { - if (iface && iface->metaType() != QMetaType::fromType()) { + if (iface && metaType() != QMetaType::fromType()) { data = nullptr; iface = nullptr; } @@ -701,7 +718,7 @@ public: using QUntypedBindable::setBinding; QPropertyBinding setBinding(const QPropertyBinding &binding) { - Q_ASSERT(!iface || binding.isNull() || binding.valueMetaType() == iface->metaType()); + Q_ASSERT(!iface || binding.isNull() || binding.valueMetaType() == metaType()); if (iface && iface->setBinding) return static_cast &&>(iface->setBinding(data, binding));