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 <ulf.hermann@qt.io>
bb10
Fabian Kosmale 2021-04-23 14:51:40 +02:00
parent 98b4f4bc4d
commit ba561efa9d
2 changed files with 31 additions and 4 deletions

View File

@ -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

View File

@ -484,6 +484,8 @@ struct QBindableInterface
MakeBinding makeBinding;
SetObserver setObserver;
GetMetaType metaType;
static constexpr quintptr MetaTypeAccessorFlag = 0x1;
};
template<typename Property, typename = void>
@ -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<void *>(quintptr(&result) | QtPrivate::QBindableInterface::MetaTypeAccessorFlag));
return result;
}
};
template<typename T>
@ -678,7 +695,7 @@ public:
using QUntypedBindable::QUntypedBindable;
explicit QBindable(const QUntypedBindable &b) : QUntypedBindable(b)
{
if (iface && iface->metaType() != QMetaType::fromType<T>()) {
if (iface && metaType() != QMetaType::fromType<T>()) {
data = nullptr;
iface = nullptr;
}
@ -701,7 +718,7 @@ public:
using QUntypedBindable::setBinding;
QPropertyBinding<T> setBinding(const QPropertyBinding<T> &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<QPropertyBinding<T> &&>(iface->setBinding(data, binding));