aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmltype.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/qml/qqmltype.cpp')
-rw-r--r--src/qml/qml/qqmltype.cpp684
1 files changed, 258 insertions, 426 deletions
diff --git a/src/qml/qml/qqmltype.cpp b/src/qml/qml/qqmltype.cpp
index 811ff668c6..533c3909ba 100644
--- a/src/qml/qml/qqmltype.cpp
+++ b/src/qml/qml/qqmltype.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 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$
-**
-****************************************************************************/
+// 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
#include "qqmltype_p_p.h"
@@ -53,45 +17,44 @@
QT_BEGIN_NAMESPACE
QQmlTypePrivate::QQmlTypePrivate(QQmlType::RegistrationType type)
- : regType(type), iid(nullptr), revision(QTypeRevision::zero()),
- containsRevisionedAttributes(false), baseMetaObject(nullptr),
- index(-1), isSetup(false), isEnumFromCacheSetup(false), isEnumFromBaseSetup(false),
- haveSuperType(false)
+ : regType(type)
{
switch (type) {
case QQmlType::CppType:
- extraData.cd = new QQmlCppTypeData;
- extraData.cd->allocationSize = 0;
- extraData.cd->newFunc = nullptr;
- extraData.cd->createValueTypeFunc = nullptr;
- extraData.cd->parserStatusCast = -1;
- extraData.cd->extFunc = nullptr;
- extraData.cd->extMetaObject = nullptr;
- extraData.cd->customParser = nullptr;
- extraData.cd->attachedPropertiesFunc = nullptr;
- extraData.cd->attachedPropertiesType = nullptr;
- extraData.cd->propertyValueSourceCast = -1;
- extraData.cd->propertyValueInterceptorCast = -1;
- extraData.cd->registerEnumClassesUnscoped = true;
+ extraData.cppTypeData = new QQmlCppTypeData;
+ extraData.cppTypeData->allocationSize = 0;
+ extraData.cppTypeData->newFunc = nullptr;
+ extraData.cppTypeData->createValueTypeFunc = nullptr;
+ extraData.cppTypeData->parserStatusCast = -1;
+ extraData.cppTypeData->extFunc = nullptr;
+ extraData.cppTypeData->extMetaObject = nullptr;
+ extraData.cppTypeData->customParser = nullptr;
+ extraData.cppTypeData->attachedPropertiesFunc = nullptr;
+ extraData.cppTypeData->attachedPropertiesType = nullptr;
+ extraData.cppTypeData->propertyValueSourceCast = -1;
+ extraData.cppTypeData->propertyValueInterceptorCast = -1;
+ extraData.cppTypeData->finalizerCast = -1;
+ extraData.cppTypeData->registerEnumClassesUnscoped = true;
+ extraData.cppTypeData->registerEnumsFromRelatedTypes = true;
break;
case QQmlType::SingletonType:
case QQmlType::CompositeSingletonType:
- extraData.sd = new QQmlSingletonTypeData;
- extraData.sd->singletonInstanceInfo = nullptr;
- extraData.sd->extFunc = nullptr;
- extraData.sd->extMetaObject = nullptr;
+ extraData.singletonTypeData = new QQmlSingletonTypeData;
+ extraData.singletonTypeData->singletonInstanceInfo = nullptr;
+ extraData.singletonTypeData->extFunc = nullptr;
+ extraData.singletonTypeData->extMetaObject = nullptr;
break;
case QQmlType::InterfaceType:
- extraData.cd = nullptr;
+ extraData.interfaceTypeData = nullptr;
break;
case QQmlType::CompositeType:
- extraData.fd = new QQmlCompositeTypeData;
+ new (&extraData.compositeTypeData) QUrl();
break;
case QQmlType::InlineComponentType:
- extraData.id = new QQmlInlineTypeData;
+ new (&extraData.inlineComponentTypeData) QUrl();
break;
case QQmlType::SequentialContainerType:
- extraData.ld = new QQmlSequenceTypeData;
+ new (&extraData.sequentialContainerTypeData) QMetaSequence();
break;
default: qFatal("QQmlTypePrivate Internal Error.");
}
@@ -99,27 +62,32 @@ QQmlTypePrivate::QQmlTypePrivate(QQmlType::RegistrationType type)
QQmlTypePrivate::~QQmlTypePrivate()
{
- qDeleteAll(scopedEnums);
- for (const auto &metaObject : metaObjects)
- free(metaObject.metaObject);
+ delete enums.fetchAndStoreAcquire(nullptr);
+ delete proxyMetaObjects.fetchAndStoreAcquire(nullptr);
+
+ if (const QtPrivate::QMetaTypeInterface *iface = typeId.iface()) {
+ if (iface->metaObjectFn == &dynamicQmlMetaObject)
+ QQmlMetaType::unregisterInternalCompositeType(typeId, listId);
+ }
+
switch (regType) {
case QQmlType::CppType:
- delete extraData.cd->customParser;
- delete extraData.cd;
+ delete extraData.cppTypeData->customParser;
+ delete extraData.cppTypeData;
break;
case QQmlType::SingletonType:
case QQmlType::CompositeSingletonType:
- delete extraData.sd->singletonInstanceInfo;
- delete extraData.sd;
+ extraData.singletonTypeData->singletonInstanceInfo.reset();
+ delete extraData.singletonTypeData;
break;
case QQmlType::CompositeType:
- delete extraData.fd;
+ extraData.compositeTypeData.~QUrl();
break;
case QQmlType::InlineComponentType:
- delete extraData.id;
+ extraData.inlineComponentTypeData.~QUrl();
break;
case QQmlType::SequentialContainerType:
- delete extraData.ld;
+ extraData.sequentialContainerTypeData.~QMetaSequence();
break;
default: //Also InterfaceType, because it has no extra data
break;
@@ -178,12 +146,13 @@ QQmlType QQmlTypePrivate::resolveCompositeBaseType(QQmlEnginePrivate *engine) co
QQmlRefPointer<QQmlTypeData> td(engine->typeLoader.getType(sourceUrl()));
if (td.isNull() || !td->isComplete())
return QQmlType();
- QV4::ExecutableCompilationUnit *compilationUnit = td->compilationUnit();
+ QV4::CompiledData::CompilationUnit *compilationUnit = td->compilationUnit();
const QMetaObject *mo = compilationUnit->rootPropertyCache()->firstCppMetaObject();
return QQmlMetaType::qmlType(mo);
}
-QQmlPropertyCache *QQmlTypePrivate::compositePropertyCache(QQmlEnginePrivate *engine) const
+QQmlPropertyCache::ConstPtr QQmlTypePrivate::compositePropertyCache(
+ QQmlEnginePrivate *engine) const
{
// similar logic to resolveCompositeBaseType
Q_ASSERT(isComposite());
@@ -192,8 +161,8 @@ QQmlPropertyCache *QQmlTypePrivate::compositePropertyCache(QQmlEnginePrivate *en
QQmlRefPointer<QQmlTypeData> td(engine->typeLoader.getType(sourceUrl()));
if (td.isNull() || !td->isComplete())
return nullptr;
- QV4::ExecutableCompilationUnit *compilationUnit = td->compilationUnit();
- return compilationUnit->rootPropertyCache().data();
+ QV4::CompiledData::CompilationUnit *compilationUnit = td->compilationUnit();
+ return compilationUnit->rootPropertyCache();
}
static bool isPropertyRevisioned(const QMetaObject *mo, int index)
@@ -201,54 +170,63 @@ static bool isPropertyRevisioned(const QMetaObject *mo, int index)
return mo->property(index).revision();
}
-void QQmlTypePrivate::init() const
+const QQmlTypePrivate::ProxyMetaObjects *QQmlTypePrivate::init() const
{
- if (isSetup.loadAcquire())
- return;
+ if (const ProxyMetaObjects *result = proxyMetaObjects.loadRelaxed())
+ return result;
- QMutexLocker lock(QQmlMetaType::typeRegistrationLock());
- if (isSetup.loadAcquire())
- return;
+ ProxyMetaObjects *proxies = new ProxyMetaObjects;
+ auto finalize = [this, proxies]() -> const ProxyMetaObjects *{
+ const ProxyMetaObjects *concurrentModification;
+ if (proxyMetaObjects.testAndSetOrdered(nullptr, proxies, concurrentModification))
+ return proxies;
+
+ delete proxies;
+ return concurrentModification;
+ };
const QMetaObject *mo = baseMetaObject;
if (!mo) {
// version 0 singleton type without metaobject information
- return;
+ return finalize();
}
- auto setupExtendedMetaObject = [&](
- const QMetaObject *extMetaObject,
- QObject *(*extFunc)(QObject *)) {
+ QList<QQmlProxyMetaObject::ProxyData> metaObjects;
+ auto setupExtendedMetaObject = [&](const QMetaObject *extMetaObject,
+ QObject *(*extFunc)(QObject *)) {
if (!extMetaObject)
return;
// XXX - very inefficient
QMetaObjectBuilder builder;
- QQmlMetaType::clone(builder, extMetaObject, extMetaObject, extMetaObject);
- builder.setFlags(MetaObjectFlag::DynamicMetaObject);
+ QQmlMetaType::clone(builder, extMetaObject, extMetaObject, extMetaObject,
+ extFunc ? QQmlMetaType::CloneAll : QQmlMetaType::CloneEnumsOnly);
QMetaObject *mmo = builder.toMetaObject();
mmo->d.superdata = mo;
QQmlProxyMetaObject::ProxyData data = { mmo, extFunc, 0, 0 };
metaObjects << data;
+ QQmlMetaType::registerMetaObjectForType(mmo, const_cast<QQmlTypePrivate *>(this));
};
if (regType == QQmlType::SingletonType)
- setupExtendedMetaObject(extraData.sd->extMetaObject, extraData.sd->extFunc);
+ setupExtendedMetaObject(extraData.singletonTypeData->extMetaObject, extraData.singletonTypeData->extFunc);
else if (regType == QQmlType::CppType)
- setupExtendedMetaObject(extraData.cd->extMetaObject, extraData.cd->extFunc);
+ setupExtendedMetaObject(extraData.cppTypeData->extMetaObject, extraData.cppTypeData->extFunc);
metaObjects.append(QQmlMetaType::proxyData(
mo, baseMetaObject, metaObjects.isEmpty() ? nullptr
: metaObjects.constLast().metaObject));
- for (int ii = 0; ii < metaObjects.count(); ++ii) {
+ for (int ii = 0; ii < metaObjects.size(); ++ii) {
metaObjects[ii].propertyOffset =
metaObjects.at(ii).metaObject->propertyOffset();
metaObjects[ii].methodOffset =
metaObjects.at(ii).metaObject->methodOffset();
}
+ bool containsRevisionedAttributes = false;
+
// Check for revisioned details
{
const QMetaObject *mo = nullptr;
@@ -268,53 +246,75 @@ void QQmlTypePrivate::init() const
}
}
- isSetup.storeRelease(true);
- lock.unlock();
+ proxies->data = std::move(metaObjects);
+ proxies->containsRevisionedAttributes = containsRevisionedAttributes;
+
+ return finalize();
}
-void QQmlTypePrivate::initEnums(QQmlEnginePrivate *engine) const
+const QQmlTypePrivate::Enums *QQmlTypePrivate::initEnums(QQmlEnginePrivate *engine) const
{
- const QQmlPropertyCache *cache = (!isEnumFromCacheSetup.loadAcquire() && isComposite())
- ? compositePropertyCache(engine)
- : nullptr;
+ if (const Enums *result = enums.loadRelaxed())
+ return result;
- // beware: It could be a singleton type without metaobject
- const QMetaObject *metaObject = !isEnumFromBaseSetup.loadAcquire()
- ? baseMetaObject
- : nullptr;
+ QQmlPropertyCache::ConstPtr cache;
+ if (isComposite()) {
+ cache = compositePropertyCache(engine);
+ if (!cache)
+ return nullptr; // Composite type not ready, yet.
+ }
- if (!cache && !metaObject)
- return;
+ Enums *newEnums = new Enums;
- init(); // init() can add to the metaObjects list. Therefore, check metaObjects only below
+ // beware: It could be a singleton type without metaobject
- QMutexLocker lock(QQmlMetaType::typeRegistrationLock());
+ if (cache)
+ insertEnumsFromPropertyCache(newEnums, cache);
- if (cache) {
- insertEnumsFromPropertyCache(cache);
- isEnumFromCacheSetup.storeRelease(true);
+ if (baseMetaObject) {
+ // init() can add to the metaObjects list. Therefore, check proxies->data only below
+ const ProxyMetaObjects *proxies = init();
+ insertEnums(
+ newEnums,
+ proxies->data.isEmpty() ? baseMetaObject : proxies->data.constFirst().metaObject);
}
- if (metaObject) {
- insertEnums(metaObjects.isEmpty() ? baseMetaObject : metaObjects.constFirst().metaObject);
- isEnumFromBaseSetup.storeRelease(true);
- }
+ const Enums *concurrentModification;
+ if (enums.testAndSetOrdered(nullptr, newEnums, concurrentModification))
+ return newEnums;
+
+ delete newEnums;
+ return concurrentModification;
}
-void QQmlTypePrivate::insertEnums(const QMetaObject *metaObject) const
+void QQmlTypePrivate::insertEnums(Enums *enums, const QMetaObject *metaObject) const
{
// Add any enum values defined by 'related' classes
- if (metaObject->d.relatedMetaObjects) {
- const auto *related = metaObject->d.relatedMetaObjects;
- if (related) {
- while (*related)
- insertEnums(*related++);
+ if (regType != QQmlType::CppType || extraData.cppTypeData->registerEnumsFromRelatedTypes) {
+ if (const auto *related = metaObject->d.relatedMetaObjects) {
+ while (const QMetaObject *relatedMetaObject = *related) {
+ insertEnums(enums, relatedMetaObject);
+ ++related;
+ }
}
}
QSet<QString> localEnums;
const QMetaObject *localMetaObject = nullptr;
+ // ### TODO (QTBUG-123294): track this at instance creation time
+ auto shouldSingletonAlsoRegisterUnscoped = [&](){
+ Q_ASSERT(regType == QQmlType::SingletonType);
+ if (!baseMetaObject)
+ return true;
+ int idx = baseMetaObject->indexOfClassInfo("RegisterEnumClassesUnscoped");
+ if (idx == -1)
+ return true;
+ if (qstrcmp(baseMetaObject->classInfo(idx).value(), "false") == 0)
+ return false;
+ return true;
+ };
+
// Add any enum values defined by this class, overwriting any inherited values
for (int ii = 0; ii < metaObject->enumeratorCount(); ++ii) {
QMetaEnum e = metaObject->enumerator(ii);
@@ -331,29 +331,33 @@ void QQmlTypePrivate::insertEnums(const QMetaObject *metaObject) const
localEnums.clear();
localMetaObject = e.enclosingMetaObject();
}
+ const bool shouldRegisterUnscoped = !isScoped
+ || (regType == QQmlType::CppType && extraData.cppTypeData->registerEnumClassesUnscoped)
+ || (regType == QQmlType::SingletonType && shouldSingletonAlsoRegisterUnscoped())
+ ;
for (int jj = 0; jj < e.keyCount(); ++jj) {
const QString key = QString::fromUtf8(e.key(jj));
const int value = e.value(jj);
- if (!isScoped || (regType == QQmlType::CppType && extraData.cd->registerEnumClassesUnscoped)) {
+ if (shouldRegisterUnscoped) {
if (localEnums.contains(key)) {
- auto existingEntry = enums.find(key);
- if (existingEntry != enums.end() && existingEntry.value() != value) {
+ auto existingEntry = enums->enums.find(key);
+ if (existingEntry != enums->enums.end() && existingEntry.value() != value) {
qWarning("Previously registered enum will be overwritten due to name clash: %s.%s", metaObject->className(), key.toUtf8().constData());
createEnumConflictReport(metaObject, key);
}
} else {
localEnums.insert(key);
}
- enums.insert(key, value);
+ enums->enums.insert(key, value);
}
if (isScoped)
scoped->insert(key, value);
}
if (isScoped) {
- scopedEnums << scoped;
- scopedEnumIndex.insert(QString::fromUtf8(e.name()), scopedEnums.count()-1);
+ enums->scopedEnums << scoped;
+ enums->scopedEnumIndex.insert(QString::fromUtf8(e.name()), enums->scopedEnums.size()-1);
}
}
}
@@ -404,41 +408,37 @@ void QQmlTypePrivate::createEnumConflictReport(const QMetaObject *metaObject, co
qWarning().noquote() << QLatin1String("Possible conflicting items:");
// find items with conflicting key
- for (const auto &i : qAsConst(enumInfoList)) {
+ for (const auto &i : std::as_const(enumInfoList)) {
if (i.enumKey == conflictingKey)
qWarning().noquote().nospace() << " " << i.metaObjectName << "." << i.enumName << "." << i.enumKey << " from scope "
<< i.metaEnumScope << " injected by " << i.path.join(QLatin1String("->"));
}
}
-void QQmlTypePrivate::insertEnumsFromPropertyCache(const QQmlPropertyCache *cache) const
+void QQmlTypePrivate::insertEnumsFromPropertyCache(
+ Enums *enums, const QQmlPropertyCache::ConstPtr &cache) const
{
const QMetaObject *cppMetaObject = cache->firstCppMetaObject();
- while (cache && cache->metaObject() != cppMetaObject) {
+ for (const QQmlPropertyCache *currentCache = cache.data();
+ currentCache && currentCache->metaObject() != cppMetaObject;
+ currentCache = currentCache->parent().data()) {
- int count = cache->qmlEnumCount();
+ int count = currentCache->qmlEnumCount();
for (int ii = 0; ii < count; ++ii) {
QStringHash<int> *scoped = new QStringHash<int>();
- QQmlEnumData *enumData = cache->qmlEnum(ii);
+ QQmlEnumData *enumData = currentCache->qmlEnum(ii);
- for (int jj = 0; jj < enumData->values.count(); ++jj) {
+ for (int jj = 0; jj < enumData->values.size(); ++jj) {
const QQmlEnumValue &value = enumData->values.at(jj);
- enums.insert(value.namedValue, value.value);
+ enums->enums.insert(value.namedValue, value.value);
scoped->insert(value.namedValue, value.value);
}
- scopedEnums << scoped;
- scopedEnumIndex.insert(enumData->name, scopedEnums.count()-1);
+ enums->scopedEnums << scoped;
+ enums->scopedEnumIndex.insert(enumData->name, enums->scopedEnums.size()-1);
}
- cache = cache->parent();
}
- insertEnums(cppMetaObject);
-}
-
-void QQmlTypePrivate::setContainingType(QQmlType *containingType)
-{
- Q_ASSERT(regType == QQmlType::InlineComponentType);
- extraData.id->containingType = containingType->d.data();
+ insertEnums(enums, cppMetaObject);
}
void QQmlTypePrivate::setName(const QString &uri, const QString &element)
@@ -452,11 +452,9 @@ QByteArray QQmlType::typeName() const
{
if (d) {
if (d->regType == SingletonType || d->regType == CompositeSingletonType)
- return d->extraData.sd->singletonInstanceInfo->typeName.toUtf8();
+ return d->extraData.singletonTypeData->singletonInstanceInfo->typeName;
else if (d->baseMetaObject)
return d->baseMetaObject->className();
- else if (d->regType == InlineComponentType)
- return d->extraData.id->inlineComponentName.toUtf8();
}
return QByteArray();
}
@@ -475,43 +473,68 @@ QString QQmlType::qmlTypeName() const
return d->name;
}
+/*!
+ \internal
+ Allocates and initializes an object if the type is creatable.
+ Returns a pointer to the object, or nullptr if the type was
+ not creatable.
+ */
QObject *QQmlType::create() const
{
- if (!d || !isCreatable())
- return nullptr;
+ void *unused;
+ return create(&unused, 0);
+}
- d->init();
+/*!
+ \internal
+ \brief Like create without arguments, but allocates some extra space after the object.
+ \param memory An out-only argument. *memory will point to the start of the additionally
+ allocated memory.
+ \param additionalMemory The amount of extra memory in bytes that shoudld be allocated.
- QObject *rv = (QObject *)operator new(d->extraData.cd->allocationSize);
+ \note This function is used to allocate the QQmlData next to the object in the
+ QQmlObjectCreator.
- d->extraData.cd->newFunc(rv, d->extraData.cd->userdata);
+ \overload
+ */
+QObject *QQmlType::create(void **memory, size_t additionalMemory) const
+{
+ if (!d || !isCreatable())
+ return nullptr;
+
+ QObject *rv = (QObject *)operator new(d->extraData.cppTypeData->allocationSize + additionalMemory);
+ d->extraData.cppTypeData->newFunc(rv, d->extraData.cppTypeData->userdata);
createProxy(rv);
+ *memory = ((char *)rv) + d->extraData.cppTypeData->allocationSize;
return rv;
}
-void QQmlType::create(QObject **out, void **memory, size_t additionalMemory) const
+/*!
+ \internal
+ Like create, but also allocates memory behind the object, constructs a QQmlData there
+ and lets the objects declarativeData point to the newly created QQmlData.
+ */
+QObject *QQmlType::createWithQQmlData() const
{
- if (!d || !isCreatable())
- return;
-
- d->init();
-
- QObject *rv = (QObject *)operator new(d->extraData.cd->allocationSize + additionalMemory);
- d->extraData.cd->newFunc(rv, d->extraData.cd->userdata);
-
- createProxy(rv);
- *out = rv;
- *memory = ((char *)rv) + d->extraData.cd->allocationSize;
+ void *ddataMemory = nullptr;
+ auto instance = create(&ddataMemory, sizeof(QQmlData));
+ if (!instance)
+ return nullptr;
+ QObjectPrivate* p = QObjectPrivate::get(instance);
+ Q_ASSERT(!p->isDeletingChildren);
+ if (!p->declarativeData)
+ p->declarativeData = new (ddataMemory) QQmlData(QQmlData::DoesNotOwnMemory);
+ return instance;
}
-QQmlType::SingletonInstanceInfo *QQmlType::singletonInstanceInfo() const
+QQmlType::SingletonInstanceInfo::ConstPtr QQmlType::singletonInstanceInfo() const
{
if (!d)
- return nullptr;
+ return {};
if (d->regType != SingletonType && d->regType != CompositeSingletonType)
- return nullptr;
- return d->extraData.sd->singletonInstanceInfo;
+ return {};
+ return d->extraData.singletonTypeData->singletonInstanceInfo;
}
QQmlCustomParser *QQmlType::customParser() const
@@ -520,33 +543,47 @@ QQmlCustomParser *QQmlType::customParser() const
return nullptr;
if (d->regType != CppType)
return nullptr;
- return d->extraData.cd->customParser;
+ return d->extraData.cppTypeData->customParser;
}
QQmlType::CreateValueTypeFunc QQmlType::createValueTypeFunction() const
{
if (!d || d->regType != CppType)
return nullptr;
- return d->extraData.cd->createValueTypeFunc;
+ return d->extraData.cppTypeData->createValueTypeFunc;
+}
+
+bool QQmlType::canConstructValueType() const
+{
+ if (!d || d->regType != CppType)
+ return false;
+ return d->extraData.cppTypeData->constructValueType;
+}
+
+bool QQmlType::canPopulateValueType() const
+{
+ if (!d || d->regType != CppType)
+ return false;
+ return d->extraData.cppTypeData->populateValueType;
}
QQmlType::CreateFunc QQmlType::createFunction() const
{
if (!d || d->regType != CppType)
return nullptr;
- return d->extraData.cd->newFunc;
+ return d->extraData.cppTypeData->newFunc;
}
QString QQmlType::noCreationReason() const
{
if (!d || d->regType != CppType)
return QString();
- return d->extraData.cd->noCreationReason;
+ return d->extraData.cppTypeData->noCreationReason;
}
bool QQmlType::isCreatable() const
{
- return d && d->regType == CppType && d->extraData.cd->newFunc;
+ return d && d->regType == CppType && d->extraData.cppTypeData->newFunc;
}
QQmlType::ExtensionFunc QQmlType::extensionFunction() const
@@ -556,9 +593,9 @@ QQmlType::ExtensionFunc QQmlType::extensionFunction() const
switch (d->regType) {
case CppType:
- return d->extraData.cd->extFunc;
+ return d->extraData.cppTypeData->extFunc;
case SingletonType:
- return d->extraData.sd->extFunc;
+ return d->extraData.singletonTypeData->extFunc;
default:
return nullptr;
}
@@ -571,9 +608,9 @@ const QMetaObject *QQmlType::extensionMetaObject() const
switch (d->regType) {
case CppType:
- return d->extraData.cd->extMetaObject;
+ return d->extraData.cppTypeData->extMetaObject;
case SingletonType:
- return d->extraData.sd->extMetaObject;
+ return d->extraData.singletonTypeData->extMetaObject;
default:
return nullptr;
}
@@ -581,11 +618,7 @@ const QMetaObject *QQmlType::extensionMetaObject() const
bool QQmlType::isExtendedType() const
{
- if (!d)
- return false;
- d->init();
-
- return !d->metaObjects.isEmpty();
+ return d && !d->init()->data.isEmpty();
}
bool QQmlType::isSingleton() const
@@ -614,12 +647,12 @@ bool QQmlType::isCompositeSingleton() const
bool QQmlType::isQObjectSingleton() const
{
- return d && d->regType == SingletonType && d->extraData.sd->singletonInstanceInfo->qobjectCallback;
+ return d && d->regType == SingletonType && d->extraData.singletonTypeData->singletonInstanceInfo->qobjectCallback;
}
bool QQmlType::isQJSValueSingleton() const
{
- return d && d->regType == SingletonType && d->extraData.sd->singletonInstanceInfo->scriptCallback;
+ return d && d->regType == SingletonType && d->extraData.singletonTypeData->singletonInstanceInfo->scriptCallback;
}
bool QQmlType::isSequentialContainer() const
@@ -627,6 +660,11 @@ bool QQmlType::isSequentialContainer() const
return d && d->regType == SequentialContainerType;
}
+bool QQmlType::isValueType() const
+{
+ return d && d->isValueType();
+}
+
QMetaType QQmlType::typeId() const
{
return d ? d->typeId : QMetaType{};
@@ -637,17 +675,20 @@ QMetaType QQmlType::qListTypeId() const
return d ? d->listId : QMetaType{};
}
-const QMetaObject *QQmlType::metaObject() const
+QMetaSequence QQmlType::listMetaSequence() const
{
- if (!d)
- return nullptr;
- d->init();
+ return isSequentialContainer() ? d->extraData.sequentialContainerTypeData : QMetaSequence();
+}
- if (d->metaObjects.isEmpty())
- return d->baseMetaObject;
- else
- return d->metaObjects.constFirst().metaObject;
+const QMetaObject *QQmlType::metaObject() const
+{
+ return d ? d->metaObject() : nullptr;
+}
+const QMetaObject *QQmlType::metaObjectForValueType() const
+{
+ Q_ASSERT(d);
+ return d->metaObjectForValueType();
}
const QMetaObject *QQmlType::baseMetaObject() const
@@ -657,11 +698,7 @@ const QMetaObject *QQmlType::baseMetaObject() const
bool QQmlType::containsRevisionedAttributes() const
{
- if (!d)
- return false;
- d->init();
-
- return d->containsRevisionedAttributes;
+ return d && d->init()->containsRevisionedAttributes;
}
QTypeRevision QQmlType::metaObjectRevision() const
@@ -672,14 +709,14 @@ QTypeRevision QQmlType::metaObjectRevision() const
QQmlAttachedPropertiesFunc QQmlType::attachedPropertiesFunction(QQmlEnginePrivate *engine) const
{
if (const QQmlTypePrivate *base = d ? d->attachedPropertiesBase(engine) : nullptr)
- return base->extraData.cd->attachedPropertiesFunc;
+ return base->extraData.cppTypeData->attachedPropertiesFunc;
return nullptr;
}
const QMetaObject *QQmlType::attachedPropertiesType(QQmlEnginePrivate *engine) const
{
if (const QQmlTypePrivate *base = d ? d->attachedPropertiesBase(engine) : nullptr)
- return base->extraData.cd->attachedPropertiesType;
+ return base->extraData.cppTypeData->attachedPropertiesType;
return nullptr;
}
@@ -687,28 +724,35 @@ int QQmlType::parserStatusCast() const
{
if (!d || d->regType != CppType)
return -1;
- return d->extraData.cd->parserStatusCast;
+ return d->extraData.cppTypeData->parserStatusCast;
}
int QQmlType::propertyValueSourceCast() const
{
if (!d || d->regType != CppType)
return -1;
- return d->extraData.cd->propertyValueSourceCast;
+ return d->extraData.cppTypeData->propertyValueSourceCast;
}
int QQmlType::propertyValueInterceptorCast() const
{
if (!d || d->regType != CppType)
return -1;
- return d->extraData.cd->propertyValueInterceptorCast;
+ return d->extraData.cppTypeData->propertyValueInterceptorCast;
+}
+
+int QQmlType::finalizerCast() const
+{
+ if (!d || d->regType != CppType)
+ return -1;
+ return d->extraData.cppTypeData->finalizerCast;
}
const char *QQmlType::interfaceIId() const
{
if (!d || d->regType != InterfaceType)
return nullptr;
- return d->iid;
+ return d->extraData.interfaceTypeData;
}
int QQmlType::index() const
@@ -720,200 +764,49 @@ bool QQmlType::isInlineComponentType() const {
return d ? d->regType == QQmlType::InlineComponentType : false;
}
-int QQmlType::inlineComponentId() const {
- bool ok = false;
- if (d->regType == QQmlType::RegistrationType::InlineComponentType) {
- Q_ASSERT(d->extraData.id->objectId != -1);
- return d->extraData.id->objectId;
- }
- int subObjectId = sourceUrl().fragment().toInt(&ok);
- return ok ? subObjectId : -1;
-}
-
QUrl QQmlType::sourceUrl() const
{
- auto url = d ? d->sourceUrl() : QUrl();
- if (url.isValid() && d->regType == QQmlType::RegistrationType::InlineComponentType && d->extraData.id->objectId) {
- Q_ASSERT(url.hasFragment());
- url.setFragment(QString::number(inlineComponentId()));
- }
- return url;
+ return d ? d->sourceUrl() : QUrl();
}
int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedStringRef &name, bool *ok) const
{
- Q_ASSERT(ok);
- if (d) {
- *ok = true;
-
- d->initEnums(engine);
-
- int *rv = d->enums.value(name);
- if (rv)
- return *rv;
- }
-
- *ok = false;
- return -1;
+ return QQmlTypePrivate::enumValue(d, engine, name, ok);
}
int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedCStringRef &name, bool *ok) const
{
- Q_ASSERT(ok);
- if (d) {
- *ok = true;
-
- d->initEnums(engine);
-
- int *rv = d->enums.value(name);
- if (rv)
- return *rv;
- }
-
- *ok = false;
- return -1;
+ return QQmlTypePrivate::enumValue(d, engine, name, ok);
}
int QQmlType::enumValue(QQmlEnginePrivate *engine, const QV4::String *name, bool *ok) const
{
- Q_ASSERT(ok);
- if (d) {
- *ok = true;
-
- d->initEnums(engine);
-
- int *rv = d->enums.value(name);
- if (rv)
- return *rv;
- }
-
- *ok = false;
- return -1;
+ return QQmlTypePrivate::enumValue(d, engine, name, ok);
}
int QQmlType::scopedEnumIndex(QQmlEnginePrivate *engine, const QV4::String *name, bool *ok) const
{
- Q_ASSERT(ok);
- if (d) {
- *ok = true;
-
- d->initEnums(engine);
-
- int *rv = d->scopedEnumIndex.value(name);
- if (rv)
- return *rv;
- }
-
- *ok = false;
- return -1;
+ return QQmlTypePrivate::scopedEnumIndex(d, engine, name, ok);
}
int QQmlType::scopedEnumIndex(QQmlEnginePrivate *engine, const QString &name, bool *ok) const
{
- Q_ASSERT(ok);
- if (d) {
- *ok = true;
-
- d->initEnums(engine);
-
- int *rv = d->scopedEnumIndex.value(name);
- if (rv)
- return *rv;
- }
-
- *ok = false;
- return -1;
+ return QQmlTypePrivate::scopedEnumIndex(d, engine, name, ok);
}
int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, int index, const QV4::String *name, bool *ok) const
{
- Q_UNUSED(engine);
- Q_ASSERT(ok);
- *ok = true;
-
- if (d) {
- Q_ASSERT(index > -1 && index < d->scopedEnums.count());
- int *rv = d->scopedEnums.at(index)->value(name);
- if (rv)
- return *rv;
- }
-
- *ok = false;
- return -1;
+ return QQmlTypePrivate::scopedEnumValue(d, engine, index, name, ok);
}
int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, int index, const QString &name, bool *ok) const
{
- Q_UNUSED(engine);
- Q_ASSERT(ok);
- *ok = true;
-
- if (d) {
- Q_ASSERT(index > -1 && index < d->scopedEnums.count());
- int *rv = d->scopedEnums.at(index)->value(name);
- if (rv)
- return *rv;
- }
-
- *ok = false;
- return -1;
+ return QQmlTypePrivate::scopedEnumValue(d, engine, index, name, ok);
}
-int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, const QByteArray &scopedEnumName, const QByteArray &name, bool *ok) const
+int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, const QHashedStringRef &scopedEnumName, const QHashedStringRef &name, bool *ok) const
{
- Q_ASSERT(ok);
- if (d) {
- *ok = true;
-
- d->initEnums(engine);
-
- int *rv = d->scopedEnumIndex.value(QHashedCStringRef(scopedEnumName.constData(), scopedEnumName.length()));
- if (rv) {
- int index = *rv;
- Q_ASSERT(index > -1 && index < d->scopedEnums.count());
- rv = d->scopedEnums.at(index)->value(QHashedCStringRef(name.constData(), name.length()));
- if (rv)
- return *rv;
- }
- }
-
- *ok = false;
- return -1;
-}
-
-int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, QStringView scopedEnumName, QStringView name, bool *ok) const
-{
- Q_ASSERT(ok);
- if (d) {
- *ok = true;
-
- d->initEnums(engine);
-
- int *rv = d->scopedEnumIndex.value(QHashedStringRef(scopedEnumName));
- if (rv) {
- int index = *rv;
- Q_ASSERT(index > -1 && index < d->scopedEnums.count());
- rv = d->scopedEnums.at(index)->value(QHashedStringRef(name));
- if (rv)
- return *rv;
- }
- }
-
- *ok = false;
- return -1;
-}
-
-int QQmlType::inlineComponentObjectId() const
-{
- if (!isInlineComponentType())
- return -1;
- return d->extraData.id->objectId;
-}
-
-void QQmlType::setInlineComponentObjectId(int id) const
-{
- Q_ASSERT(d && d->regType == QQmlType::InlineComponentType);
- d->extraData.id->objectId = id;
+ return QQmlTypePrivate::scopedEnumValue(d, engine, scopedEnumName, name, ok);
}
void QQmlType::refHandle(const QQmlTypePrivate *priv)
@@ -935,72 +828,11 @@ int QQmlType::refCount(const QQmlTypePrivate *priv)
return -1;
}
-int QQmlType::lookupInlineComponentIdByName(const QString &name) const
-{
- Q_ASSERT(d);
- return d->namesToInlineComponentObjectIndex.value(name, -1);
-}
-
-QQmlType QQmlType::containingType() const
-{
- Q_ASSERT(d && d->regType == QQmlType::RegistrationType::InlineComponentType);
- auto ret = QQmlType {d->extraData.id->containingType};
- Q_ASSERT(!ret.isInlineComponentType());
- return ret;
-}
-
-QQmlType QQmlType::lookupInlineComponentById(int objectid) const
-{
- Q_ASSERT(d);
- return d->objectIdToICType.value(objectid, QQmlType(nullptr));
-}
-
-int QQmlType::generatePlaceHolderICId() const
-{
- Q_ASSERT(d);
- int id = -2;
- for (auto it = d->objectIdToICType.keyBegin(); it != d->objectIdToICType.keyEnd(); ++it)
- if (*it < id)
- id = *it;
- return id;
-}
-
-void QQmlType::associateInlineComponent(const QString &name, int objectID, const CompositeMetaTypeIds &metaTypeIds, QQmlType existingType)
-{
- bool const reuseExistingType = existingType.isValid();
- auto priv = reuseExistingType ? const_cast<QQmlTypePrivate *>(existingType.d.data()) : new QQmlTypePrivate { RegistrationType::InlineComponentType } ;
- priv->setName( QString::fromUtf8(typeName()), name);
- auto icUrl = QUrl(sourceUrl());
- icUrl.setFragment(QString::number(objectID));
- priv->extraData.id->url = icUrl;
- priv->extraData.id->containingType = d.data();
- priv->extraData.id->objectId = objectID;
- priv->typeId = metaTypeIds.id;
- priv->listId = metaTypeIds.listId;
- d->namesToInlineComponentObjectIndex.insert(name, objectID);
- QQmlType icType(priv);
- d->objectIdToICType.insert(objectID, icType);
- if (!reuseExistingType)
- priv->release();
-}
-
-void QQmlType::setPendingResolutionName(const QString &name)
-{
- Q_ASSERT(d && d->regType == QQmlType::RegistrationType::InlineComponentType);
- Q_ASSERT(d->extraData.id->inlineComponentName == name|| d->extraData.id->inlineComponentName.isEmpty());
- d->extraData.id->inlineComponentName = name;
-}
-
-QString QQmlType::pendingResolutionName() const
-{
- Q_ASSERT(d && d->regType == QQmlType::RegistrationType::InlineComponentType);
- return d->extraData.id->inlineComponentName;
-}
-
void QQmlType::createProxy(QObject *instance) const
{
- if (!d->metaObjects.isEmpty())
- (void)new QQmlProxyMetaObject(instance, &d->metaObjects);
+ const QQmlTypePrivate::ProxyMetaObjects *proxies = d->init();
+ if (!proxies->data.isEmpty())
+ (void)new QQmlProxyMetaObject(instance, &proxies->data);
}
QT_END_NAMESPACE