qmlobject_cast: Make it useful again

The Qt 6 implementation of qmlobject_cast simply accessed the metaObject
of the object (canConvert -> QQmlMetaObject::QQmlMetaObject(QObject*)
-> QOject:metaObject). That would directly cause the creation of
dynamic meta-objects, if they weren't created so far.

Given that we still didn't get rid of the property-cache in QML, use it
to optimize this code path:
If the object has some associated QQmlData, retrieve it and check if we
have a  property cache. If we do, retrieve the first C++ meta object
from it. We can safely ignore any dynamic meta-objects as T must be a
static meta-object. Then do the normal inheritance check with the first
C++ meta-object and T::staticMetaObject.
If we don't have a property cache, fall back to the previous
implementation (but without the QQmlMetaObject detour).

Change-Id: Ie23d1a3dac6bf343ee2bc31e04c4592681ad9995
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
This commit is contained in:
Fabian Kosmale 2023-03-16 15:30:57 +01:00 committed by Shawn Rutledge
parent 51c6db3f3d
commit 677cd24de6
2 changed files with 15 additions and 1 deletions

View File

@ -596,6 +596,16 @@ void QQmlApplication::setDomain(const QString &arg)
QCoreApplication::instance()->setOrganizationDomain(arg);
}
bool qmlobject_can_cast(QObject *object, const QMetaObject *mo)
{
Q_ASSERT(object);
Q_ASSERT(mo);
auto ddata = QQmlData::get(object, false);
if (!ddata || ! ddata->propertyCache)
return object->metaObject()->inherits(mo);
return ddata->propertyCache->firstCppMetaObject()->inherits(mo);
}
QT_END_NAMESPACE
#include "moc_qqmlglobal_p.cpp"

View File

@ -122,6 +122,8 @@ do { \
QMetaObject::disconnect(sender, signalIdx, receiver, methodIdx); \
} while (0)
Q_QML_PRIVATE_EXPORT bool qmlobject_can_cast(QObject *object, const QMetaObject *mo);
/*!
This method is identical to qobject_cast<T>() except that it does not require lazy
QMetaObjects to be built, so should be preferred in all QML code that might interact
@ -137,7 +139,9 @@ do { \
template<class T>
T qmlobject_cast(QObject *object)
{
if (object && QQmlMetaObject::canConvert(object, &reinterpret_cast<T>(object)->staticMetaObject))
if (!object)
return nullptr;
if (qmlobject_can_cast(object, &(std::remove_pointer_t<T>::staticMetaObject)))
return static_cast<T>(object);
else
return nullptr;