diff options
Diffstat (limited to 'src/qml/qml/qqmlmetatypedata.cpp')
-rw-r--r-- | src/qml/qml/qqmlmetatypedata.cpp | 145 |
1 files changed, 66 insertions, 79 deletions
diff --git a/src/qml/qml/qqmlmetatypedata.cpp b/src/qml/qml/qqmlmetatypedata.cpp index 4be26acdc6..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,9 +15,14 @@ QQmlMetaTypeData::QQmlMetaTypeData() QQmlMetaTypeData::~QQmlMetaTypeData() { - for (auto 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(); @@ -63,7 +32,7 @@ QQmlMetaTypeData::~QQmlMetaTypeData() // 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; @@ -72,7 +41,7 @@ void QQmlMetaTypeData::registerType(QQmlTypePrivate *priv) } } types.append(QQmlType(priv)); - priv->index = types.count() - 1; + priv->index = types.size() - 1; priv->release(); } @@ -118,48 +87,53 @@ bool QQmlMetaTypeData::registerModuleTypes(const QString &uri) return false; } -QQmlPropertyCache *QQmlMetaTypeData::propertyCacheForVersion(int index, QTypeRevision version) const +QQmlPropertyCache::ConstPtr QQmlMetaTypeData::propertyCacheForVersion( + int index, QTypeRevision version) const { - return (index < typePropertyCaches.length()) - ? typePropertyCaches.at(index).value(version).data() - : nullptr; + return (index < typePropertyCaches.size()) + ? typePropertyCaches.at(index).value(version) + : QQmlPropertyCache::ConstPtr(); } void QQmlMetaTypeData::setPropertyCacheForVersion(int index, QTypeRevision version, - QQmlPropertyCache *cache) + const QQmlPropertyCache::ConstPtr &cache) { - if (index >= typePropertyCaches.length()) + if (index >= typePropertyCaches.size()) typePropertyCaches.resize(index + 1); typePropertyCaches[index][version] = cache; } void QQmlMetaTypeData::clearPropertyCachesForVersion(int index) { - if (index < typePropertyCaches.length()) + if (index < typePropertyCaches.size()) typePropertyCaches[index].clear(); } -QQmlRefPointer<QQmlPropertyCache> QQmlMetaTypeData::propertyCache(const QMetaObject *metaObject, QTypeRevision version) +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; - } - auto super = propertyCache(metaObject->superClass(), version); - QQmlPropertyCache *rv = super->copyAndAppend(metaObject, version); - propertyCaches.insert(metaObject, rv); + return rv; } -QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, QTypeRevision version) +QQmlPropertyCache::ConstPtr QQmlMetaTypeData::propertyCache( + const QQmlType &type, QTypeRevision version) { Q_ASSERT(type.isValid()); - if (QQmlPropertyCache *pc = propertyCacheForVersion(type.index(), version)) + if (auto pc = propertyCacheForVersion(type.index(), version)) return pc; QVector<QQmlType> types; @@ -167,13 +141,14 @@ QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, QTypeRe 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()) - : type.version()); + : QTypeRevision::fromMajorVersion(type.version().majorVersion())); while (metaObject) { QQmlType t = QQmlMetaType::qmlType(metaObject, type.module(), combinedVersion); @@ -189,32 +164,28 @@ QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, QTypeRe const QTypeRevision maxVersion = QTypeRevision::fromVersion(combinedVersion.majorVersion(), maxMinorVersion); - if (QQmlPropertyCache *pc = propertyCacheForVersion(type.index(), maxVersion)) { + if (auto pc = propertyCacheForVersion(type.index(), maxVersion)) { setPropertyCacheForVersion(type.index(), maxVersion, pc); return pc; } - QQmlPropertyCache *raw = propertyCache(type.metaObject(), combinedVersion).data(); - - 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 ¤tType = types.at(ii); if (!currentType.isValid()) continue; QTypeRevision rev = currentType.metaObjectRevision(); - int moIndex = types.count() - 1 - ii; + 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); } } @@ -240,12 +211,12 @@ QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, QTypeRe !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)) @@ -263,13 +234,29 @@ QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, QTypeRe setPropertyCacheForVersion(type.index(), version, raw); - if (hasCopied) - raw->release(); - 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 |