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 | |
24 | QT_BEGIN_NAMESPACE |
25 | |
26 | class QQmlTypeModule; |
27 | class QRecursiveMutex; |
28 | class QQmlError; |
29 | class QQmlValueType; |
30 | |
31 | namespace QV4 { class ExecutableCompilationUnit; } |
32 | |
33 | struct CompositeMetaTypeIds |
34 | { |
35 | private: |
36 | int *refCount = nullptr; |
37 | void deref(); |
38 | void ref() |
39 | { |
40 | Q_ASSERT(refCount); |
41 | ++*refCount; |
42 | } |
43 | public: |
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); |
80 | public: |
81 | QMetaType id; |
82 | QMetaType listId; |
83 | bool isValid() const { return id.isValid() && listId.isValid(); } |
84 | }; |
85 | |
86 | class 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 | |
94 | public: |
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 | |
289 | Q_DECLARE_TYPEINFO(QQmlMetaType, Q_RELOCATABLE_TYPE); |
290 | |
291 | // used in QQmlListMetaType to tag the metatpye |
292 | inline const QMetaObject *dynamicQmlListMarker(const QtPrivate::QMetaTypeInterface *) { |
293 | return nullptr; |
294 | }; |
295 | |
296 | inline const QMetaObject *dynamicQmlMetaObject(const QtPrivate::QMetaTypeInterface *iface) { |
297 | return QQmlMetaType::metaObjectForType(metaType: QMetaType(iface)).metaObject(); |
298 | }; |
299 | |
300 | // metatype interface for composite QML types |
301 | struct 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 |
334 | struct 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 | |
372 | QT_END_NAMESPACE |
373 | |
374 | #endif // QQMLMETATYPE_P_H |
375 | |
376 | |