1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QQMLMETATYPE_P_H
5#define QQMLMETATYPE_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <private/qqmldirparser_p.h>
19#include <private/qqmlmetaobject_p.h>
20#include <private/qqmlproxymetaobject_p.h>
21#include <private/qqmltype_p.h>
22#include <private/qtqmlglobal_p.h>
23
24QT_BEGIN_NAMESPACE
25
26class QQmlTypeModule;
27class QRecursiveMutex;
28class QQmlError;
29class QQmlValueType;
30
31namespace QV4 { class ExecutableCompilationUnit; }
32
33struct CompositeMetaTypeIds
34{
35private:
36 int *refCount = nullptr;
37 void deref();
38 void ref()
39 {
40 Q_ASSERT(refCount);
41 ++*refCount;
42 }
43public:
44 CompositeMetaTypeIds() = default;
45 CompositeMetaTypeIds(QMetaType id, QMetaType listId) : id(id), listId(listId) {}
46 CompositeMetaTypeIds(const CompositeMetaTypeIds &other)
47 : refCount(other.refCount), id(other.id), listId(other.listId)
48 {
49 if (refCount)
50 ref();
51 }
52 CompositeMetaTypeIds(CompositeMetaTypeIds &&other)
53 : refCount(other.refCount), id(other.id), listId(other.listId)
54 {
55 other.refCount = nullptr;
56 }
57 CompositeMetaTypeIds &operator=(const CompositeMetaTypeIds &other)
58 {
59 if (refCount)
60 deref();
61 refCount = other.refCount;
62 id = other.id;
63 listId = other.listId;
64 if (refCount)
65 ref();
66 return *this;
67 }
68 CompositeMetaTypeIds &operator=(CompositeMetaTypeIds &&other)
69 {
70 if (refCount)
71 deref();
72 refCount = other.refCount;
73 id = other.id;
74 listId = other.listId;
75 other.refCount = nullptr;
76 return *this;
77 }
78 ~CompositeMetaTypeIds();
79 static CompositeMetaTypeIds fromCompositeName(const QByteArray &name);
80public:
81 QMetaType id;
82 QMetaType listId;
83 bool isValid() const { return id.isValid() && listId.isValid(); }
84};
85
86class Q_QML_PRIVATE_EXPORT QQmlMetaType
87{
88 friend struct CompositeMetaTypeIds;
89 friend class QQmlDesignerMetaObject;
90
91 static CompositeMetaTypeIds registerInternalCompositeType(const QByteArray &className);
92 static void unregisterInternalCompositeType(const CompositeMetaTypeIds &typeIds);
93
94public:
95 enum class RegistrationResult {
96 Success,
97 Failure,
98 NoRegistrationFunction
99 };
100
101 static QQmlType registerType(const QQmlPrivate::RegisterType &type);
102 static QQmlType registerInterface(const QQmlPrivate::RegisterInterface &type);
103 static QQmlType registerSingletonType(const QQmlPrivate::RegisterSingletonType &type);
104 static QQmlType registerCompositeSingletonType(const QQmlPrivate::RegisterCompositeSingletonType &type);
105 static QQmlType registerCompositeType(const QQmlPrivate::RegisterCompositeType &type);
106 static RegistrationResult registerPluginTypes(QObject *instance, const QString &basePath,
107 const QString &uri, const QString &typeNamespace,
108 QTypeRevision version, QList<QQmlError> *errors);
109 static QQmlType typeForUrl(const QString &urlString, const QHashedStringRef& typeName,
110 bool isCompositeSingleton, QList<QQmlError> *errors,
111 QTypeRevision version = QTypeRevision());
112
113 static void unregisterType(int type);
114
115 static void registerMetaObjectForType(const QMetaObject *metaobject, QQmlTypePrivate *type);
116
117 static void registerModule(const char *uri, QTypeRevision version);
118 static bool protectModule(const QString &uri, QTypeRevision version,
119 bool weakProtectAllVersions = false);
120
121 static void registerModuleImport(const QString &uri, QTypeRevision version,
122 const QQmlDirParser::Import &import);
123 static void unregisterModuleImport(const QString &uri, QTypeRevision version,
124 const QQmlDirParser::Import &import);
125 static QList<QQmlDirParser::Import> moduleImports(const QString &uri, QTypeRevision version);
126
127 static int typeId(const char *uri, QTypeRevision version, const char *qmlName);
128
129 static void registerUndeletableType(const QQmlType &dtype);
130
131 static QList<QString> qmlTypeNames();
132 static QList<QQmlType> qmlTypes();
133 static QList<QQmlType> qmlSingletonTypes();
134 static QList<QQmlType> qmlAllTypes();
135
136 static QQmlType qmlType(const QString &qualifiedName, QTypeRevision version);
137 static QQmlType qmlType(const QHashedStringRef &name, const QHashedStringRef &module, QTypeRevision version);
138 static QQmlType qmlType(const QMetaObject *);
139 static QQmlType qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, QTypeRevision version);
140 static QQmlType qmlTypeById(int qmlTypeId);
141
142 static QQmlType qmlType(QMetaType metaType);
143 static QQmlType qmlListType(QMetaType metaType);
144
145 static QQmlType qmlType(const QUrl &unNormalizedUrl, bool includeNonFileImports = false);
146 static QQmlType inlineComponentType(const QQmlType &containingType, const QString &name);
147 static void associateInlineComponent(const QQmlType &containingType, const QString &name, const CompositeMetaTypeIds &metaTypeIds, QQmlType existingType);
148
149 static QQmlPropertyCache::ConstPtr propertyCache(
150 QObject *object, QTypeRevision version = QTypeRevision());
151 static QQmlPropertyCache::ConstPtr propertyCache(
152 const QMetaObject *metaObject, QTypeRevision version = QTypeRevision());
153 static QQmlPropertyCache::ConstPtr propertyCache(
154 const QQmlType &type, QTypeRevision version);
155
156 // These methods may be called from the loader thread
157 static QQmlMetaObject rawMetaObjectForType(QMetaType metaType);
158 static QQmlMetaObject metaObjectForType(QMetaType metaType);
159 static QQmlPropertyCache::ConstPtr propertyCacheForType(QMetaType metaType);
160 static QQmlPropertyCache::ConstPtr rawPropertyCacheForType(QMetaType metaType);
161 static QQmlPropertyCache::ConstPtr rawPropertyCacheForType(
162 QMetaType metaType, QTypeRevision version);
163
164 static void freeUnusedTypesAndCaches();
165
166 static QMetaProperty defaultProperty(const QMetaObject *);
167 static QMetaProperty defaultProperty(QObject *);
168 static QMetaMethod defaultMethod(const QMetaObject *);
169 static QMetaMethod defaultMethod(QObject *);
170
171 static QObject *toQObject(const QVariant &, bool *ok = nullptr);
172
173 static QMetaType listValueType(QMetaType type);
174 static QQmlAttachedPropertiesFunc attachedPropertiesFunc(QQmlEnginePrivate *,
175 const QMetaObject *);
176 static bool isInterface(QMetaType type);
177 static const char *interfaceIId(QMetaType type);
178 static bool isList(QMetaType type);
179
180 static QTypeRevision latestModuleVersion(const QString &uri);
181 static bool isStronglyLockedModule(const QString &uri, QTypeRevision version);
182 static QTypeRevision matchingModuleVersion(const QString &module, QTypeRevision version);
183 static QQmlTypeModule *typeModule(const QString &uri, QTypeRevision version);
184
185 static QList<QQmlPrivate::AutoParentFunction> parentFunctions();
186
187 enum class CachedUnitLookupError {
188 NoError,
189 NoUnitFound,
190 VersionMismatch,
191 NotFullyTyped
192 };
193
194 enum CacheMode { RejectAll, AcceptUntyped, RequireFullyTyped };
195 static const QQmlPrivate::CachedQmlUnit *findCachedCompilationUnit(
196 const QUrl &uri, CacheMode mode, CachedUnitLookupError *status);
197
198 // used by tst_qqmlcachegen.cpp
199 static void prependCachedUnitLookupFunction(QQmlPrivate::QmlUnitCacheLookupFunction handler);
200 static void removeCachedUnitLookupFunction(QQmlPrivate::QmlUnitCacheLookupFunction handler);
201
202 static QRecursiveMutex *typeRegistrationLock();
203
204 static QString prettyTypeName(const QObject *object);
205
206 template <typename QQmlTypeContainer>
207 static void removeQQmlTypePrivate(QQmlTypeContainer &container,
208 const QQmlTypePrivate *reference)
209 {
210 for (typename QQmlTypeContainer::iterator it = container.begin(); it != container.end();) {
211 if (*it == reference)
212 it = container.erase(it);
213 else
214 ++it;
215 }
216 }
217
218 template <typename InlineComponentContainer>
219 static void removeFromInlineComponents(
220 InlineComponentContainer &container, const QQmlTypePrivate *reference)
221 {
222 for (auto it = container.begin(), end = container.end(); it != end;) {
223 if (it.key().containingType == reference)
224 it = container.erase(it);
225 else
226 ++it;
227 }
228 }
229
230 static void registerTypeAlias(int typeId, const QString &name);
231
232 static int registerAutoParentFunction(const QQmlPrivate::RegisterAutoParent &autoparent);
233 static void unregisterAutoParentFunction(const QQmlPrivate::AutoParentFunction &function);
234
235 static QQmlType registerSequentialContainer(
236 const QQmlPrivate::RegisterSequentialContainer &sequenceRegistration);
237 static void unregisterSequentialContainer(int id);
238
239 static int registerUnitCacheHook(const QQmlPrivate::RegisterQmlUnitCacheHook &hookRegistration);
240 static void clearTypeRegistrations();
241
242 static QList<QQmlProxyMetaObject::ProxyData> proxyData(const QMetaObject *mo,
243 const QMetaObject *baseMetaObject,
244 QMetaObject *lastMetaObject);
245
246 enum ClonePolicy {
247 CloneAll, // default
248 CloneEnumsOnly, // skip properties and methods
249 };
250 static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo,
251 const QMetaObject *ignoreStart, const QMetaObject *ignoreEnd,
252 ClonePolicy policy);
253
254 static void qmlInsertModuleRegistration(const QString &uri, void (*registerFunction)());
255 static void qmlRemoveModuleRegistration(const QString &uri);
256
257 static bool qmlRegisterModuleTypes(const QString &uri);
258
259 static bool isValueType(QMetaType type);
260 static QQmlValueType *valueType(QMetaType metaType);
261 static const QMetaObject *metaObjectForValueType(QMetaType type);
262 static const QMetaObject *metaObjectForValueType(const QQmlType &qmlType)
263 {
264 // Prefer the extension meta object, if any.
265 // Extensions allow registration of non-gadget value types.
266 if (const QMetaObject *extensionMetaObject = qmlType.extensionMetaObject()) {
267 // This may be a namespace even if the original metaType isn't.
268 // You can do such things with QML_FOREIGN declarations.
269 if (extensionMetaObject->metaType().flags() & QMetaType::IsGadget)
270 return extensionMetaObject;
271 }
272
273 if (const QMetaObject *qmlTypeMetaObject = qmlType.metaObject()) {
274 // This may be a namespace even if the original metaType isn't.
275 // You can do such things with QML_FOREIGN declarations.
276 if (qmlTypeMetaObject->metaType().flags() & QMetaType::IsGadget)
277 return qmlTypeMetaObject;
278 }
279
280 return nullptr;
281 }
282
283 static QQmlPropertyCache::ConstPtr findPropertyCacheInCompositeTypes(QMetaType t);
284 static void registerInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit);
285 static void unregisterInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit);
286 static QV4::ExecutableCompilationUnit *obtainExecutableCompilationUnit(QMetaType type);
287};
288
289Q_DECLARE_TYPEINFO(QQmlMetaType, Q_RELOCATABLE_TYPE);
290
291// used in QQmlListMetaType to tag the metatpye
292inline const QMetaObject *dynamicQmlListMarker(const QtPrivate::QMetaTypeInterface *) {
293 return nullptr;
294};
295
296inline const QMetaObject *dynamicQmlMetaObject(const QtPrivate::QMetaTypeInterface *iface) {
297 return QQmlMetaType::metaObjectForType(metaType: QMetaType(iface)).metaObject();
298};
299
300// metatype interface for composite QML types
301struct QQmlMetaTypeInterface : QtPrivate::QMetaTypeInterface
302{
303 const QByteArray name;
304 QQmlMetaTypeInterface(const QByteArray &name)
305 : QMetaTypeInterface {
306 /*.revision=*/ .revision: QMetaTypeInterface::CurrentRevision,
307 /*.alignment=*/ .alignment: alignof(QObject *),
308 /*.size=*/ .size: sizeof(QObject *),
309 /*.flags=*/ .flags: QtPrivate::QMetaTypeTypeFlags<QObject *>::Flags,
310 /*.typeId=*/ .typeId: 0,
311 /*.metaObjectFn=*/ .metaObjectFn: &dynamicQmlMetaObject,
312 /*.name=*/ .name: name.constData(),
313 /*.defaultCtr=*/ .defaultCtr: [](const QMetaTypeInterface *, void *addr) {
314 *static_cast<QObject **>(addr) = nullptr;
315 },
316 /*.copyCtr=*/ .copyCtr: [](const QMetaTypeInterface *, void *addr, const void *other) {
317 *static_cast<QObject **>(addr) = *static_cast<QObject *const *>(other);
318 },
319 /*.moveCtr=*/ .moveCtr: [](const QMetaTypeInterface *, void *addr, void *other) {
320 *static_cast<QObject **>(addr) = *static_cast<QObject **>(other);
321 },
322 /*.dtor=*/ .dtor: [](const QMetaTypeInterface *, void *) {},
323 /*.equals*/ .equals: nullptr,
324 /*.lessThan*/ .lessThan: nullptr,
325 /*.debugStream=*/ .debugStream: nullptr,
326 /*.dataStreamOut=*/ .dataStreamOut: nullptr,
327 /*.dataStreamIn=*/ .dataStreamIn: nullptr,
328 /*.legacyRegisterOp=*/ .legacyRegisterOp: nullptr
329 }
330 , name(name) { }
331};
332
333// metatype for qml list types
334struct QQmlListMetaTypeInterface : QtPrivate::QMetaTypeInterface
335{
336 const QByteArray name;
337 // if this interface is for list<type>; valueType stores the interface for type
338 const QtPrivate::QMetaTypeInterface *valueType;
339 QQmlListMetaTypeInterface(const QByteArray &name, const QtPrivate::QMetaTypeInterface *valueType)
340 : QMetaTypeInterface {
341 /*.revision=*/ .revision: QMetaTypeInterface::CurrentRevision,
342 /*.alignment=*/ .alignment: alignof(QQmlListProperty<QObject>),
343 /*.size=*/ .size: sizeof(QQmlListProperty<QObject>),
344 /*.flags=*/ .flags: QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<QObject>>::Flags,
345 /*.typeId=*/ .typeId: 0,
346 /*.metaObjectFn=*/ .metaObjectFn: &dynamicQmlListMarker,
347 /*.name=*/ .name: name.constData(),
348 /*.defaultCtr=*/ .defaultCtr: [](const QMetaTypeInterface *, void *addr) {
349 new (addr) QQmlListProperty<QObject> ();
350 },
351 /*.copyCtr=*/ .copyCtr: [](const QMetaTypeInterface *, void *addr, const void *other) {
352 new (addr) QQmlListProperty<QObject>(
353 *static_cast<const QQmlListProperty<QObject> *>(other));
354 },
355 /*.moveCtr=*/ .moveCtr: [](const QMetaTypeInterface *, void *addr, void *other) {
356 new (addr) QQmlListProperty<QObject>(
357 std::move(*static_cast<QQmlListProperty<QObject> *>(other)));
358 },
359 /*.dtor=*/ .dtor: [](const QMetaTypeInterface *, void *addr) {
360 static_cast<QQmlListProperty<QObject> *>(addr)->~QQmlListProperty<QObject>();
361 },
362 /*.equals*/ .equals: nullptr,
363 /*.lessThan*/ .lessThan: nullptr,
364 /*.debugStream=*/ .debugStream: nullptr,
365 /*.dataStreamOut=*/ .dataStreamOut: nullptr,
366 /*.dataStreamIn=*/ .dataStreamIn: nullptr,
367 /*.legacyRegisterOp=*/ .legacyRegisterOp: nullptr
368 }
369 , name(name), valueType(valueType) { }
370};
371
372QT_END_NAMESPACE
373
374#endif // QQMLMETATYPE_P_H
375
376

source code of qtdeclarative/src/qml/qml/qqmlmetatype_p.h