aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2021-02-10 19:20:21 +0100
committerUlf Hermann <ulf.hermann@qt.io>2021-02-12 11:36:25 +0100
commit25f765cbd9067c1ebb61721efbe471d9100d9237 (patch)
treedff3b8ed6cdfefca12b1ef6d9759d91ad040e018
parent953ea29328db71ac7a8ef177ecbc2329367b9170 (diff)
Unregister value types when tearing down QML types
Move the value type registry into QQmlMetaTypeData. This way we can conveniently drop the relevant entries when unregistering a type. Fixes: QTBUG-86946 Change-Id: Id024a34a8b2b622fd9417fc0e52864b43c66cc01 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp4
-rw-r--r--src/qml/jsruntime/qv4engine.cpp4
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp8
-rw-r--r--src/qml/qml/qqmlbinding.cpp2
-rw-r--r--src/qml/qml/qqmlengine_p.h2
-rw-r--r--src/qml/qml/qqmlmetatype.cpp117
-rw-r--r--src/qml/qml/qqmlmetatype_p.h5
-rw-r--r--src/qml/qml/qqmlmetatypedata.cpp1
-rw-r--r--src/qml/qml/qqmlmetatypedata_p.h2
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp2
-rw-r--r--src/qml/qml/qqmlproperty.cpp14
-rw-r--r--src/qml/qml/qqmlpropertycachecreator.cpp2
-rw-r--r--src/qml/qml/qqmlpropertycachecreator_p.h6
-rw-r--r--src/qml/qml/qqmlpropertyvalidator.cpp10
-rw-r--r--src/qml/qml/qqmltypecompiler.cpp2
-rw-r--r--src/qml/qml/qqmlvaluetype.cpp167
-rw-r--r--src/qml/qml/qqmlvaluetype_p.h8
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp10
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp2
-rw-r--r--src/quick/util/qquickanimation.cpp2
-rw-r--r--tests/auto/qml/qqmlpropertycache/BLACKLIST2
-rw-r--r--tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp2
-rw-r--r--tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp6
23 files changed, 162 insertions, 218 deletions
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
index 971404c831..be9db84272 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
@@ -258,8 +258,8 @@ QVariant QQmlEngineDebugServiceImpl::valueContents(QVariant value) const
case QMetaType::QJsonDocument:
return value.toJsonDocument().toVariant();
default:
- if (QQmlValueTypeFactory::isValueType(metaType)) {
- const QMetaObject *mo = QQmlValueTypeFactory::metaObjectForMetaType(metaType);
+ if (QQmlMetaType::isValueType(metaType)) {
+ const QMetaObject *mo = QQmlMetaType::metaObjectForMetaType(metaType);
if (mo) {
int toStringIndex = mo->indexOfMethod("toString()");
if (toStringIndex != -1) {
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 320dc15a15..7ae281fb1a 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -1808,7 +1808,7 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
break;
}
- if (const QMetaObject *vtmo = QQmlValueTypeFactory::metaObjectForMetaType(metaType))
+ if (const QMetaObject *vtmo = QQmlMetaType::metaObjectForMetaType(metaType))
return QV4::QQmlValueTypeWrapper::create(this, variant, vtmo, metaType);
} else {
QV4::Scope scope(this);
@@ -1855,7 +1855,7 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
return sequentialIterableToJS(this, lst);
}
- if (const QMetaObject *vtmo = QQmlValueTypeFactory::metaObjectForMetaType(metaType))
+ if (const QMetaObject *vtmo = QQmlMetaType::metaObjectForMetaType(metaType))
return QV4::QQmlValueTypeWrapper::create(this, variant, vtmo, metaType);
}
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 98d69b2f80..55d62a2a8b 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -178,14 +178,14 @@ static QV4::ReturnedValue loadProperty(QV4::ExecutionEngine *v4, QObject *object
QVariant v;
property.readProperty(object, &v);
- if (QQmlValueTypeFactory::isValueType(v.metaType())) {
- if (const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(v.metaType()))
+ if (QQmlMetaType::isValueType(v.metaType())) {
+ if (const QMetaObject *valueTypeMetaObject = QQmlMetaType::metaObjectForMetaType(v.metaType()))
return QV4::QQmlValueTypeWrapper::create(v4, object, property.coreIndex(), valueTypeMetaObject, v.metaType()); // VariantReference value-type.
}
return scope.engine->fromVariant(v);
- } else if (QQmlValueTypeFactory::isValueType(propMetaType)) {
- if (const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(propMetaType))
+ } else if (QQmlMetaType::isValueType(propMetaType)) {
+ if (const QMetaObject *valueTypeMetaObject = QQmlMetaType::metaObjectForMetaType(propMetaType))
return QV4::QQmlValueTypeWrapper::create(v4, object, property.coreIndex(), valueTypeMetaObject, propMetaType);
} else {
#if QT_CONFIG(qml_sequence_object)
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index 68764f1052..69ac63b0ad 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -630,7 +630,7 @@ void QQmlBinding::getPropertyData(QQmlPropertyData **propertyData, QQmlPropertyD
Q_ASSERT(*propertyData);
if (Q_UNLIKELY(m_targetIndex.hasValueTypeIndex() && valueTypeData)) {
- const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType((*propertyData)->propType());
+ const QMetaObject *valueTypeMetaObject = QQmlMetaType::metaObjectForMetaType((*propertyData)->propType());
Q_ASSERT(valueTypeMetaObject);
QMetaProperty vtProp = valueTypeMetaObject->property(m_targetIndex.valueTypeIndex());
valueTypeData->setFlags(QQmlPropertyData::flagsForProperty(vtProp));
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index 9e9d24e90b..b7073ffcfd 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -291,7 +291,7 @@ public:
if (it != cachedValueTypeInstances.end())
return *it;
- if (QQmlValueType *valueType = QQmlValueTypeFactory::valueType(type)) {
+ if (QQmlValueType *valueType = QQmlMetaType::valueType(type)) {
QQmlGadgetPtrWrapper *instance = new QQmlGadgetPtrWrapper(valueType, q_func());
cachedValueTypeInstances.insert(typeIndex, instance);
return instance;
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index 16aafac6d1..7ce57c8d9f 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -44,8 +44,13 @@
#include <private/qqmltype_p_p.h>
#include <private/qqmltypeloader_p.h>
#include <private/qqmlextensionplugin_p.h>
+#include <private/qqmlvaluetype_p.h>
#include <private/qv4executablecompilationunit_p.h>
+#if QT_CONFIG(qml_itemmodel)
+#include <private/qqmlmodelindexvaluetype_p.h>
+#endif
+
#include <QtCore/qcoreapplication.h>
#include <QtCore/qmutex.h>
#include <QtCore/qloggingcategory.h>
@@ -629,11 +634,18 @@ CompositeMetaTypeIds QQmlMetaType::registerInternalCompositeType(const QByteArra
void QQmlMetaType::unregisterInternalCompositeType(const CompositeMetaTypeIds &typeIds)
{
- QQmlMetaTypeDataPtr data;
- data->qmlLists.remove(typeIds.listId.id());
QMetaType metaType(typeIds.id);
- QMetaType::unregisterMetaType(metaType);
QMetaType listMetaType(typeIds.listId);
+
+ QQmlMetaTypeDataPtr data;
+
+ if (QQmlValueType *vt = data->metaTypeToValueType.take(metaType.id()))
+ delete vt;
+ if (QQmlValueType *vt = data->metaTypeToValueType.take(listMetaType.id()))
+ delete vt;
+
+ data->qmlLists.remove(listMetaType.id());
+ QMetaType::unregisterMetaType(metaType);
QMetaType::unregisterMetaType(listMetaType);
delete static_cast<const QQmlMetaTypeInterface *>(metaType.iface());
delete static_cast<const QQmlMetaTypeInterface *>(listMetaType.iface());
@@ -1640,4 +1652,103 @@ QList<QQmlProxyMetaObject::ProxyData> QQmlMetaType::proxyData(const QMetaObject
return metaObjects;
}
+bool isInternalType(int idx)
+{
+ // Qt internal types
+ switch (idx) {
+ case QMetaType::UnknownType:
+ case QMetaType::QStringList:
+ case QMetaType::QObjectStar:
+ case QMetaType::VoidStar:
+ case QMetaType::Nullptr:
+ case QMetaType::QVariant:
+ case QMetaType::QLocale:
+ case QMetaType::QImage: // scarce type, keep as QVariant
+ case QMetaType::QPixmap: // scarce type, keep as QVariant
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool QQmlMetaType::isValueType(QMetaType type)
+{
+ if (!type.isValid() || isInternalType(type.id()))
+ return false;
+
+ return valueType(type) != nullptr;
+}
+
+const QMetaObject *QQmlMetaType::metaObjectForMetaType(QMetaType metaType)
+{
+ const int t = metaType.id();
+ switch (t) {
+ case QMetaType::QPoint:
+ return &QQmlPointValueType::staticMetaObject;
+ case QMetaType::QPointF:
+ return &QQmlPointFValueType::staticMetaObject;
+ case QMetaType::QSize:
+ return &QQmlSizeValueType::staticMetaObject;
+ case QMetaType::QSizeF:
+ return &QQmlSizeFValueType::staticMetaObject;
+ case QMetaType::QRect:
+ return &QQmlRectValueType::staticMetaObject;
+ case QMetaType::QRectF:
+ return &QQmlRectFValueType::staticMetaObject;
+#if QT_CONFIG(easingcurve)
+ case QMetaType::QEasingCurve:
+ return &QQmlEasingValueType::staticMetaObject;
+#endif
+#if QT_CONFIG(qml_itemmodel)
+ case QMetaType::QModelIndex:
+ return &QQmlModelIndexValueType::staticMetaObject;
+ case QMetaType::QPersistentModelIndex:
+ return &QQmlPersistentModelIndexValueType::staticMetaObject;
+#endif
+ default:
+#if QT_CONFIG(qml_itemmodel)
+ if (metaType == QMetaType::fromType<QItemSelectionRange>())
+ return &QQmlItemSelectionRangeValueType::staticMetaObject;
+#endif
+ if (metaType == QMetaType::fromType<QQmlProperty>())
+ return &QQmlPropertyValueType::staticMetaObject;
+ break;
+ }
+
+ // It doesn't have to be a gadget for a QML type to exist, but we don't want to
+ // call QObject pointers value types. Explicitly registered types also override
+ // the implicit use of gadgets.
+ if (!(metaType.flags() & QMetaType::PointerToQObject)) {
+ const QQmlType qmlType = QQmlMetaType::qmlType(t, QQmlMetaType::TypeIdCategory::MetaType);
+
+ // Prefer the extension meta object.
+ // Extensions allow registration of non-gadget value types.
+ if (const QMetaObject *extensionMetaObject = qmlType.extensionMetaObject())
+ return extensionMetaObject;
+
+ if (const QMetaObject *qmlTypeMetaObject = qmlType.metaObject())
+ return qmlTypeMetaObject;
+ }
+
+ // If it _is_ a gadget, we can just use it.
+ if (metaType.flags() & QMetaType::IsGadget)
+ return metaType.metaObject();
+
+ return nullptr;
+}
+
+QQmlValueType *QQmlMetaType::valueType(QMetaType type)
+{
+ const int idx = type.id();
+ QQmlMetaTypeDataPtr data;
+
+ const auto it = data->metaTypeToValueType.constFind(idx);
+ if (it != data->metaTypeToValueType.constEnd())
+ return *it;
+
+ if (const QMetaObject *mo = metaObjectForMetaType(type))
+ return *data->metaTypeToValueType.insert(idx, new QQmlValueType(idx, mo));
+ return *data->metaTypeToValueType.insert(idx, nullptr);
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
index 383952c41e..0cfe313421 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE
class QQmlTypeModule;
class QRecursiveMutex;
class QQmlError;
+class QQmlValueType;
namespace QV4 { class ExecutableCompilationUnit; }
@@ -262,6 +263,10 @@ public:
static bool qmlRegisterModuleTypes(const QString &uri);
static int qmlRegisteredListTypeCount();
+
+ static bool isValueType(QMetaType type);
+ static QQmlValueType *valueType(QMetaType metaType);
+ static const QMetaObject *metaObjectForMetaType(QMetaType type);
};
Q_DECLARE_TYPEINFO(QQmlMetaType, Q_RELOCATABLE_TYPE);
diff --git a/src/qml/qml/qqmlmetatypedata.cpp b/src/qml/qml/qqmlmetatypedata.cpp
index e973226053..4be26acdc6 100644
--- a/src/qml/qml/qqmlmetatypedata.cpp
+++ b/src/qml/qml/qqmlmetatypedata.cpp
@@ -57,6 +57,7 @@ QQmlMetaTypeData::~QQmlMetaTypeData()
// Do this before the attached properties disappear.
types.clear();
undeletableTypes.clear();
+ qDeleteAll(metaTypeToValueType);
}
// This expects a "fresh" QQmlTypePrivate and adopts its reference.
diff --git a/src/qml/qml/qqmlmetatypedata_p.h b/src/qml/qml/qqmlmetatypedata_p.h
index ed7c81639a..9719ec1bb4 100644
--- a/src/qml/qml/qqmlmetatypedata_p.h
+++ b/src/qml/qml/qqmlmetatypedata_p.h
@@ -54,6 +54,7 @@
#include <private/qqmltype_p.h>
#include <private/qqmlmetatype_p.h>
#include <private/qhashedstring_p.h>
+#include <private/qqmlvaluetype_p.h>
#include <QtCore/qset.h>
#include <QtCore/qvector.h>
@@ -85,6 +86,7 @@ struct QQmlMetaTypeData
typedef QHash<int, QQmlMetaType::StringConverter> StringConverters;
StringConverters stringConverters;
QVector<QHash<QTypeRevision, QQmlRefPointer<QQmlPropertyCache>>> typePropertyCaches;
+ QHash<int, QQmlValueType *> metaTypeToValueType;
struct VersionedUri {
VersionedUri() = default;
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 47d1b5e785..987b9a617e 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -846,7 +846,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper
const QQmlPropertyData *valueTypeProperty = nullptr;
QObject *bindingTarget = _bindingTarget;
- if (QQmlValueTypeFactory::isValueType(bindingProperty->propType())) {
+ if (QQmlMetaType::isValueType(bindingProperty->propType())) {
valueType = QQmlGadgetPtrWrapper::instance(engine, bindingProperty->propType());
if (!valueType) {
recordError(binding->location, tr("Cannot set properties on %1 as it is null").arg(stringAt(binding->propertyNameIndex)));
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index 2d503b053c..d178caf320 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -316,9 +316,9 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
if (property->isFunction())
return; // Not an object property
- if (ii == (path.count() - 2) && QQmlValueTypeFactory::isValueType(property->propType())) {
+ if (ii == (path.count() - 2) && QQmlMetaType::isValueType(property->propType())) {
// We're now at a value type property
- const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(property->propType());
+ const QMetaObject *valueTypeMetaObject = QQmlMetaType::metaObjectForMetaType(property->propType());
if (!valueTypeMetaObject) return; // Not a value type
int idx = valueTypeMetaObject->indexOfProperty(path.last().toUtf8().constData());
@@ -480,7 +480,7 @@ QQmlPropertyPrivate::propertyTypeCategory() const
QMetaType type = propertyType();
if (!type.isValid())
return QQmlProperty::InvalidCategory;
- else if (QQmlValueTypeFactory::isValueType(type))
+ else if (QQmlMetaType::isValueType(type))
return QQmlProperty::Normal;
else if (core.isQObject())
return QQmlProperty::Object;
@@ -502,7 +502,7 @@ const char *QQmlProperty::propertyTypeName() const
if (!d)
return nullptr;
if (d->isValueType()) {
- const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(d->core.propType());
+ const QMetaObject *valueTypeMetaObject = QQmlMetaType::metaObjectForMetaType(d->core.propType());
Q_ASSERT(valueTypeMetaObject);
return valueTypeMetaObject->property(d->valueTypeData.coreIndex()).typeName();
} else if (d->object && type() & Property && d->core.isValid()) {
@@ -681,7 +681,7 @@ QString QQmlProperty::name() const
// ###
if (!d->object) {
} else if (d->isValueType()) {
- const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(d->core.propType());
+ const QMetaObject *valueTypeMetaObject = QQmlMetaType::metaObjectForMetaType(d->core.propType());
Q_ASSERT(valueTypeMetaObject);
const char *vtName = valueTypeMetaObject->property(d->valueTypeData.coreIndex()).name();
@@ -1061,7 +1061,7 @@ QVariant QQmlPropertyPrivate::readValueProperty()
if (isValueType()) {
if (QQmlGadgetPtrWrapper *wrapper = QQmlGadgetPtrWrapper::instance(engine, core.propType()))
return doRead(wrapper);
- if (QQmlValueType *valueType = QQmlValueTypeFactory::valueType(core.propType())) {
+ if (QQmlValueType *valueType = QQmlMetaType::valueType(core.propType())) {
QQmlGadgetPtrWrapper wrapper(valueType, nullptr);
return doRead(&wrapper);
}
@@ -1201,7 +1201,7 @@ QQmlPropertyPrivate::writeValueProperty(QObject *object,
: nullptr;
if (wrapper) {
doWrite(wrapper);
- } else if (QQmlValueType *valueType = QQmlValueTypeFactory::valueType(core.propType())) {
+ } else if (QQmlValueType *valueType = QQmlMetaType::valueType(core.propType())) {
QQmlGadgetPtrWrapper wrapper(valueType, nullptr);
doWrite(&wrapper);
}
diff --git a/src/qml/qml/qqmlpropertycachecreator.cpp b/src/qml/qml/qqmlpropertycachecreator.cpp
index 141aa80f85..5b44bd4f9d 100644
--- a/src/qml/qml/qqmlpropertycachecreator.cpp
+++ b/src/qml/qml/qqmlpropertycachecreator.cpp
@@ -132,7 +132,7 @@ QQmlRefPointer<QQmlPropertyCache> QQmlBindingInstantiationContext::instantiating
// There is another overload that takes no version, which we shall not use here.
return enginePrivate->rawPropertyCacheForType(instantiatingProperty->propType().id(),
instantiatingProperty->typeVersion());
- } else if (const QMetaObject *vtmo = QQmlValueTypeFactory::metaObjectForMetaType(instantiatingProperty->propType())) {
+ } else if (const QMetaObject *vtmo = QQmlMetaType::metaObjectForMetaType(instantiatingProperty->propType())) {
return enginePrivate->cache(vtmo, instantiatingProperty->typeVersion());
}
}
diff --git a/src/qml/qml/qqmlpropertycachecreator_p.h b/src/qml/qml/qqmlpropertycachecreator_p.h
index ce1a830979..ca2f2effcd 100644
--- a/src/qml/qml/qqmlpropertycachecreator_p.h
+++ b/src/qml/qml/qqmlpropertycachecreator_p.h
@@ -239,7 +239,7 @@ inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObjectRecur
// group properties and value type group properties. For the former the base type is derived from
// the property that references us, for the latter we only need a meta-object on the referencing object
// because interceptors can't go to the shared value type instances.
- if (context.instantiatingProperty && QQmlValueTypeFactory::isValueType(context.instantiatingProperty->propType())) {
+ if (context.instantiatingProperty && QQmlMetaType::isValueType(context.instantiatingProperty->propType())) {
if (!propertyCaches->needsVMEMetaObject(context.referencingObjectIndex)) {
const CompiledObject *obj = objectContainer->objectAt(context.referencingObjectIndex);
auto *typeRef = objectContainer->resolvedType(obj->inheritedTypeNameIndex);
@@ -853,7 +853,7 @@ inline QQmlError QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataFor
Q_ASSERT(targetProperty);
// for deep aliases, valueTypeIndex is always set
- if (!QQmlValueTypeFactory::isValueType(targetProperty->propType()) && valueTypeIndex != -1) {
+ if (!QQmlMetaType::isValueType(targetProperty->propType()) && valueTypeIndex != -1) {
// deep alias property
*type = targetProperty->propType();
targetCache = enginePriv->propertyCacheForType(type->id());
@@ -878,7 +878,7 @@ inline QQmlError QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataFor
bindable = targetProperty->isBindable();
if (valueTypeIndex != -1) {
- const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(*type);
+ const QMetaObject *valueTypeMetaObject = QQmlMetaType::metaObjectForMetaType(*type);
if (valueTypeMetaObject->property(valueTypeIndex).isEnumType())
*type = QMetaType::fromType<int>();
else
diff --git a/src/qml/qml/qqmlpropertyvalidator.cpp b/src/qml/qml/qqmlpropertyvalidator.cpp
index 590eee2a12..615128bfac 100644
--- a/src/qml/qml/qqmlpropertyvalidator.cpp
+++ b/src/qml/qml/qqmlpropertyvalidator.cpp
@@ -231,7 +231,7 @@ QVector<QQmlError> QQmlPropertyValidator::validateObject(
if (binding->type >= QV4::CompiledData::Binding::Type_Object && (pd || binding->isAttachedProperty())) {
const bool populatingValueTypeGroupProperty
= pd
- && QQmlValueTypeFactory::metaObjectForMetaType(pd->propType())
+ && QQmlMetaType::metaObjectForMetaType(pd->propType())
&& !(binding->flags & QV4::CompiledData::Binding::IsOnAssignment);
const QVector<QQmlError> subObjectValidatorErrors
= validateObject(binding->value.objectIndex, binding,
@@ -284,7 +284,7 @@ QVector<QQmlError> QQmlPropertyValidator::validateObject(
if (loc < (*assignedGroupProperty)->valueLocation)
loc = (*assignedGroupProperty)->valueLocation;
- if (pd && QQmlValueTypeFactory::isValueType(pd->propType()))
+ if (pd && QQmlMetaType::isValueType(pd->propType()))
return recordError(loc, tr("Property has already been assigned a value"));
return recordError(loc, tr("Cannot assign a value directly to a grouped property"));
}
@@ -298,8 +298,8 @@ QVector<QQmlError> QQmlPropertyValidator::validateObject(
if (bindingError.isValid())
return recordError(bindingError);
} else if (binding->isGroupProperty()) {
- if (QQmlValueTypeFactory::isValueType(pd->propType())) {
- if (QQmlValueTypeFactory::metaObjectForMetaType(pd->propType())) {
+ if (QQmlMetaType::isValueType(pd->propType())) {
+ if (QQmlMetaType::metaObjectForMetaType(pd->propType())) {
if (!pd->isWritable()) {
return recordError(binding->location, tr("Invalid property assignment: \"%1\" is a read-only property").arg(name));
}
@@ -752,7 +752,7 @@ QQmlError QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *propert
.arg(typeName));
} else if (propType == qMetaTypeId<QQmlScriptString>()) {
return qQmlCompileError(binding->valueLocation, tr("Invalid property assignment: script expected"));
- } else if (QQmlValueTypeFactory::isValueType(property->propType())) {
+ } else if (QQmlMetaType::isValueType(property->propType())) {
return qQmlCompileError(binding->location, tr("Cannot assign value of type \"%1\" to property \"%2\", expecting an object")
.arg(rhsType()).arg(propertyName));
} else {
diff --git a/src/qml/qml/qqmltypecompiler.cpp b/src/qml/qml/qqmltypecompiler.cpp
index cd89a908b3..e395439c10 100644
--- a/src/qml/qml/qqmltypecompiler.cpp
+++ b/src/qml/qml/qqmltypecompiler.cpp
@@ -1184,7 +1184,7 @@ QQmlComponentAndAliasResolver::resolveAliasesInObject(int objectIndex,
propIdx = QQmlPropertyIndex(targetProperty->coreIndex());
if (!subProperty.isEmpty()) {
- const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(targetProperty->propType());
+ const QMetaObject *valueTypeMetaObject = QQmlMetaType::metaObjectForMetaType(targetProperty->propType());
if (!valueTypeMetaObject) {
// could be a deep alias
bool isDeepAlias = subProperty.at(0).isLower();
diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp
index 150d70ee0c..e1f56d0d59 100644
--- a/src/qml/qml/qqmlvaluetype.cpp
+++ b/src/qml/qml/qqmlvaluetype.cpp
@@ -44,176 +44,9 @@
#include <QtCore/qdebug.h>
#include <private/qqmlengine_p.h>
#include <private/qmetaobjectbuilder_p.h>
-#if QT_CONFIG(qml_itemmodel)
-#include <private/qqmlmodelindexvaluetype_p.h>
-#endif
-
-Q_DECLARE_METATYPE(QQmlProperty)
QT_BEGIN_NAMESPACE
-namespace {
-
-struct QQmlValueTypeFactoryImpl
-{
- QQmlValueTypeFactoryImpl();
- ~QQmlValueTypeFactoryImpl();
-
- bool isValueType(QMetaType type);
-
- const QMetaObject *metaObjectForMetaType(QMetaType metaType);
- QQmlValueType *valueType(QMetaType type);
-
- QHash<int, QQmlValueType *> metaTypeToValueType;
- QReadWriteLock rwLock;
-};
-
-QQmlValueTypeFactoryImpl::QQmlValueTypeFactoryImpl()
-{
-
-#if QT_CONFIG(qml_itemmodel)
- // See types wrapped in qqmlmodelindexvaluetype_p.h
- qRegisterMetaType<QItemSelectionRange>();
-#endif
-}
-
-QQmlValueTypeFactoryImpl::~QQmlValueTypeFactoryImpl()
-{
- qDeleteAll(metaTypeToValueType);
-}
-
-bool isInternalType(int idx)
-{
- // Qt internal types
- switch (idx) {
- case QMetaType::UnknownType:
- case QMetaType::QStringList:
- case QMetaType::QObjectStar:
- case QMetaType::VoidStar:
- case QMetaType::Nullptr:
- case QMetaType::QVariant:
- case QMetaType::QLocale:
- case QMetaType::QImage: // scarce type, keep as QVariant
- case QMetaType::QPixmap: // scarce type, keep as QVariant
- return true;
- default:
- return false;
- }
-}
-
-bool QQmlValueTypeFactoryImpl::isValueType(QMetaType type)
-{
- if (!type.isValid() || isInternalType(type.id()))
- return false;
-
- return valueType(type) != nullptr;
-}
-
-const QMetaObject *QQmlValueTypeFactoryImpl::metaObjectForMetaType(QMetaType metaType)
-{
- const int t = metaType.id();
- switch (t) {
- case QMetaType::QPoint:
- return &QQmlPointValueType::staticMetaObject;
- case QMetaType::QPointF:
- return &QQmlPointFValueType::staticMetaObject;
- case QMetaType::QSize:
- return &QQmlSizeValueType::staticMetaObject;
- case QMetaType::QSizeF:
- return &QQmlSizeFValueType::staticMetaObject;
- case QMetaType::QRect:
- return &QQmlRectValueType::staticMetaObject;
- case QMetaType::QRectF:
- return &QQmlRectFValueType::staticMetaObject;
-#if QT_CONFIG(easingcurve)
- case QMetaType::QEasingCurve:
- return &QQmlEasingValueType::staticMetaObject;
-#endif
-#if QT_CONFIG(qml_itemmodel)
- case QMetaType::QModelIndex:
- return &QQmlModelIndexValueType::staticMetaObject;
- case QMetaType::QPersistentModelIndex:
- return &QQmlPersistentModelIndexValueType::staticMetaObject;
-#endif
- default:
-#if QT_CONFIG(qml_itemmodel)
- if (metaType == QMetaType::fromType<QItemSelectionRange>())
- return &QQmlItemSelectionRangeValueType::staticMetaObject;
-#endif
- if (metaType == QMetaType::fromType<QQmlProperty>())
- return &QQmlPropertyValueType::staticMetaObject;
- break;
- }
-
- // It doesn't have to be a gadget for a QML type to exist, but we don't want to
- // call QObject pointers value types. Explicitly registered types also override
- // the implicit use of gadgets.
- if (!(metaType.flags() & QMetaType::PointerToQObject)) {
- const QQmlType qmlType = QQmlMetaType::qmlType(t, QQmlMetaType::TypeIdCategory::MetaType);
-
- // Prefer the extension meta object.
- // Extensions allow registration of non-gadget value types.
- if (const QMetaObject *extensionMetaObject = qmlType.extensionMetaObject())
- return extensionMetaObject;
-
- if (const QMetaObject *qmlTypeMetaObject = qmlType.metaObject())
- return qmlTypeMetaObject;
- }
-
- // If it _is_ a gadget, we can just use it.
- if (metaType.flags() & QMetaType::IsGadget)
- return metaType.metaObject();
-
- return nullptr;
-}
-
-QQmlValueType *QQmlValueTypeFactoryImpl::valueType(QMetaType type)
-{
- int idx = type.id();
- // Protect the hash with a mutex
- {
- QReadLocker lock(&rwLock);
-
- auto it = metaTypeToValueType.constFind(idx);
- if (it != metaTypeToValueType.constEnd()) {
- return *it;
- }
- }
-
- {
- QWriteLocker lock(&rwLock);
- // TODO: we need try_emplace to avoid the double lookup
- auto it = metaTypeToValueType.find(idx);
- if (it != metaTypeToValueType.end()) // another thread inserted the element before we relocked
- return *it;
- QQmlValueType *vt = nullptr;
- if (const QMetaObject *mo = metaObjectForMetaType(type))
- vt = new QQmlValueType(idx, mo);
- it = metaTypeToValueType.insert(idx, vt);
- return *it;
- }
-
-}
-
-}
-
-Q_GLOBAL_STATIC(QQmlValueTypeFactoryImpl, factoryImpl);
-
-bool QQmlValueTypeFactory::isValueType(QMetaType type)
-{
- return factoryImpl()->isValueType(type);
-}
-
-QQmlValueType *QQmlValueTypeFactory::valueType(QMetaType type)
-{
- return factoryImpl()->valueType(type);
-}
-
-const QMetaObject *QQmlValueTypeFactory::metaObjectForMetaType(QMetaType type)
-{
- return factoryImpl()->metaObjectForMetaType(type);
-}
-
QQmlValueType::QQmlValueType(int typeId, const QMetaObject *gadgetMetaObject)
: metaType(typeId)
{
diff --git a/src/qml/qml/qqmlvaluetype_p.h b/src/qml/qml/qqmlvaluetype_p.h
index 177aa65a57..632405f315 100644
--- a/src/qml/qml/qqmlvaluetype_p.h
+++ b/src/qml/qml/qqmlvaluetype_p.h
@@ -117,14 +117,6 @@ private:
void *m_gadgetPtr = nullptr;
};
-class Q_QML_PRIVATE_EXPORT QQmlValueTypeFactory
-{
-public:
- static bool isValueType(QMetaType type);
- static QQmlValueType *valueType(QMetaType metaType);
- static const QMetaObject *metaObjectForMetaType(QMetaType type);
-};
-
struct Q_QML_PRIVATE_EXPORT QQmlPointFValueType
{
QPointF v;
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index e1b76cdb6f..1b3034d5d9 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -144,15 +144,15 @@ bool QQmlValueTypeReference::readReferenceValue() const
// overwritten with a different type in the meantime.
// We need to modify this reference to the updated value type, if
// possible, or return false if it is not a value type.
- if (QQmlValueTypeFactory::isValueType(variantReferenceType)) {
- const QMetaObject *mo = QQmlValueTypeFactory::metaObjectForMetaType(variantReferenceType);
+ if (QQmlMetaType::isValueType(variantReferenceType)) {
+ const QMetaObject *mo = QQmlMetaType::metaObjectForMetaType(variantReferenceType);
if (d()->gadgetPtr()) {
d()->valueType()->metaType.destruct(d()->gadgetPtr());
::operator delete(d()->gadgetPtr());
}
d()->setGadgetPtr(nullptr);
d()->setMetaObject(mo);
- d()->setValueType(QQmlValueTypeFactory::valueType(variantReferenceType));
+ d()->setValueType(QQmlMetaType::valueType(variantReferenceType));
if (!mo)
return false;
} else {
@@ -192,7 +192,7 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, QObject *obj
r->d()->object = object;
r->d()->property = property;
r->d()->setMetaObject(metaObject);
- auto valueType = QQmlValueTypeFactory::valueType(type);
+ auto valueType = QQmlMetaType::valueType(type);
if (!valueType) {
return engine->throwTypeError(QLatin1String("Type %1 is not a value type")
.arg(QString::fromUtf8(type.name())));
@@ -209,7 +209,7 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, const QVaria
Scoped<QQmlValueTypeWrapper> r(scope, engine->memoryManager->allocate<QQmlValueTypeWrapper>());
r->d()->setMetaObject(metaObject);
- auto valueType = QQmlValueTypeFactory::valueType(type);
+ auto valueType = QQmlMetaType::valueType(type);
if (!valueType) {
return engine->throwTypeError(QLatin1String("Type %1 is not a value type")
.arg(QString::fromUtf8(type.name())));
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index 61ae1d4a06..265169a4d8 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -247,7 +247,7 @@ void QQmlVMEMetaObjectEndpoint::tryConnect()
int coreIndex = encodedIndex.coreIndex();
int valueTypeIndex = encodedIndex.valueTypeIndex();
const QQmlPropertyData *pd = targetDData->propertyCache->property(coreIndex);
- if (pd && valueTypeIndex != -1 && !QQmlValueTypeFactory::valueType(pd->propType())) {
+ if (pd && valueTypeIndex != -1 && !QQmlMetaType::valueType(pd->propType())) {
// deep alias
QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(metaObject->compilationUnit->engine->qmlEngine());
auto const *newPropertyCache = enginePriv->propertyCacheForType(pd->propType().id());
diff --git a/src/quick/util/qquickanimation.cpp b/src/quick/util/qquickanimation.cpp
index f2ee096af7..8dce372b4d 100644
--- a/src/quick/util/qquickanimation.cpp
+++ b/src/quick/util/qquickanimation.cpp
@@ -1982,7 +1982,7 @@ void QQuickPropertyAnimationPrivate::convertVariant(QVariant &variant, QMetaType
}
break;
default:
- if (QQmlValueTypeFactory::isValueType(type)) {
+ if (QQmlMetaType::isValueType(type)) {
variant.convert(QMetaType(type));
} else {
QQmlMetaType::StringConverter converter = QQmlMetaType::customStringConverter(type.id());
diff --git a/tests/auto/qml/qqmlpropertycache/BLACKLIST b/tests/auto/qml/qqmlpropertycache/BLACKLIST
deleted file mode 100644
index d27b6a6290..0000000000
--- a/tests/auto/qml/qqmlpropertycache/BLACKLIST
+++ /dev/null
@@ -1,2 +0,0 @@
-[derivedGadgetMethod]
-*
diff --git a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
index 875a174814..4c04849d1f 100644
--- a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
+++ b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
@@ -654,6 +654,8 @@ void tst_qqmlpropertycache::metaObjectsForRootElements()
void tst_qqmlpropertycache::derivedGadgetMethod()
{
+ metaObjectsForRootElements();
+
qmlRegisterTypesAndRevisions<BaseGadget, DerivedGadget, GadgetUser>("Test.PropertyCache", 1);
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("derivedGadgetMethod.qml"));
diff --git a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
index f615060ce3..80360b0912 100644
--- a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
+++ b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
@@ -1823,8 +1823,8 @@ void tst_qqmlvaluetypes::scarceTypes()
// These should not be treated as value types because we want the scarce resource
// mechanism to clear them when going out of scope. The scarce resource mechanism
// only works on QV4::VariantObject as that has an additional level of redirection.
- QVERIFY(!QQmlValueTypeFactory::isValueType(QMetaType::fromType<QImage>()));
- QVERIFY(!QQmlValueTypeFactory::isValueType(QMetaType::fromType<QPixmap>()));
+ QVERIFY(!QQmlMetaType::isValueType(QMetaType::fromType<QImage>()));
+ QVERIFY(!QQmlMetaType::isValueType(QMetaType::fromType<QPixmap>()));
QV4::ExecutionEngine engine;
QV4::Scope scope(&engine);
@@ -1839,7 +1839,7 @@ void tst_qqmlvaluetypes::scarceTypes()
}
#define CHECK_TYPE_IS_NOT_VALUETYPE(Type, typeId, cppType) \
- QVERIFY(!QQmlValueTypeFactory::isValueType(QMetaType(QMetaType::Type)));
+ QVERIFY(!QQmlMetaType::isValueType(QMetaType(QMetaType::Type)));
void tst_qqmlvaluetypes::nonValueTypes()
{