diff options
Diffstat (limited to 'src/qml/qml/qqmlopenmetaobject.cpp')
-rw-r--r-- | src/qml/qml/qqmlopenmetaobject.cpp | 130 |
1 files changed, 50 insertions, 80 deletions
diff --git a/src/qml/qml/qqmlopenmetaobject.cpp b/src/qml/qml/qqmlopenmetaobject.cpp index ec2d57013f..2d0a78c6cb 100644 --- a/src/qml/qml/qqmlopenmetaobject.cpp +++ b/src/qml/qml/qqmlopenmetaobject.cpp @@ -1,47 +1,15 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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) 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 "qqmlopenmetaobject_p.h" #include <private/qqmlpropertycache_p.h> #include <private/qqmldata_p.h> +#include <private/qqmlmetatype_p.h> + #include <private/qmetaobjectbuilder_p.h> #include <qdebug.h> +#include <QtCore/qpointer.h> +#include <QtCore/qset.h> QT_BEGIN_NAMESPACE @@ -49,7 +17,7 @@ QT_BEGIN_NAMESPACE class QQmlOpenMetaObjectTypePrivate { public: - QQmlOpenMetaObjectTypePrivate() : mem(nullptr), cache(nullptr) {} + QQmlOpenMetaObjectTypePrivate() : mem(nullptr) {} void init(const QMetaObject *metaObj); @@ -58,7 +26,13 @@ public: QHash<QByteArray, int> names; QMetaObjectBuilder mob; QMetaObject *mem; - QQmlPropertyCache *cache; + + // TODO: We need to make sure that this does not escape into other threads. + // In particular, all its non-const uses are probably wrong. You should + // only set the open metaobject to "cached" once it's not going to be + // modified anymore. + QQmlPropertyCache::Ptr cache; + QSet<QQmlOpenMetaObject*> referers; }; @@ -72,8 +46,6 @@ QQmlOpenMetaObjectType::~QQmlOpenMetaObjectType() { if (d->mem) free(d->mem); - if (d->cache) - d->cache->release(); delete d; } @@ -89,24 +61,19 @@ int QQmlOpenMetaObjectType::signalOffset() const int QQmlOpenMetaObjectType::propertyCount() const { - return d->names.count(); + return d->names.size(); } QByteArray QQmlOpenMetaObjectType::propertyName(int idx) const { - Q_ASSERT(idx >= 0 && idx < d->names.count()); + Q_ASSERT(idx >= 0 && idx < d->names.size()); return d->mob.property(idx).name(); } -QMetaObject *QQmlOpenMetaObjectType::metaObject() const -{ - return d->mem; -} - void QQmlOpenMetaObjectType::createProperties(const QVector<QByteArray> &names) { - for (int i = 0; i < names.count(); ++i) { + for (int i = 0; i < names.size(); ++i) { const QByteArray &name = names.at(i); const int id = d->mob.propertyCount(); d->mob.addSignal("__" + QByteArray::number(id) + "()"); @@ -128,13 +95,13 @@ void QQmlOpenMetaObjectType::createProperties(const QVector<QByteArray> &names) int QQmlOpenMetaObjectType::createProperty(const QByteArray &name) { - int id = d->mob.propertyCount(); - d->mob.addSignal("__" + QByteArray::number(id) + "()"); - QMetaPropertyBuilder build = d->mob.addProperty(name, "QVariant", id); - propertyCreated(id, build); + const int signalIdx = d->mob.addSignal( + "__" + QByteArray::number(d->mob.propertyCount()) + "()").index(); + QMetaPropertyBuilder build = d->mob.addProperty(name, "QVariant", signalIdx); + propertyCreated(build.index(), build); free(d->mem); d->mem = d->mob.toMetaObject(); - d->names.insert(name, id); + d->names.insert(name, build.index()); QSet<QQmlOpenMetaObject*>::iterator it = d->referers.begin(); while (it != d->referers.end()) { QQmlOpenMetaObject *omo = *it; @@ -144,12 +111,12 @@ int QQmlOpenMetaObjectType::createProperty(const QByteArray &name) ++it; } - return d->propertyOffset + id; + return d->propertyOffset + build.index(); } void QQmlOpenMetaObjectType::propertyCreated(int id, QMetaPropertyBuilder &builder) { - if (d->referers.count()) + if (d->referers.size()) (*d->referers.begin())->propertyCreated(id, builder); } @@ -198,13 +165,13 @@ public: }; inline void setPropertyValue(int idx, const QVariant &value) { - if (data.count() <= idx) + if (data.size() <= idx) data.resize(idx + 1); data[idx].setValue(value); } inline Property &propertyRef(int idx) { - if (data.count() <= idx) + if (data.size() <= idx) data.resize(idx + 1); Property &prop = data[idx]; if (!prop.valueSet) @@ -223,22 +190,18 @@ public: } inline bool hasProperty(int idx) const { - if (idx >= data.count()) + if (idx >= data.size()) return false; return data[idx].valueSet; } void dropPropertyCache() { - if (QQmlData *ddata = QQmlData::get(object, /*create*/false)) { - if (ddata->propertyCache) { - ddata->propertyCache->release(); - ddata->propertyCache = nullptr; - } - } + if (QQmlData *ddata = QQmlData::get(object, /*create*/false)) + ddata->propertyCache.reset(); } QQmlOpenMetaObject *q; - QAbstractDynamicMetaObject *parent = nullptr; + QDynamicMetaObjectData *parent = nullptr; QVector<Property> data; QObject *object; QQmlRefPointer<QQmlOpenMetaObjectType> type; @@ -254,19 +217,20 @@ QQmlOpenMetaObject::QQmlOpenMetaObject(QObject *obj, const QMetaObject *base) d->type->d->referers.insert(this); QObjectPrivate *op = QObjectPrivate::get(obj); - d->parent = static_cast<QAbstractDynamicMetaObject *>(op->metaObject); + d->parent = op->metaObject; *static_cast<QMetaObject *>(this) = *d->type->d->mem; op->metaObject = this; } -QQmlOpenMetaObject::QQmlOpenMetaObject(QObject *obj, QQmlOpenMetaObjectType *type) +QQmlOpenMetaObject::QQmlOpenMetaObject( + QObject *obj, const QQmlRefPointer<QQmlOpenMetaObjectType> &type) : d(new QQmlOpenMetaObjectPrivate(this, obj)) { d->type = type; d->type->d->referers.insert(this); QObjectPrivate *op = QObjectPrivate::get(obj); - d->parent = static_cast<QAbstractDynamicMetaObject *>(op->metaObject); + d->parent = op->metaObject; *static_cast<QMetaObject *>(this) = *d->type->d->mem; op->metaObject = this; } @@ -292,6 +256,11 @@ void QQmlOpenMetaObject::emitPropertyNotification(const QByteArray &propertyName activate(d->object, *iter + d->type->d->signalOffset, nullptr); } +void QQmlOpenMetaObject::unparent() +{ + d->parent = nullptr; +} + int QQmlOpenMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void **a) { Q_ASSERT(d->object == o); @@ -303,7 +272,7 @@ int QQmlOpenMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void * propertyRead(propId); *reinterpret_cast<QVariant *>(a[0]) = d->propertyValue(propId); } else if (c == QMetaObject::WriteProperty) { - if (propId >= d->data.count() || d->data.at(propId).value() != *reinterpret_cast<QVariant *>(a[0])) { + if (propId >= d->data.size() || d->data.at(propId).value() != *reinterpret_cast<QVariant *>(a[0])) { propertyWrite(propId); d->setPropertyValue(propId, propertyWriteValue(propId, *reinterpret_cast<QVariant *>(a[0]))); propertyWritten(propId); @@ -319,7 +288,7 @@ int QQmlOpenMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void * } } -QAbstractDynamicMetaObject *QQmlOpenMetaObject::parent() const +QDynamicMetaObjectData *QQmlOpenMetaObject::parent() const { return d->parent; } @@ -408,7 +377,7 @@ void QQmlOpenMetaObject::setValues(const QHash<QByteArray, QVariant> &values, bo d->type->createProperties(missingProperties); d->dropPropertyCache(); - for (const QByteArray &name : qAsConst(missingProperties)) + for (const QByteArray &name : std::as_const(missingProperties)) checkedSetValue(names[name], values[name], force); } @@ -427,14 +396,15 @@ void QQmlOpenMetaObject::setCached(bool c) QQmlData *qmldata = QQmlData::get(d->object, true); if (d->cacheProperties) { + // As the propertyCache is not saved in QQmlMetaType (due to it being dynamic) + // we cannot leak it to other places before we're done with it. Yes, it's still + // terrible. if (!d->type->d->cache) - d->type->d->cache = new QQmlPropertyCache(this); + d->type->d->cache = QQmlPropertyCache::createStandalone(this); qmldata->propertyCache = d->type->d->cache; - d->type->d->cache->addref(); } else { - if (d->type->d->cache) - d->type->d->cache->release(); - qmldata->propertyCache = nullptr; + d->type->d->cache.reset(); + qmldata->propertyCache.reset(); } } @@ -493,12 +463,12 @@ QVariant QQmlOpenMetaObject::initialValue(int) int QQmlOpenMetaObject::count() const { - return d->type->d->names.count(); + return d->type->d->names.size(); } QByteArray QQmlOpenMetaObject::name(int idx) const { - Q_ASSERT(idx >= 0 && idx < d->type->d->names.count()); + Q_ASSERT(idx >= 0 && idx < d->type->d->names.size()); return d->type->d->mob.property(idx).name(); } |