aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmlmetatype.cpp
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 /src/qml/qml/qqmlmetatype.cpp
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>
Diffstat (limited to 'src/qml/qml/qqmlmetatype.cpp')
-rw-r--r--src/qml/qml/qqmlmetatype.cpp117
1 files changed, 114 insertions, 3 deletions
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