aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmlmetatypedata.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/qml/qqmlmetatypedata.cpp')
-rw-r--r--src/qml/qml/qqmlmetatypedata.cpp219
1 files changed, 124 insertions, 95 deletions
diff --git a/src/qml/qml/qqmlmetatypedata.cpp b/src/qml/qml/qqmlmetatypedata.cpp
index c2150225c3..bc7e762e53 100644
--- a/src/qml/qml/qqmlmetatypedata.cpp
+++ b/src/qml/qml/qqmlmetatypedata.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 "qqmlmetatypedata_p.h"
@@ -51,21 +15,24 @@ QQmlMetaTypeData::QQmlMetaTypeData()
QQmlMetaTypeData::~QQmlMetaTypeData()
{
- for (TypeModules::const_iterator i = uriToModule.constBegin(), cend = uriToModule.constEnd(); i != cend; ++i)
- delete *i;
- for (QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator it = propertyCaches.begin(), end = propertyCaches.end();
- it != end; ++it)
- (*it)->release();
+ {
+ // Unregister all remaining composite types.
+ // Avoid deletion recursion (via QQmlTypePrivate dtor) by moving them out of the way first.
+ CompositeTypes emptyComposites;
+ emptyComposites.swap(compositeTypes);
+ }
+ propertyCaches.clear();
// Do this before the attached properties disappear.
types.clear();
undeletableTypes.clear();
+ qDeleteAll(metaTypeToValueType);
}
// This expects a "fresh" QQmlTypePrivate and adopts its reference.
void QQmlMetaTypeData::registerType(QQmlTypePrivate *priv)
{
- for (int i = 0; i < types.count(); ++i) {
+ for (int i = 0; i < types.size(); ++i) {
if (!types.at(i).isValid()) {
types[i] = QQmlType(priv);
priv->index = i;
@@ -74,71 +41,119 @@ void QQmlMetaTypeData::registerType(QQmlTypePrivate *priv)
}
}
types.append(QQmlType(priv));
- priv->index = types.count() - 1;
+ priv->index = types.size() - 1;
priv->release();
}
-void QQmlMetaTypeData::registerModuleTypes(const QQmlMetaTypeData::VersionedUri &versionedUri)
+QQmlMetaTypeData::VersionedUri::VersionedUri(const std::unique_ptr<QQmlTypeModule> &module)
+ : uri(module->module()), majorVersion(module->majorVersion())
{
- auto function = moduleTypeRegistrationFunctions.constFind(versionedUri);
- if (function != moduleTypeRegistrationFunctions.constEnd())
- (*function)();
}
-QQmlPropertyCache *QQmlMetaTypeData::propertyCacheForMinorVersion(int index, int minorVersion) const
+QQmlTypeModule *QQmlMetaTypeData::findTypeModule(const QString &module, QTypeRevision version)
{
- return (index < typePropertyCaches.length())
- ? typePropertyCaches.at(index).value(minorVersion).data()
+ const auto qqtm = std::lower_bound(
+ uriToModule.begin(), uriToModule.end(), VersionedUri(module, version),
+ std::less<QQmlMetaTypeData::VersionedUri>());
+ if (qqtm == uriToModule.end())
+ return nullptr;
+
+ QQmlTypeModule *candidate = qqtm->get();
+ return (candidate->module() == module && candidate->majorVersion() == version.majorVersion())
+ ? candidate
: nullptr;
}
-void QQmlMetaTypeData::setPropertyCacheForMinorVersion(int index, int minorVersion,
- QQmlPropertyCache *cache)
+QQmlTypeModule *QQmlMetaTypeData::addTypeModule(std::unique_ptr<QQmlTypeModule> module)
+{
+ QQmlTypeModule *ret = module.get();
+ uriToModule.emplace_back(std::move(module));
+ std::sort(uriToModule.begin(), uriToModule.end(),
+ [](const std::unique_ptr<QQmlTypeModule> &a,
+ const std::unique_ptr<QQmlTypeModule> &b) {
+ const int diff = a->module().compare(b->module());
+ return diff < 0 || (diff == 0 && a->majorVersion() < b->majorVersion());
+ });
+ return ret;
+}
+
+bool QQmlMetaTypeData::registerModuleTypes(const QString &uri)
+{
+ auto function = moduleTypeRegistrationFunctions.constFind(uri);
+ if (function != moduleTypeRegistrationFunctions.constEnd()) {
+ (*function)();
+ return true;
+ }
+ return false;
+}
+
+QQmlPropertyCache::ConstPtr QQmlMetaTypeData::propertyCacheForVersion(
+ int index, QTypeRevision version) const
+{
+ return (index < typePropertyCaches.size())
+ ? typePropertyCaches.at(index).value(version)
+ : QQmlPropertyCache::ConstPtr();
+}
+
+void QQmlMetaTypeData::setPropertyCacheForVersion(int index, QTypeRevision version,
+ const QQmlPropertyCache::ConstPtr &cache)
{
- if (index >= typePropertyCaches.length())
+ if (index >= typePropertyCaches.size())
typePropertyCaches.resize(index + 1);
- typePropertyCaches[index][minorVersion] = cache;
+ typePropertyCaches[index][version] = cache;
}
-void QQmlMetaTypeData::clearPropertyCachesForMinorVersion(int index)
+void QQmlMetaTypeData::clearPropertyCachesForVersion(int index)
{
- if (index < typePropertyCaches.length())
+ if (index < typePropertyCaches.size())
typePropertyCaches[index].clear();
}
-QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QMetaObject *metaObject, int minorVersion)
+QQmlPropertyCache::ConstPtr QQmlMetaTypeData::propertyCache(
+ const QMetaObject *metaObject, QTypeRevision version)
{
- if (QQmlPropertyCache *rv = propertyCaches.value(metaObject))
+ if (QQmlPropertyCache::ConstPtr rv = propertyCaches.value(metaObject))
return rv;
- if (!metaObject->superClass()) {
- QQmlPropertyCache *rv = new QQmlPropertyCache(metaObject);
+ QQmlPropertyCache::ConstPtr rv;
+ if (const QMetaObject *superMeta = metaObject->superClass())
+ rv = propertyCache(superMeta, version)->copyAndAppend(metaObject, version);
+ else
+ rv = QQmlPropertyCache::createStandalone(metaObject);
+
+ const auto *mop = reinterpret_cast<const QMetaObjectPrivate *>(metaObject->d.data);
+ if (!(mop->flags & DynamicMetaObject))
propertyCaches.insert(metaObject, rv);
- return rv;
- }
- QQmlPropertyCache *super = propertyCache(metaObject->superClass(), minorVersion);
- QQmlPropertyCache *rv = super->copyAndAppend(metaObject, minorVersion);
- propertyCaches.insert(metaObject, rv);
+
return rv;
}
-QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, int minorVersion)
+QQmlPropertyCache::ConstPtr QQmlMetaTypeData::propertyCache(
+ const QQmlType &type, QTypeRevision version)
{
Q_ASSERT(type.isValid());
- if (QQmlPropertyCache *pc = propertyCacheForMinorVersion(type.index(), minorVersion))
+ if (auto pc = propertyCacheForVersion(type.index(), version))
return pc;
QVector<QQmlType> types;
- int maxMinorVersion = 0;
+ quint8 maxMinorVersion = 0;
const QMetaObject *metaObject = type.metaObject();
+ Q_ASSERT(metaObject);
+
+ const QTypeRevision combinedVersion = version.hasMajorVersion()
+ ? version
+ : (version.hasMinorVersion()
+ ? QTypeRevision::fromVersion(type.version().majorVersion(),
+ version.minorVersion())
+ : QTypeRevision::fromMajorVersion(type.version().majorVersion()));
while (metaObject) {
- QQmlType t = QQmlMetaType::qmlType(metaObject, type.module(), type.majorVersion(), minorVersion);
+ QQmlType t = QQmlMetaType::qmlType(metaObject, type.module(), combinedVersion);
if (t.isValid()) {
- maxMinorVersion = qMax(maxMinorVersion, t.minorVersion());
+ maxMinorVersion = qMax(maxMinorVersion, t.version().minorVersion());
types << t;
} else {
types << QQmlType();
@@ -147,32 +162,30 @@ QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, int min
metaObject = metaObject->superClass();
}
- if (QQmlPropertyCache *pc = propertyCacheForMinorVersion(type.index(), maxMinorVersion)) {
- setPropertyCacheForMinorVersion(type.index(), minorVersion, pc);
+ const QTypeRevision maxVersion = QTypeRevision::fromVersion(combinedVersion.majorVersion(),
+ maxMinorVersion);
+ if (auto pc = propertyCacheForVersion(type.index(), maxVersion)) {
+ setPropertyCacheForVersion(type.index(), maxVersion, pc);
return pc;
}
- QQmlPropertyCache *raw = propertyCache(type.metaObject(), minorVersion);
-
- bool hasCopied = false;
+ QQmlPropertyCache::ConstPtr raw = propertyCache(type.metaObject(), combinedVersion);
+ QQmlPropertyCache::Ptr copied;
- for (int ii = 0; ii < types.count(); ++ii) {
+ for (int ii = 0; ii < types.size(); ++ii) {
const QQmlType &currentType = types.at(ii);
if (!currentType.isValid())
continue;
- int rev = currentType.metaObjectRevision();
- int moIndex = types.count() - 1 - ii;
+ QTypeRevision rev = currentType.metaObjectRevision();
+ int moIndex = types.size() - 1 - ii;
if (raw->allowedRevision(moIndex) != rev) {
- if (!hasCopied) {
- // TODO: The copy should be mutable, and the original should be const
- // Considering this, the setAllowedRevision() below does not violate
- // the immutability of already published property caches.
- raw = raw->copy();
- hasCopied = true;
+ if (copied.isNull()) {
+ copied = raw->copy();
+ raw = copied;
}
- raw->setAllowedRevision(moIndex, rev);
+ copied->setAllowedRevision(moIndex, rev);
}
}
@@ -198,12 +211,12 @@ QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, int min
!overloadError && iter != raw->stringCache.end();
++iter) {
- QQmlPropertyData *d = *iter;
+ const QQmlPropertyData *d = *iter;
if (raw->isAllowedInRevision(d))
continue; // Not excluded - no problems
// check that a regular "name" overload isn't happening
- QQmlPropertyData *current = d;
+ const QQmlPropertyData *current = d;
while (!overloadError && current) {
current = d->overrideData(current);
if (current && raw->isAllowedInRevision(current))
@@ -219,15 +232,31 @@ QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, int min
}
#endif
- setPropertyCacheForMinorVersion(type.index(), minorVersion, raw);
-
- if (hasCopied)
- raw->release();
+ setPropertyCacheForVersion(type.index(), version, raw);
- if (minorVersion != maxMinorVersion)
- setPropertyCacheForMinorVersion(type.index(), maxMinorVersion, raw);
+ if (version != maxVersion)
+ setPropertyCacheForVersion(type.index(), maxVersion, raw);
return raw;
}
+static QQmlPropertyCache::ConstPtr propertyCacheForPotentialInlineComponentType(
+ QMetaType t, const QQmlMetaTypeData::CompositeTypes::const_iterator &iter) {
+ if (t != (*iter)->metaType()) {
+ // this is an inline component, and what we have in the iterator is currently the parent compilation unit
+ for (auto &&icDatum: (*iter)->inlineComponentData)
+ if (icDatum.qmlType.typeId() == t)
+ return (*iter)->propertyCaches.at(icDatum.objectIndex);
+ }
+ return (*iter)->rootPropertyCache();
+}
+
+QQmlPropertyCache::ConstPtr QQmlMetaTypeData::findPropertyCacheInCompositeTypes(QMetaType t) const
+{
+ auto iter = compositeTypes.constFind(t.iface());
+ return (iter == compositeTypes.constEnd())
+ ? QQmlPropertyCache::ConstPtr()
+ : propertyCacheForPotentialInlineComponentType(t, iter);
+}
+
QT_END_NAMESPACE