1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the QtQml module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #ifndef QQMLPRIVATE_H |
41 | #define QQMLPRIVATE_H |
42 | |
43 | // |
44 | // W A R N I N G |
45 | // ------------- |
46 | // |
47 | // This file is not part of the Qt API. It exists purely as an |
48 | // implementation detail. This header file may change from version to |
49 | // version without notice, or even be removed. |
50 | // |
51 | // We mean it. |
52 | // |
53 | |
54 | #include <functional> |
55 | #include <type_traits> |
56 | |
57 | #include <QtQml/qtqmlglobal.h> |
58 | #include <QtQml/qqmlparserstatus.h> |
59 | #include <QtQml/qqmllist.h> |
60 | #include <QtQml/qqmlpropertyvaluesource.h> |
61 | |
62 | #include <QtCore/qglobal.h> |
63 | #include <QtCore/qvariant.h> |
64 | #include <QtCore/qurl.h> |
65 | #include <QtCore/qpointer.h> |
66 | |
67 | #include <QtCore/qmetaobject.h> |
68 | #include <QtCore/qdebug.h> |
69 | |
70 | #define QML_GETTYPENAMES \ |
71 | const char *className = T::staticMetaObject.className(); \ |
72 | const int nameLen = int(strlen(className)); \ |
73 | QVarLengthArray<char,48> pointerName(nameLen+2); \ |
74 | memcpy(pointerName.data(), className, size_t(nameLen)); \ |
75 | pointerName[nameLen] = '*'; \ |
76 | pointerName[nameLen+1] = '\0'; \ |
77 | const int listLen = int(strlen("QQmlListProperty<")); \ |
78 | QVarLengthArray<char,64> listName(listLen + nameLen + 2); \ |
79 | memcpy(listName.data(), "QQmlListProperty<", size_t(listLen)); \ |
80 | memcpy(listName.data()+listLen, className, size_t(nameLen)); \ |
81 | listName[listLen+nameLen] = '>'; \ |
82 | listName[listLen+nameLen+1] = '\0'; |
83 | |
84 | QT_BEGIN_NAMESPACE |
85 | |
86 | class QQmlPropertyValueInterceptor; |
87 | |
88 | namespace QQmlPrivate { |
89 | struct CachedQmlUnit; |
90 | template<typename A> |
91 | using QQmlAttachedPropertiesFunc = A *(*)(QObject *); |
92 | } |
93 | |
94 | namespace QV4 { |
95 | struct ExecutionEngine; |
96 | namespace CompiledData { |
97 | struct Unit; |
98 | struct CompilationUnit; |
99 | } |
100 | } |
101 | namespace QmlIR { |
102 | struct Document; |
103 | typedef void (*IRLoaderFunction)(Document *, const QQmlPrivate::CachedQmlUnit *); |
104 | } |
105 | |
106 | using QQmlAttachedPropertiesFunc = QQmlPrivate::QQmlAttachedPropertiesFunc<QObject>; |
107 | |
108 | inline uint qHash(QQmlAttachedPropertiesFunc func, uint seed = 0) |
109 | { |
110 | return qHash(key: quintptr(func), seed); |
111 | } |
112 | |
113 | template <typename TYPE> |
114 | class QQmlTypeInfo |
115 | { |
116 | public: |
117 | enum { |
118 | hasAttachedProperties = 0 |
119 | }; |
120 | }; |
121 | |
122 | |
123 | class QJSValue; |
124 | class QJSEngine; |
125 | class QQmlEngine; |
126 | class QQmlCustomParser; |
127 | class QQmlTypeNotAvailable; |
128 | |
129 | template<class T> |
130 | QQmlCustomParser *qmlCreateCustomParser() |
131 | { |
132 | return nullptr; |
133 | } |
134 | |
135 | namespace QQmlPrivate |
136 | { |
137 | void Q_QML_EXPORT qdeclarativeelement_destructor(QObject *); |
138 | template<typename T> |
139 | class QQmlElement final : public T |
140 | { |
141 | public: |
142 | ~QQmlElement() override { |
143 | QQmlPrivate::qdeclarativeelement_destructor(this); |
144 | } |
145 | static void operator delete(void *ptr) { |
146 | // We allocate memory from this class in QQmlType::create |
147 | // along with some additional memory. |
148 | // So we override the operator delete in order to avoid the |
149 | // sized operator delete to be called with a different size than |
150 | // the size that was allocated. |
151 | ::operator delete (ptr); |
152 | } |
153 | static void operator delete(void *, void *) { |
154 | // Deliberately empty placement delete operator. |
155 | // Silences MSVC warning C4291: no matching operator delete found |
156 | } |
157 | }; |
158 | |
159 | template<typename T> |
160 | constexpr bool isConstructible() |
161 | { |
162 | return std::is_default_constructible<T>::value && std::is_base_of<QObject, T>::value; |
163 | } |
164 | |
165 | template<typename T> |
166 | void createInto(void *memory) { new (memory) QQmlElement<T>; } |
167 | |
168 | template<typename T> |
169 | QObject *createSingletonInstance(QQmlEngine *, QJSEngine *) { return new T; } |
170 | |
171 | template<typename T> |
172 | QObject *createParent(QObject *p) { return new T(p); } |
173 | |
174 | using CreateIntoFunction = void (*)(void *); |
175 | using CreateSingletonFunction = QObject *(*)(QQmlEngine *, QJSEngine *); |
176 | using CreateParentFunction = QObject *(*)(QObject *); |
177 | |
178 | template<typename T, bool Constructible = isConstructible<T>()> |
179 | struct Constructors; |
180 | |
181 | template<typename T> |
182 | struct Constructors<T, true> |
183 | { |
184 | static constexpr CreateIntoFunction createInto |
185 | = QQmlPrivate::createInto<T>; |
186 | static constexpr CreateSingletonFunction createSingletonInstance |
187 | = QQmlPrivate::createSingletonInstance<T>; |
188 | }; |
189 | |
190 | template<typename T> |
191 | struct Constructors<T, false> |
192 | { |
193 | static constexpr CreateIntoFunction createInto = nullptr; |
194 | static constexpr CreateSingletonFunction createSingletonInstance = nullptr; |
195 | }; |
196 | |
197 | template<typename T, bool IsVoid = std::is_void<T>::value> |
198 | struct ExtendedType; |
199 | |
200 | // void means "not an extended type" |
201 | template<typename T> |
202 | struct ExtendedType<T, true> |
203 | { |
204 | static constexpr const CreateParentFunction createParent = nullptr; |
205 | static constexpr const QMetaObject *staticMetaObject = nullptr; |
206 | }; |
207 | |
208 | // If it's not void, we actually want an error if the ctor or the metaobject is missing. |
209 | template<typename T> |
210 | struct ExtendedType<T, false> |
211 | { |
212 | static constexpr const CreateParentFunction createParent = QQmlPrivate::createParent<T>; |
213 | static constexpr const QMetaObject *staticMetaObject = &T::staticMetaObject; |
214 | }; |
215 | |
216 | template<class From, class To, int N> |
217 | struct StaticCastSelectorClass |
218 | { |
219 | static inline int cast() { return -1; } |
220 | }; |
221 | |
222 | template<class From, class To> |
223 | struct StaticCastSelectorClass<From, To, sizeof(int)> |
224 | { |
225 | static inline int cast() { return int(reinterpret_cast<quintptr>(static_cast<To *>(reinterpret_cast<From *>(0x10000000)))) - 0x10000000; } |
226 | }; |
227 | |
228 | template<class From, class To> |
229 | struct StaticCastSelector |
230 | { |
231 | typedef int yes_type; |
232 | typedef char no_type; |
233 | |
234 | static yes_type checkType(To *); |
235 | static no_type checkType(...); |
236 | |
237 | static inline int cast() |
238 | { |
239 | return StaticCastSelectorClass<From, To, sizeof(checkType(reinterpret_cast<From *>(0)))>::cast(); |
240 | } |
241 | }; |
242 | |
243 | template<typename...> |
244 | using QmlVoidT = void; |
245 | |
246 | // You can prevent subclasses from using the same attached type by specialzing this. |
247 | // This is reserved for internal types, though. |
248 | template<class T, class A> |
249 | struct OverridableAttachedType |
250 | { |
251 | using Type = A; |
252 | }; |
253 | |
254 | template<class T, class = QmlVoidT<>, bool OldStyle = QQmlTypeInfo<T>::hasAttachedProperties> |
255 | struct QmlAttached |
256 | { |
257 | using Type = void; |
258 | using Func = QQmlAttachedPropertiesFunc<QObject>; |
259 | static const QMetaObject *staticMetaObject() { return nullptr; } |
260 | static Func attachedPropertiesFunc() { return nullptr; } |
261 | }; |
262 | |
263 | // Defined inline via QML_ATTACHED |
264 | template<class T> |
265 | struct QmlAttached<T, QmlVoidT<typename OverridableAttachedType<T, typename T::QmlAttachedType>::Type>, false> |
266 | { |
267 | // Normal attached properties |
268 | template <typename Parent, typename Attached> |
269 | struct Properties |
270 | { |
271 | using Func = QQmlAttachedPropertiesFunc<Attached>; |
272 | static const QMetaObject *staticMetaObject() { return &Attached::staticMetaObject; } |
273 | static Func attachedPropertiesFunc() { return Parent::qmlAttachedProperties; } |
274 | }; |
275 | |
276 | // Disabled via OverridableAttachedType |
277 | template<typename Parent> |
278 | struct Properties<Parent, void> |
279 | { |
280 | using Func = QQmlAttachedPropertiesFunc<QObject>; |
281 | static const QMetaObject *staticMetaObject() { return nullptr; }; |
282 | static Func attachedPropertiesFunc() { return nullptr; }; |
283 | }; |
284 | |
285 | using Type = typename OverridableAttachedType<T, typename T::QmlAttachedType>::Type; |
286 | using Func = typename Properties<T, Type>::Func; |
287 | |
288 | static const QMetaObject *staticMetaObject() |
289 | { |
290 | return Properties<T, Type>::staticMetaObject(); |
291 | } |
292 | |
293 | static Func attachedPropertiesFunc() |
294 | { |
295 | return Properties<T, Type>::attachedPropertiesFunc(); |
296 | } |
297 | }; |
298 | |
299 | // Separately defined via QQmlTypeInfo |
300 | template<class T> |
301 | struct QmlAttached<T, QmlVoidT<decltype(T::qmlAttachedProperties)>, true> |
302 | { |
303 | using Type = typename std::remove_pointer<decltype(T::qmlAttachedProperties(nullptr))>::type; |
304 | using Func = QQmlAttachedPropertiesFunc<Type>; |
305 | |
306 | static const QMetaObject *staticMetaObject() { return &Type::staticMetaObject; } |
307 | static Func attachedPropertiesFunc() { return T::qmlAttachedProperties; } |
308 | }; |
309 | |
310 | // This is necessary because both the type containing a default template parameter and the type |
311 | // instantiating the template need to have access to the default template parameter type. In |
312 | // this case that's T::QmlAttachedType. The QML_FOREIGN macro needs to befriend specific other |
313 | // types. Therefore we need some kind of "accessor". Because of compiler bugs in gcc and clang, |
314 | // we cannot befriend attachedPropertiesFunc() directly. Wrapping the actual access into another |
315 | // struct "fixes" that. For convenience we still want the free standing functions in addition. |
316 | template<class T> |
317 | struct QmlAttachedAccessor |
318 | { |
319 | static QQmlAttachedPropertiesFunc<QObject> attachedPropertiesFunc() |
320 | { |
321 | return QQmlAttachedPropertiesFunc<QObject>(QmlAttached<T>::attachedPropertiesFunc()); |
322 | } |
323 | |
324 | static const QMetaObject *staticMetaObject() |
325 | { |
326 | return QmlAttached<T>::staticMetaObject(); |
327 | } |
328 | }; |
329 | |
330 | template<typename T> |
331 | inline QQmlAttachedPropertiesFunc<QObject> attachedPropertiesFunc() |
332 | { |
333 | return QmlAttachedAccessor<T>::attachedPropertiesFunc(); |
334 | } |
335 | |
336 | template<typename T> |
337 | inline const QMetaObject *attachedPropertiesMetaObject() |
338 | { |
339 | return QmlAttachedAccessor<T>::staticMetaObject(); |
340 | } |
341 | |
342 | enum AutoParentResult { Parented, IncompatibleObject, IncompatibleParent }; |
343 | typedef AutoParentResult (*AutoParentFunction)(QObject *object, QObject *parent); |
344 | |
345 | struct RegisterType { |
346 | int version; |
347 | |
348 | int typeId; |
349 | int listId; |
350 | int objectSize; |
351 | void (*create)(void *); |
352 | QString noCreationReason; |
353 | |
354 | const char *uri; |
355 | int versionMajor; |
356 | int versionMinor; |
357 | const char *elementName; |
358 | const QMetaObject *metaObject; |
359 | |
360 | QQmlAttachedPropertiesFunc<QObject> attachedPropertiesFunction; |
361 | const QMetaObject *attachedPropertiesMetaObject; |
362 | |
363 | int parserStatusCast; |
364 | int valueSourceCast; |
365 | int valueInterceptorCast; |
366 | |
367 | QObject *(*extensionObjectCreate)(QObject *); |
368 | const QMetaObject *extensionMetaObject; |
369 | |
370 | QQmlCustomParser *customParser; |
371 | |
372 | int revision; |
373 | // If this is extended ensure "version" is bumped!!! |
374 | }; |
375 | |
376 | struct RegisterTypeAndRevisions { |
377 | int version; |
378 | |
379 | int typeId; |
380 | int listId; |
381 | int objectSize; |
382 | void (*create)(void *); |
383 | |
384 | const char *uri; |
385 | int versionMajor; |
386 | |
387 | const QMetaObject *metaObject; |
388 | const QMetaObject *classInfoMetaObject; |
389 | |
390 | QQmlAttachedPropertiesFunc<QObject> attachedPropertiesFunction; |
391 | const QMetaObject *attachedPropertiesMetaObject; |
392 | |
393 | int parserStatusCast; |
394 | int valueSourceCast; |
395 | int valueInterceptorCast; |
396 | |
397 | QObject *(*extensionObjectCreate)(QObject *); |
398 | const QMetaObject *extensionMetaObject; |
399 | |
400 | QQmlCustomParser *(*customParserFactory)(); |
401 | }; |
402 | |
403 | struct RegisterInterface { |
404 | int version; |
405 | |
406 | int typeId; |
407 | int listId; |
408 | |
409 | const char *iid; |
410 | |
411 | const char *uri; |
412 | int versionMajor; |
413 | }; |
414 | |
415 | struct RegisterAutoParent { |
416 | int version; |
417 | |
418 | AutoParentFunction function; |
419 | }; |
420 | |
421 | struct RegisterSingletonType { |
422 | int version; |
423 | |
424 | const char *uri; |
425 | int versionMajor; |
426 | int versionMinor; |
427 | const char *typeName; |
428 | |
429 | QJSValue (*scriptApi)(QQmlEngine *, QJSEngine *); |
430 | QObject *(*qobjectApi)(QQmlEngine *, QJSEngine *); |
431 | const QMetaObject *instanceMetaObject; // new in version 1 |
432 | int typeId; // new in version 2 |
433 | int revision; // new in version 2 |
434 | std::function<QObject*(QQmlEngine *, QJSEngine *)> generalizedQobjectApi; // new in version 3 |
435 | // If this is extended ensure "version" is bumped!!! |
436 | }; |
437 | |
438 | struct RegisterSingletonTypeAndRevisions { |
439 | int version; |
440 | const char *uri; |
441 | int versionMajor; |
442 | |
443 | QJSValue (*scriptApi)(QQmlEngine *, QJSEngine *); |
444 | const QMetaObject *instanceMetaObject; |
445 | const QMetaObject *classInfoMetaObject; |
446 | |
447 | int typeId; |
448 | std::function<QObject*(QQmlEngine *, QJSEngine *)> generalizedQobjectApi; // new in version 3 |
449 | }; |
450 | |
451 | struct RegisterCompositeType { |
452 | QUrl url; |
453 | const char *uri; |
454 | int versionMajor; |
455 | int versionMinor; |
456 | const char *typeName; |
457 | }; |
458 | |
459 | struct RegisterCompositeSingletonType { |
460 | QUrl url; |
461 | const char *uri; |
462 | int versionMajor; |
463 | int versionMinor; |
464 | const char *typeName; |
465 | }; |
466 | |
467 | struct CachedQmlUnit { |
468 | const QV4::CompiledData::Unit *qmlData; |
469 | void *unused1; |
470 | void *unused2; |
471 | }; |
472 | |
473 | typedef const CachedQmlUnit *(*QmlUnitCacheLookupFunction)(const QUrl &url); |
474 | struct RegisterQmlUnitCacheHook { |
475 | int version; |
476 | QmlUnitCacheLookupFunction lookupCachedQmlUnit; |
477 | }; |
478 | |
479 | enum RegistrationType { |
480 | TypeRegistration = 0, |
481 | InterfaceRegistration = 1, |
482 | AutoParentRegistration = 2, |
483 | SingletonRegistration = 3, |
484 | CompositeRegistration = 4, |
485 | CompositeSingletonRegistration = 5, |
486 | QmlUnitCacheHookRegistration = 6, |
487 | TypeAndRevisionsRegistration = 7, |
488 | SingletonAndRevisionsRegistration = 8 |
489 | }; |
490 | |
491 | int Q_QML_EXPORT qmlregister(RegistrationType, void *); |
492 | void Q_QML_EXPORT qmlunregister(RegistrationType, quintptr); |
493 | struct Q_QML_EXPORT RegisterSingletonFunctor |
494 | { |
495 | QObject *operator()(QQmlEngine *, QJSEngine *); |
496 | |
497 | QPointer<QObject> m_object; |
498 | bool alreadyCalled = false; |
499 | }; |
500 | |
501 | static int indexOfOwnClassInfo(const QMetaObject *metaObject, const char *key) |
502 | { |
503 | if (!metaObject || !key) |
504 | return -1; |
505 | |
506 | const int offset = metaObject->classInfoOffset(); |
507 | for (int i = metaObject->classInfoCount() + offset - 1; i >= offset; --i) |
508 | if (qstrcmp(str1: key, str2: metaObject->classInfo(index: i).name()) == 0) { |
509 | return i; |
510 | } |
511 | return -1; |
512 | } |
513 | |
514 | inline const char *classInfo(const QMetaObject *metaObject, const char *key) |
515 | { |
516 | return metaObject->classInfo(index: indexOfOwnClassInfo(metaObject, key)).value(); |
517 | } |
518 | |
519 | inline int intClassInfo(const QMetaObject *metaObject, const char *key, int defaultValue = 0) |
520 | { |
521 | const int index = indexOfOwnClassInfo(metaObject, key); |
522 | return (index == -1) ? defaultValue |
523 | : QByteArray(metaObject->classInfo(index).value()).toInt(); |
524 | } |
525 | |
526 | inline bool boolClassInfo(const QMetaObject *metaObject, const char *key, |
527 | bool defaultValue = false) |
528 | { |
529 | const int index = indexOfOwnClassInfo(metaObject, key); |
530 | return (index == -1) ? defaultValue |
531 | : (QByteArray(metaObject->classInfo(index).value()) == "true" ); |
532 | } |
533 | |
534 | inline const char *classElementName(const QMetaObject *metaObject) |
535 | { |
536 | const char *elementName = classInfo(metaObject, key: "QML.Element" ); |
537 | if (qstrcmp(str1: elementName, str2: "auto" ) == 0) |
538 | return metaObject->className(); |
539 | if (qstrcmp(str1: elementName, str2: "anonymous" ) == 0) |
540 | return nullptr; |
541 | |
542 | if (!elementName || elementName[0] < 'A' || elementName[0] > 'Z') { |
543 | qWarning() << "Missing or unusable QML.Element class info \"" << elementName << "\"" |
544 | << "for" << metaObject->className(); |
545 | } |
546 | |
547 | return elementName; |
548 | } |
549 | |
550 | template<class T, class = QmlVoidT<>> |
551 | struct QmlExtended |
552 | { |
553 | using Type = void; |
554 | }; |
555 | |
556 | template<class T> |
557 | struct QmlExtended<T, QmlVoidT<typename T::QmlExtendedType>> |
558 | { |
559 | using Type = typename T::QmlExtendedType; |
560 | }; |
561 | |
562 | template<class T, class = QmlVoidT<>> |
563 | struct QmlResolved |
564 | { |
565 | using Type = T; |
566 | }; |
567 | |
568 | template<class T> |
569 | struct QmlResolved<T, QmlVoidT<typename T::QmlForeignType>> |
570 | { |
571 | using Type = typename T::QmlForeignType; |
572 | }; |
573 | |
574 | template<class T, class = QmlVoidT<>> |
575 | struct QmlSingleton |
576 | { |
577 | static constexpr bool Value = false; |
578 | }; |
579 | |
580 | template<class T> |
581 | struct QmlSingleton<T, QmlVoidT<typename T::QmlIsSingleton>> |
582 | { |
583 | static constexpr bool Value = bool(T::QmlIsSingleton::yes); |
584 | }; |
585 | |
586 | template<class T, class = QmlVoidT<>> |
587 | struct QmlInterface |
588 | { |
589 | static constexpr bool Value = false; |
590 | }; |
591 | |
592 | template<class T> |
593 | struct QmlInterface<T, QmlVoidT<typename T::QmlIsInterface>> |
594 | { |
595 | static constexpr bool Value = bool(T::QmlIsInterface::yes); |
596 | }; |
597 | |
598 | template<typename T> |
599 | void qmlRegisterSingletonAndRevisions(const char *uri, int versionMajor, |
600 | const QMetaObject *classInfoMetaObject) |
601 | { |
602 | QML_GETTYPENAMES |
603 | |
604 | RegisterSingletonTypeAndRevisions api = { |
605 | 0, |
606 | |
607 | uri, |
608 | versionMajor, |
609 | |
610 | nullptr, |
611 | |
612 | &T::staticMetaObject, |
613 | classInfoMetaObject, |
614 | |
615 | qRegisterNormalizedMetaType<T *>(pointerName.constData()), |
616 | Constructors<T>::createSingletonInstance |
617 | }; |
618 | |
619 | qmlregister(SingletonAndRevisionsRegistration, &api); |
620 | } |
621 | |
622 | template<typename T, typename E> |
623 | void qmlRegisterTypeAndRevisions(const char *uri, int versionMajor, |
624 | const QMetaObject *classInfoMetaObject) |
625 | { |
626 | QML_GETTYPENAMES |
627 | |
628 | RegisterTypeAndRevisions type = { |
629 | 0, |
630 | qRegisterNormalizedMetaType<T *>(pointerName.constData()), |
631 | qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()), |
632 | int(sizeof(T)), |
633 | Constructors<T>::createInto, |
634 | |
635 | uri, |
636 | versionMajor, |
637 | |
638 | &T::staticMetaObject, |
639 | classInfoMetaObject, |
640 | |
641 | attachedPropertiesFunc<T>(), |
642 | attachedPropertiesMetaObject<T>(), |
643 | |
644 | StaticCastSelector<T, QQmlParserStatus>::cast(), |
645 | StaticCastSelector<T, QQmlPropertyValueSource>::cast(), |
646 | StaticCastSelector<T, QQmlPropertyValueInterceptor>::cast(), |
647 | |
648 | ExtendedType<E>::createParent, |
649 | ExtendedType<E>::staticMetaObject, |
650 | |
651 | &qmlCreateCustomParser<T> |
652 | }; |
653 | |
654 | qmlregister(TypeAndRevisionsRegistration, &type); |
655 | } |
656 | |
657 | template<> |
658 | void Q_QML_EXPORT qmlRegisterTypeAndRevisions<QQmlTypeNotAvailable, void>( |
659 | const char *uri, int versionMajor, const QMetaObject *classInfoMetaObject); |
660 | |
661 | } // namespace QQmlPrivate |
662 | |
663 | QT_END_NAMESPACE |
664 | |
665 | #endif // QQMLPRIVATE_H |
666 | |