/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtQml module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QQMLPRIVATE_H #define QQMLPRIVATE_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include #include #include #include #include #include #include #include #include #include #include #include #define QML_GETTYPENAMES \ const char *className = T::staticMetaObject.className(); \ const int nameLen = int(strlen(className)); \ QVarLengthArray pointerName(nameLen+2); \ memcpy(pointerName.data(), className, size_t(nameLen)); \ pointerName[nameLen] = '*'; \ pointerName[nameLen+1] = '\0'; \ const int listLen = int(strlen("QQmlListProperty<")); \ QVarLengthArray listName(listLen + nameLen + 2); \ memcpy(listName.data(), "QQmlListProperty<", size_t(listLen)); \ memcpy(listName.data()+listLen, className, size_t(nameLen)); \ listName[listLen+nameLen] = '>'; \ listName[listLen+nameLen+1] = '\0'; QT_BEGIN_NAMESPACE class QQmlPropertyValueInterceptor; namespace QQmlPrivate { struct CachedQmlUnit; template using QQmlAttachedPropertiesFunc = A *(*)(QObject *); } namespace QV4 { struct ExecutionEngine; namespace CompiledData { struct Unit; struct CompilationUnit; } } namespace QmlIR { struct Document; typedef void (*IRLoaderFunction)(Document *, const QQmlPrivate::CachedQmlUnit *); } using QQmlAttachedPropertiesFunc = QQmlPrivate::QQmlAttachedPropertiesFunc; inline uint qHash(QQmlAttachedPropertiesFunc func, uint seed = 0) { return qHash(quintptr(func), seed); } template class QQmlTypeInfo { public: enum { hasAttachedProperties = 0 }; }; class QJSValue; class QJSEngine; class QQmlEngine; class QQmlCustomParser; template QQmlCustomParser *qmlCreateCustomParser() { return nullptr; } namespace QQmlPrivate { void Q_QML_EXPORT qdeclarativeelement_destructor(QObject *); template class QQmlElement final : public T { public: ~QQmlElement() override { QQmlPrivate::qdeclarativeelement_destructor(this); } static void operator delete(void *ptr) { // We allocate memory from this class in QQmlType::create // along with some additional memory. // So we override the operator delete in order to avoid the // sized operator delete to be called with a different size than // the size that was allocated. ::operator delete (ptr); } static void operator delete(void *, void *) { // Deliberately empty placement delete operator. // Silences MSVC warning C4291: no matching operator delete found } }; template constexpr bool isConstructible() { return std::is_default_constructible::value && std::is_base_of::value; } template void createInto(void *memory) { new (memory) QQmlElement; } template QObject *createSingletonInstance(QQmlEngine *, QJSEngine *) { return new T; } template QObject *createParent(QObject *p) { return new T(p); } using CreateIntoFunction = void (*)(void *); using CreateSingletonFunction = QObject *(*)(QQmlEngine *, QJSEngine *); using CreateParentFunction = QObject *(*)(QObject *); template()> struct Constructors; template struct Constructors { static constexpr CreateIntoFunction createInto = QQmlPrivate::createInto; static constexpr CreateSingletonFunction createSingletonInstance = QQmlPrivate::createSingletonInstance; }; template struct Constructors { static constexpr CreateIntoFunction createInto = nullptr; static constexpr CreateSingletonFunction createSingletonInstance = nullptr; }; template::value> struct ExtendedType; // void means "not an extended type" template struct ExtendedType { static constexpr const CreateParentFunction createParent = nullptr; static constexpr const QMetaObject *staticMetaObject = nullptr; }; // If it's not void, we actually want an error if the ctor or the metaobject is missing. template struct ExtendedType { static constexpr const CreateParentFunction createParent = QQmlPrivate::createParent; static constexpr const QMetaObject *staticMetaObject = &T::staticMetaObject; }; template struct StaticCastSelectorClass { static inline int cast() { return -1; } }; template struct StaticCastSelectorClass { static inline int cast() { return int(reinterpret_cast(static_cast(reinterpret_cast(0x10000000)))) - 0x10000000; } }; template struct StaticCastSelector { typedef int yes_type; typedef char no_type; static yes_type checkType(To *); static no_type checkType(...); static inline int cast() { return StaticCastSelectorClass(0)))>::cast(); } }; template using QmlVoidT = void; // You can prevent subclasses from using the same attached type by specialzing this. // This is reserved for internal types, though. template struct OverridableAttachedType { using Type = A; }; template, bool OldStyle = QQmlTypeInfo::hasAttachedProperties> struct QmlAttached { using Type = void; using Func = QQmlAttachedPropertiesFunc; static const QMetaObject *staticMetaObject() { return nullptr; } static Func attachedPropertiesFunc() { return nullptr; } }; // Defined inline via QML_ATTACHED template struct QmlAttached::Type>, false> { // Normal attached properties template struct Properties { using Func = QQmlAttachedPropertiesFunc; static const QMetaObject *staticMetaObject() { return &Attached::staticMetaObject; } static Func attachedPropertiesFunc() { return Parent::qmlAttachedProperties; } }; // Disabled via OverridableAttachedType template struct Properties { using Func = QQmlAttachedPropertiesFunc; static const QMetaObject *staticMetaObject() { return nullptr; }; static Func attachedPropertiesFunc() { return nullptr; }; }; using Type = typename OverridableAttachedType::Type; using Func = typename Properties::Func; static const QMetaObject *staticMetaObject() { return Properties::staticMetaObject(); } static Func attachedPropertiesFunc() { return Properties::attachedPropertiesFunc(); } }; // Separately defined via QQmlTypeInfo template struct QmlAttached, true> { using Type = typename std::remove_pointer::type; using Func = QQmlAttachedPropertiesFunc; static const QMetaObject *staticMetaObject() { return &Type::staticMetaObject; } static Func attachedPropertiesFunc() { return T::qmlAttachedProperties; } }; // This is necessary because both the type containing a default template parameter and the type // instantiating the template need to have access to the default template parameter type. In // this case that's T::QmlAttachedType. The QML_FOREIGN macro needs to befriend specific other // types. Therefore we need some kind of "accessor". Because of compiler bugs in gcc and clang, // we cannot befriend attachedPropertiesFunc() directly. Wrapping the actual access into another // struct "fixes" that. For convenience we still want the free standing functions in addition. template struct QmlAttachedAccessor { static QQmlAttachedPropertiesFunc attachedPropertiesFunc() { return QQmlAttachedPropertiesFunc(QmlAttached::attachedPropertiesFunc()); } static const QMetaObject *staticMetaObject() { return QmlAttached::staticMetaObject(); } }; template inline QQmlAttachedPropertiesFunc attachedPropertiesFunc() { return QmlAttachedAccessor::attachedPropertiesFunc(); } template inline const QMetaObject *attachedPropertiesMetaObject() { return QmlAttachedAccessor::staticMetaObject(); } enum AutoParentResult { Parented, IncompatibleObject, IncompatibleParent }; typedef AutoParentResult (*AutoParentFunction)(QObject *object, QObject *parent); struct RegisterType { int version; int typeId; int listId; int objectSize; void (*create)(void *); QString noCreationReason; const char *uri; int versionMajor; int versionMinor; const char *elementName; const QMetaObject *metaObject; QQmlAttachedPropertiesFunc attachedPropertiesFunction; const QMetaObject *attachedPropertiesMetaObject; int parserStatusCast; int valueSourceCast; int valueInterceptorCast; QObject *(*extensionObjectCreate)(QObject *); const QMetaObject *extensionMetaObject; QQmlCustomParser *customParser; int revision; // If this is extended ensure "version" is bumped!!! }; struct RegisterTypeAndRevisions { int version; int typeId; int listId; int objectSize; void (*create)(void *); const char *uri; int versionMajor; const QMetaObject *metaObject; const QMetaObject *classInfoMetaObject; QQmlAttachedPropertiesFunc attachedPropertiesFunction; const QMetaObject *attachedPropertiesMetaObject; int parserStatusCast; int valueSourceCast; int valueInterceptorCast; QObject *(*extensionObjectCreate)(QObject *); const QMetaObject *extensionMetaObject; QQmlCustomParser *(*customParserFactory)(); }; struct RegisterInterface { int version; int typeId; int listId; const char *iid; }; struct RegisterAutoParent { int version; AutoParentFunction function; }; struct RegisterSingletonType { int version; const char *uri; int versionMajor; int versionMinor; const char *typeName; QJSValue (*scriptApi)(QQmlEngine *, QJSEngine *); QObject *(*qobjectApi)(QQmlEngine *, QJSEngine *); const QMetaObject *instanceMetaObject; // new in version 1 int typeId; // new in version 2 int revision; // new in version 2 std::function generalizedQobjectApi; // new in version 3 // If this is extended ensure "version" is bumped!!! }; struct RegisterSingletonTypeAndRevisions { int version; const char *uri; int versionMajor; QJSValue (*scriptApi)(QQmlEngine *, QJSEngine *); const QMetaObject *instanceMetaObject; const QMetaObject *classInfoMetaObject; int typeId; std::function generalizedQobjectApi; // new in version 3 }; struct RegisterCompositeType { QUrl url; const char *uri; int versionMajor; int versionMinor; const char *typeName; }; struct RegisterCompositeSingletonType { QUrl url; const char *uri; int versionMajor; int versionMinor; const char *typeName; }; struct CachedQmlUnit { const QV4::CompiledData::Unit *qmlData; void *unused1; void *unused2; }; typedef const CachedQmlUnit *(*QmlUnitCacheLookupFunction)(const QUrl &url); struct RegisterQmlUnitCacheHook { int version; QmlUnitCacheLookupFunction lookupCachedQmlUnit; }; enum RegistrationType { TypeRegistration = 0, InterfaceRegistration = 1, AutoParentRegistration = 2, SingletonRegistration = 3, CompositeRegistration = 4, CompositeSingletonRegistration = 5, QmlUnitCacheHookRegistration = 6, TypeAndRevisionsRegistration = 7, SingletonAndRevisionsRegistration = 8 }; int Q_QML_EXPORT qmlregister(RegistrationType, void *); void Q_QML_EXPORT qmlunregister(RegistrationType, quintptr); struct Q_QML_EXPORT RegisterSingletonFunctor { QObject *operator()(QQmlEngine *, QJSEngine *); QPointer m_object; bool alreadyCalled = false; }; static int indexOfOwnClassInfo(const QMetaObject *metaObject, const char *key) { if (!metaObject || !key) return -1; const int offset = metaObject->classInfoOffset(); for (int i = metaObject->classInfoCount() + offset - 1; i >= offset; --i) if (qstrcmp(key, metaObject->classInfo(i).name()) == 0) { return i; } return -1; } inline const char *classInfo(const QMetaObject *metaObject, const char *key) { return metaObject->classInfo(indexOfOwnClassInfo(metaObject, key)).value(); } inline int intClassInfo(const QMetaObject *metaObject, const char *key, int defaultValue = 0) { const int index = indexOfOwnClassInfo(metaObject, key); return (index == -1) ? defaultValue : QByteArray(metaObject->classInfo(index).value()).toInt(); } inline bool boolClassInfo(const QMetaObject *metaObject, const char *key, bool defaultValue = false) { const int index = indexOfOwnClassInfo(metaObject, key); return (index == -1) ? defaultValue : (QByteArray(metaObject->classInfo(index).value()) == "true"); } inline const char *classElementName(const QMetaObject *metaObject) { const char *elementName = classInfo(metaObject, "QML.Element"); if (qstrcmp(elementName, "auto") == 0) return metaObject->className(); if (qstrcmp(elementName, "anonymous") == 0) return nullptr; if (!elementName || elementName[0] < 'A' || elementName[0] > 'Z') { qWarning() << "Missing or unusable QML.Element class info \"" << elementName << "\"" << "for" << metaObject->className(); } return elementName; } template> struct QmlExtended { using Type = void; }; template struct QmlExtended> { using Type = typename T::QmlExtendedType; }; template> struct QmlResolved { using Type = T; }; template struct QmlResolved> { using Type = typename T::QmlForeignType; }; template> struct QmlSingleton { static constexpr bool Value = false; }; template struct QmlSingleton> { static constexpr bool Value = bool(T::QmlIsSingleton::yes); }; template void qmlRegisterSingletonAndRevisions(const char *uri, int versionMajor, const QMetaObject *classInfoMetaObject) { QML_GETTYPENAMES RegisterSingletonTypeAndRevisions api = { 0, uri, versionMajor, nullptr, &T::staticMetaObject, classInfoMetaObject, qRegisterNormalizedMetaType(pointerName.constData()), Constructors::createSingletonInstance }; qmlregister(SingletonAndRevisionsRegistration, &api); } template void qmlRegisterTypeAndRevisions(const char *uri, int versionMajor, const QMetaObject *classInfoMetaObject) { QML_GETTYPENAMES RegisterTypeAndRevisions type = { 0, qRegisterNormalizedMetaType(pointerName.constData()), qRegisterNormalizedMetaType >(listName.constData()), int(sizeof(T)), Constructors::createInto, uri, versionMajor, &T::staticMetaObject, classInfoMetaObject, attachedPropertiesFunc(), attachedPropertiesMetaObject(), StaticCastSelector::cast(), StaticCastSelector::cast(), StaticCastSelector::cast(), ExtendedType::createParent, ExtendedType::staticMetaObject, &qmlCreateCustomParser }; qmlregister(TypeAndRevisionsRegistration, &type); } } // namespace QQmlPrivate QT_END_NAMESPACE #endif // QQMLPRIVATE_H