aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmltype_p_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/qml/qqmltype_p_p.h')
-rw-r--r--src/qml/qml/qqmltype_p_p.h303
1 files changed, 303 insertions, 0 deletions
diff --git a/src/qml/qml/qqmltype_p_p.h b/src/qml/qml/qqmltype_p_p.h
new file mode 100644
index 0000000000..2bf83ddb8b
--- /dev/null
+++ b/src/qml/qml/qqmltype_p_p.h
@@ -0,0 +1,303 @@
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QQMLTYPE_P_P_H
+#define QQMLTYPE_P_P_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 <private/qqmltype_p.h>
+#include <private/qstringhash_p.h>
+#include <private/qqmlproxymetaobject_p.h>
+#include <private/qqmlrefcount_p.h>
+#include <private/qqmlpropertycache_p.h>
+#include <private/qqmlmetatype_p.h>
+#include <private/qqmltypeloader_p.h>
+#include <private/qv4executablecompilationunit_p.h>
+#include <private/qv4engine_p.h>
+
+#include <QAtomicInteger>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlTypePrivate final : public QQmlRefCounted<QQmlTypePrivate>
+{
+ Q_DISABLE_COPY_MOVE(QQmlTypePrivate)
+public:
+ struct ProxyMetaObjects
+ {
+ ~ProxyMetaObjects()
+ {
+ for (const QQmlProxyMetaObject::ProxyData &metaObject : data)
+ free(metaObject.metaObject);
+ }
+
+ QList<QQmlProxyMetaObject::ProxyData> data;
+ bool containsRevisionedAttributes = false;
+ };
+
+ struct Enums
+ {
+ ~Enums() { qDeleteAll(scopedEnums); }
+
+ QStringHash<int> enums;
+ QStringHash<int> scopedEnumIndex; // maps from enum name to index in scopedEnums
+ QList<QStringHash<int> *> scopedEnums;
+ };
+
+ QQmlTypePrivate(QQmlType::RegistrationType type);
+
+ const ProxyMetaObjects *init() const;
+
+ QUrl sourceUrl() const
+ {
+ switch (regType) {
+ case QQmlType::CompositeType:
+ return extraData.compositeTypeData;
+ case QQmlType::CompositeSingletonType:
+ return extraData.singletonTypeData->singletonInstanceInfo->url;
+ case QQmlType::InlineComponentType:
+ return extraData.inlineComponentTypeData;
+ default:
+ return QUrl();
+ }
+ }
+
+ const QQmlTypePrivate *attachedPropertiesBase(QQmlEnginePrivate *engine) const
+ {
+ for (const QQmlTypePrivate *d = this; d; d = d->resolveCompositeBaseType(engine).d.data()) {
+ if (d->regType == QQmlType::CppType)
+ return d->extraData.cppTypeData->attachedPropertiesType ? d : nullptr;
+
+ if (d->regType != QQmlType::CompositeType)
+ return nullptr;
+ }
+ return nullptr;
+ }
+
+ bool isComposite() const
+ {
+ return regType == QQmlType::CompositeType || regType == QQmlType::CompositeSingletonType;
+ }
+
+ bool isValueType() const
+ {
+ return regType == QQmlType::CppType && !(typeId.flags() & QMetaType::PointerToQObject);
+ }
+
+ QQmlType resolveCompositeBaseType(QQmlEnginePrivate *engine) const;
+ QQmlPropertyCache::ConstPtr compositePropertyCache(QQmlEnginePrivate *engine) const;
+
+ struct QQmlCppTypeData
+ {
+ int allocationSize;
+ void (*newFunc)(void *, void *);
+ void *userdata = nullptr;
+ QString noCreationReason;
+ QVariant (*createValueTypeFunc)(const QJSValue &);
+ int parserStatusCast;
+ QObject *(*extFunc)(QObject *);
+ const QMetaObject *extMetaObject;
+ QQmlCustomParser *customParser;
+ QQmlAttachedPropertiesFunc attachedPropertiesFunc;
+ const QMetaObject *attachedPropertiesType;
+ int propertyValueSourceCast;
+ int propertyValueInterceptorCast;
+ int finalizerCast;
+ bool registerEnumClassesUnscoped;
+ bool registerEnumsFromRelatedTypes;
+ bool constructValueType;
+ bool populateValueType;
+ };
+
+ struct QQmlSingletonTypeData
+ {
+ QQmlType::SingletonInstanceInfo::ConstPtr singletonInstanceInfo;
+ QObject *(*extFunc)(QObject *);
+ const QMetaObject *extMetaObject;
+ };
+
+ int index = -1;
+
+ union extraData {
+ extraData() {} // QQmlTypePrivate() does the actual construction.
+ ~extraData() {} // ~QQmlTypePrivate() does the actual destruction.
+
+ QQmlCppTypeData *cppTypeData;
+ QQmlSingletonTypeData *singletonTypeData;
+ QUrl compositeTypeData;
+ QUrl inlineComponentTypeData;
+ QMetaSequence sequentialContainerTypeData;
+ const char *interfaceTypeData;
+ } extraData;
+ static_assert(sizeof(extraData) == sizeof(void *));
+
+ QHashedString module;
+ QString name;
+ QString elementName;
+ QMetaType typeId;
+ QMetaType listId;
+ QQmlType::RegistrationType regType;
+ QTypeRevision version;
+ QTypeRevision revision = QTypeRevision::zero();
+ const QMetaObject *baseMetaObject = nullptr;
+
+ void setName(const QString &uri, const QString &element);
+
+ template<typename String>
+ static int enumValue(
+ const QQmlRefPointer<const QQmlTypePrivate> &d, QQmlEnginePrivate *engine,
+ const String &name, bool *ok)
+ {
+ return doGetEnumValue(d, engine, [&](const QQmlTypePrivate::Enums *enums) {
+ return enums->enums.value(name);
+ }, ok);
+ }
+
+ template<typename String>
+ static int scopedEnumIndex(
+ const QQmlRefPointer<const QQmlTypePrivate> &d, QQmlEnginePrivate *engine,
+ const String &name, bool *ok)
+ {
+ return doGetEnumValue(d, engine, [&](const QQmlTypePrivate::Enums *enums) {
+ return enums->scopedEnumIndex.value(name);
+ }, ok);
+ }
+
+ template<typename String>
+ static int scopedEnumValue(
+ const QQmlRefPointer<const QQmlTypePrivate> &d, QQmlEnginePrivate *engine, int index,
+ const String &name, bool *ok)
+ {
+ return doGetEnumValue(d, engine, [&](const QQmlTypePrivate::Enums *enums) {
+ Q_ASSERT(index > -1 && index < enums->scopedEnums.size());
+ return enums->scopedEnums.at(index)->value(name);
+ }, ok);
+ }
+
+ template<typename String1, typename String2>
+ static int scopedEnumValue(
+ const QQmlRefPointer<const QQmlTypePrivate> &d, QQmlEnginePrivate *engine,
+ const String1 &scopedEnumName, const String2 &name, bool *ok)
+ {
+ return doGetEnumValue(d, engine, [&](const QQmlTypePrivate::Enums *enums) -> const int * {
+ const int *rv = enums->scopedEnumIndex.value(scopedEnumName);
+ if (!rv)
+ return nullptr;
+
+ const int index = *rv;
+ Q_ASSERT(index > -1 && index < enums->scopedEnums.size());
+ return enums->scopedEnums.at(index)->value(name);
+ }, ok);
+ }
+
+ const QMetaObject *metaObject() const
+ {
+ if (isValueType())
+ return metaObjectForValueType();
+
+ const QQmlTypePrivate::ProxyMetaObjects *proxies = init();
+ return proxies->data.isEmpty()
+ ? baseMetaObject
+ : proxies->data.constFirst().metaObject;
+ }
+
+ const QMetaObject *metaObjectForValueType() const
+ {
+ Q_ASSERT(isValueType());
+
+ // Prefer the extension meta object, if any.
+ // Extensions allow registration of non-gadget value types.
+ if (const QMetaObject *extensionMetaObject = extraData.cppTypeData->extMetaObject) {
+ // This may be a namespace even if the original metaType isn't.
+ // You can do such things with QML_FOREIGN declarations.
+ if (extensionMetaObject->metaType().flags() & QMetaType::IsGadget)
+ return extensionMetaObject;
+ }
+
+ if (baseMetaObject) {
+ // This may be a namespace even if the original metaType isn't.
+ // You can do such things with QML_FOREIGN declarations.
+ if (baseMetaObject->metaType().flags() & QMetaType::IsGadget)
+ return baseMetaObject;
+ }
+
+ return nullptr;
+ }
+
+ static QQmlType compositeQmlType(
+ const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &unit,
+ QQmlTypeLoader *typeLoader, const QString &type)
+ {
+ Q_ASSERT(typeLoader);
+
+ const QQmlType qmltype
+ = unit->typeNameCache->query<QQmlImport::AllowRecursion>(type, typeLoader).type;
+ if (!qmltype.isValid())
+ return qmltype;
+
+ if (qmltype.isInlineComponentType()
+ && !QQmlMetaType::obtainCompilationUnit(qmltype.typeId())) {
+ // If it seems to be an IC type, make sure there is an actual
+ // compilation unit for it. We create inline component types speculatively.
+ return QQmlType();
+ }
+
+ return qmltype;
+ }
+
+private:
+ mutable QAtomicPointer<const ProxyMetaObjects> proxyMetaObjects;
+ mutable QAtomicPointer<const Enums> enums;
+
+ ~QQmlTypePrivate();
+ friend class QQmlRefCounted<QQmlTypePrivate>;
+
+ struct EnumInfo {
+ QStringList path;
+ QString metaObjectName;
+ QString enumName;
+ QString enumKey;
+ QString metaEnumScope;
+ bool scoped;
+ };
+
+ template<typename Op>
+ static int doGetEnumValue(
+ const QQmlRefPointer<const QQmlTypePrivate> &d, QQmlEnginePrivate *engine,
+ Op &&op, bool *ok)
+ {
+ Q_ASSERT(ok);
+ if (d) {
+ if (const QQmlTypePrivate::Enums *enums = d->initEnums(engine)) {
+ if (const int *rv = op(enums)) {
+ *ok = true;
+ return *rv;
+ }
+ }
+ }
+
+ *ok = false;
+ return -1;
+ }
+
+ const Enums *initEnums(QQmlEnginePrivate *engine) const;
+ void insertEnums(Enums *enums, const QMetaObject *metaObject) const;
+ void insertEnumsFromPropertyCache(Enums *enums, const QQmlPropertyCache::ConstPtr &cache) const;
+
+ void createListOfPossibleConflictingItems(const QMetaObject *metaObject, QList<EnumInfo> &enumInfoList, QStringList path) const;
+ void createEnumConflictReport(const QMetaObject *metaObject, const QString &conflictingKey) const;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLTYPE_P_P_H