diff options
Diffstat (limited to 'src/qml/qml/qqmlpropertycachecreator.cpp')
-rw-r--r-- | src/qml/qml/qqmlpropertycachecreator.cpp | 173 |
1 files changed, 79 insertions, 94 deletions
diff --git a/src/qml/qml/qqmlpropertycachecreator.cpp b/src/qml/qml/qqmlpropertycachecreator.cpp index 5b44bd4f9d..06b405c7e4 100644 --- a/src/qml/qml/qqmlpropertycachecreator.cpp +++ b/src/qml/qml/qqmlpropertycachecreator.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications 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) 2016 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 "qqmlpropertycachecreator_p.h" @@ -45,62 +9,61 @@ QT_BEGIN_NAMESPACE QAtomicInt QQmlPropertyCacheCreatorBase::classIndexCounter(0); - -QMetaType QQmlPropertyCacheCreatorBase::metaTypeForPropertyType(QV4::CompiledData::BuiltinType type) -{ - // TODO: we cannot depend on GUI types in declarative, so we'll have to do the id lookup - switch (type) { - case QV4::CompiledData::BuiltinType::Var: return QMetaType::fromType<QVariant>(); - case QV4::CompiledData::BuiltinType::Int: return QMetaType::fromType<int>(); - case QV4::CompiledData::BuiltinType::Bool: return QMetaType::fromType<bool>(); - case QV4::CompiledData::BuiltinType::Real: return QMetaType::fromType<qreal>(); - case QV4::CompiledData::BuiltinType::String: return QMetaType::fromType<QString>(); - case QV4::CompiledData::BuiltinType::Url: return QMetaType::fromType<QUrl>(); - case QV4::CompiledData::BuiltinType::Color: return QMetaType(QMetaType::QColor); - case QV4::CompiledData::BuiltinType::Font: return QMetaType(QMetaType::QFont); - case QV4::CompiledData::BuiltinType::Time: return QMetaType::fromType<QTime>(); - case QV4::CompiledData::BuiltinType::Date: return QMetaType::fromType<QDate>(); - case QV4::CompiledData::BuiltinType::DateTime: return QMetaType::fromType<QDateTime>(); - case QV4::CompiledData::BuiltinType::Rect: return QMetaType::fromType<QRectF>(); - case QV4::CompiledData::BuiltinType::Point: return QMetaType::fromType<QPointF>(); - case QV4::CompiledData::BuiltinType::Size: return QMetaType::fromType<QSizeF>(); - case QV4::CompiledData::BuiltinType::Vector2D: return QMetaType(QMetaType::QVector2D); - case QV4::CompiledData::BuiltinType::Vector3D: return QMetaType(QMetaType::QVector3D); - case QV4::CompiledData::BuiltinType::Vector4D: return QMetaType(QMetaType::QVector4D); - case QV4::CompiledData::BuiltinType::Matrix4x4: return QMetaType(QMetaType::QMatrix4x4); - case QV4::CompiledData::BuiltinType::Quaternion: return QMetaType(QMetaType::QQuaternion); - case QV4::CompiledData::BuiltinType::InvalidBuiltin: break; - }; - return QMetaType {}; -} - -QByteArray QQmlPropertyCacheCreatorBase::createClassNameTypeByUrl(const QUrl &url) +template<typename BaseNameHandler, typename FailHandler> +auto processUrlForClassName( + const QUrl &url, BaseNameHandler &&baseNameHandler, FailHandler &&failHandler) { const QString path = url.path(); - int lastSlash = path.lastIndexOf(QLatin1Char('/')); + // Not a reusable type if we don't have an absolute Url + const qsizetype lastSlash = path.lastIndexOf(QLatin1Char('/')); if (lastSlash <= -1) - return QByteArray(); + return failHandler(); + // ### this might not be correct for .ui.qml files - const QStringView nameBase = QStringView{path}.mid(lastSlash + 1, path.length() - lastSlash - 5); + const QStringView baseName = QStringView{path}.mid(lastSlash + 1, path.size() - lastSlash - 5); + // Not a reusable type if it doesn't start with a upper case letter. - if (nameBase.isEmpty() || !nameBase.at(0).isUpper()) - return QByteArray(); - return nameBase.toUtf8() + "_QMLTYPE_" + - QByteArray::number(classIndexCounter.fetchAndAddRelaxed(1)); + return (!baseName.isEmpty() && baseName.at(0).isUpper()) + ? baseNameHandler(baseName) + : failHandler(); +} + +bool QQmlPropertyCacheCreatorBase::canCreateClassNameTypeByUrl(const QUrl &url) +{ + return processUrlForClassName(url, [](QStringView) { + return true; + }, []() { + return false; + }); +} + +QByteArray QQmlPropertyCacheCreatorBase::createClassNameTypeByUrl(const QUrl &url) +{ + return processUrlForClassName(url, [](QStringView nameBase) { + return nameBase.toUtf8() + QByteArray("_QMLTYPE_"); + }, []() { + return QByteArray("ANON_QML_TYPE_"); + }) + QByteArray::number(classIndexCounter.fetchAndAddRelaxed(1)); } -QByteArray QQmlPropertyCacheCreatorBase::createClassNameForInlineComponent(const QUrl &baseUrl, int icId) +QByteArray QQmlPropertyCacheCreatorBase::createClassNameForInlineComponent( + const QUrl &baseUrl, const QString &name) { - QByteArray baseName = createClassNameTypeByUrl(baseUrl); - if (baseName.isEmpty()) - baseName = QByteArray("ANON_QML_IC_") + QByteArray::number(classIndexCounter.fetchAndAddRelaxed(1)); - baseName += "_" + QByteArray::number(icId); - return baseName; + QByteArray baseName = processUrlForClassName(baseUrl, [](QStringView nameBase) { + return QByteArray(nameBase.toUtf8() + "_QMLTYPE_"); + }, []() { + return QByteArray("ANON_QML_IC_"); + }); + return baseName + name.toUtf8() + '_' + + QByteArray::number(classIndexCounter.fetchAndAddRelaxed(1)); } -QQmlBindingInstantiationContext::QQmlBindingInstantiationContext(int referencingObjectIndex, const QV4::CompiledData::Binding *instantiatingBinding, - const QString &instantiatingPropertyName, QQmlPropertyCache *referencingObjectPropertyCache) +QQmlBindingInstantiationContext::QQmlBindingInstantiationContext( + int referencingObjectIndex, + const QV4::CompiledData::Binding *instantiatingBinding, + const QString &instantiatingPropertyName, + const QQmlPropertyCache::ConstPtr &referencingObjectPropertyCache) : referencingObjectIndex(referencingObjectIndex) , instantiatingBinding(instantiatingBinding) , instantiatingPropertyName(instantiatingPropertyName) @@ -110,11 +73,15 @@ QQmlBindingInstantiationContext::QQmlBindingInstantiationContext(int referencing bool QQmlBindingInstantiationContext::resolveInstantiatingProperty() { - if (!instantiatingBinding || instantiatingBinding->type != QV4::CompiledData::Binding::Type_GroupProperty) + if (!instantiatingBinding + || instantiatingBinding->type() != QV4::CompiledData::Binding::Type_GroupProperty) { return true; + } + + if (!referencingObjectPropertyCache) + return false; Q_ASSERT(referencingObjectIndex >= 0); - Q_ASSERT(referencingObjectPropertyCache); Q_ASSERT(instantiatingBinding->propertyNameIndex != 0); bool notInRevision = false; @@ -124,22 +91,34 @@ bool QQmlBindingInstantiationContext::resolveInstantiatingProperty() return instantiatingProperty != nullptr; } -QQmlRefPointer<QQmlPropertyCache> QQmlBindingInstantiationContext::instantiatingPropertyCache(QQmlEnginePrivate *enginePrivate) const +QQmlPropertyCache::ConstPtr QQmlBindingInstantiationContext::instantiatingPropertyCache() const { if (instantiatingProperty) { if (instantiatingProperty->isQObject()) { // rawPropertyCacheForType assumes a given unspecified version means "any version". // There is another overload that takes no version, which we shall not use here. - return enginePrivate->rawPropertyCacheForType(instantiatingProperty->propType().id(), - instantiatingProperty->typeVersion()); - } else if (const QMetaObject *vtmo = QQmlMetaType::metaObjectForMetaType(instantiatingProperty->propType())) { - return enginePrivate->cache(vtmo, instantiatingProperty->typeVersion()); + auto result = QQmlMetaType::rawPropertyCacheForType(instantiatingProperty->propType(), + instantiatingProperty->typeVersion()); + if (result) + return result; + /* We might end up here if there's a grouped property, and the type hasn't been registered. + Still try to get a property cache, as long as the type of the property is well-behaved + (i.e., not dynamic)*/ + if (auto metaObject = instantiatingProperty->propType().metaObject(); metaObject) { + // we'll warn about dynamic meta-object later in the property validator + if (!(QMetaObjectPrivate::get(metaObject)->flags & DynamicMetaObject)) + return QQmlMetaType::propertyCache(metaObject); + } + // fall through intentional + } else if (const QMetaObject *vtmo = QQmlMetaType::metaObjectForValueType(instantiatingProperty->propType())) { + return QQmlMetaType::propertyCache(vtmo, instantiatingProperty->typeVersion()); } } - return QQmlRefPointer<QQmlPropertyCache>(); + return QQmlPropertyCache::ConstPtr(); } -void QQmlPendingGroupPropertyBindings::resolveMissingPropertyCaches(QQmlEnginePrivate *enginePrivate, QQmlPropertyCacheVector *propertyCaches) const +void QQmlPendingGroupPropertyBindings::resolveMissingPropertyCaches( + QQmlPropertyCacheVector *propertyCaches) const { for (QQmlBindingInstantiationContext pendingBinding: *this) { const int groupPropertyObjectIndex = pendingBinding.instantiatingBinding->value.objectIndex; @@ -147,10 +126,16 @@ void QQmlPendingGroupPropertyBindings::resolveMissingPropertyCaches(QQmlEnginePr if (propertyCaches->at(groupPropertyObjectIndex)) continue; + Q_ASSERT(!pendingBinding.instantiatingPropertyName.isEmpty()); + + if (!pendingBinding.referencingObjectPropertyCache) { + pendingBinding.referencingObjectPropertyCache + = propertyCaches->at(pendingBinding.referencingObjectIndex); + } + if (!pendingBinding.resolveInstantiatingProperty()) continue; - - auto cache = pendingBinding.instantiatingPropertyCache(enginePrivate); + auto cache = pendingBinding.instantiatingPropertyCache(); propertyCaches->set(groupPropertyObjectIndex, cache); } } |