| 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 | |