diff options
Diffstat (limited to 'src/qml/qml/qqmlvaluetype.cpp')
-rw-r--r-- | src/qml/qml/qqmlvaluetype.cpp | 326 |
1 files changed, 82 insertions, 244 deletions
diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp index d83fc4bb48..4088d6e6c4 100644 --- a/src/qml/qml/qqmlvaluetype.cpp +++ b/src/qml/qml/qqmlvaluetype.cpp @@ -1,295 +1,117 @@ -/**************************************************************************** -** -** 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 "qqmlvaluetype_p.h" #include <QtCore/qmutex.h> #include <private/qqmlglobal_p.h> #include <QtCore/qdebug.h> +#include <private/qqmlengine_p.h> #include <private/qmetaobjectbuilder_p.h> -#if QT_CONFIG(qml_itemmodel) -#include <private/qqmlmodelindexvaluetype_p.h> -#endif -#include <private/qmetatype_p.h> QT_BEGIN_NAMESPACE -namespace { - -struct QQmlValueTypeFactoryImpl -{ - QQmlValueTypeFactoryImpl(); - ~QQmlValueTypeFactoryImpl(); - - bool isValueType(int idx); - - const QMetaObject *metaObjectForMetaType(int); - QQmlValueType *valueType(int); - - QQmlValueType *valueTypes[QVariant::UserType]; - QHash<int, QQmlValueType *> userTypes; - QMutex mutex; - - QQmlValueType invalidValueType; -}; - -QQmlValueTypeFactoryImpl::QQmlValueTypeFactoryImpl() -{ - std::fill_n(valueTypes, int(QVariant::UserType), &invalidValueType); - -#if QT_CONFIG(qml_itemmodel) - // See types wrapped in qqmlmodelindexvaluetype_p.h - qRegisterMetaType<QItemSelectionRange>(); -#endif -} - -QQmlValueTypeFactoryImpl::~QQmlValueTypeFactoryImpl() -{ - for (QQmlValueType *type : valueTypes) { - if (type != &invalidValueType) - delete type; - } - qDeleteAll(userTypes); -} - -bool isInternalType(int idx) -{ - // Qt internal types - switch (idx) { - case QMetaType::UnknownType: - case QMetaType::QStringList: - case QMetaType::QObjectStar: - case QMetaType::VoidStar: - case QMetaType::Nullptr: - case QMetaType::QVariant: - case QMetaType::QLocale: - case QMetaType::QImage: // scarce type, keep as QVariant - case QMetaType::QPixmap: // scarce type, keep as QVariant - return true; - default: - return false; - } -} - -bool QQmlValueTypeFactoryImpl::isValueType(int idx) +QQmlValueType::~QQmlValueType() { - if (idx < 0 || isInternalType(idx)) - return false; - - return valueType(idx) != nullptr; + ::free(m_dynamicMetaObject); } -const QMetaObject *QQmlValueTypeFactoryImpl::metaObjectForMetaType(int t) +QQmlGadgetPtrWrapper *QQmlGadgetPtrWrapper::instance(QQmlEngine *engine, QMetaType type) { - switch (t) { - case QVariant::Point: - return &QQmlPointValueType::staticMetaObject; - case QVariant::PointF: - return &QQmlPointFValueType::staticMetaObject; - case QVariant::Size: - return &QQmlSizeValueType::staticMetaObject; - case QVariant::SizeF: - return &QQmlSizeFValueType::staticMetaObject; - case QVariant::Rect: - return &QQmlRectValueType::staticMetaObject; - case QVariant::RectF: - return &QQmlRectFValueType::staticMetaObject; -#if QT_CONFIG(easingcurve) - case QVariant::EasingCurve: - return &QQmlEasingValueType::staticMetaObject; -#endif -#if QT_CONFIG(qml_itemmodel) - case QVariant::ModelIndex: - return &QQmlModelIndexValueType::staticMetaObject; - case QVariant::PersistentModelIndex: - return &QQmlPersistentModelIndexValueType::staticMetaObject; -#endif - default: -#if QT_CONFIG(qml_itemmodel) - if (t == qMetaTypeId<QItemSelectionRange>()) - return &QQmlItemSelectionRangeValueType::staticMetaObject; -#endif - - if (const QMetaObject *mo = QQml_valueTypeProvider()->metaObjectForMetaType(t)) - return mo; - break; - } - - QMetaType metaType(t); - if (metaType.flags() & QMetaType::IsGadget) - return metaType.metaObject(); - return nullptr; + return engine ? QQmlEnginePrivate::get(engine)->valueTypeInstance(type) : nullptr; } -QQmlValueType *QQmlValueTypeFactoryImpl::valueType(int idx) +QQmlGadgetPtrWrapper::QQmlGadgetPtrWrapper(QQmlValueType *valueType, QObject *parent) + : QObject(parent), m_gadgetPtr(valueType->create()) { - if (idx >= (int)QVariant::UserType) { - // Protect the hash with a mutex - mutex.lock(); - - QHash<int, QQmlValueType *>::iterator it = userTypes.find(idx); - if (it == userTypes.end()) { - QQmlValueType *vt = nullptr; - if (const QMetaObject *mo = metaObjectForMetaType(idx)) - vt = new QQmlValueType(idx, mo); - it = userTypes.insert(idx, vt); - } - - mutex.unlock(); - return *it; - } - - QQmlValueType *rv = valueTypes[idx]; - if (rv == &invalidValueType) { - // No need for mutex protection - the most we can lose is a valueType instance - - // TODO: Investigate the performance/memory characteristics of - // removing the preallocated array - if (isInternalType(idx)) - rv = valueTypes[idx] = nullptr; - else if (const QMetaObject *mo = metaObjectForMetaType(idx)) - rv = valueTypes[idx] = new QQmlValueType(idx, mo); - else - rv = valueTypes[idx] = nullptr; - } - - return rv; + QObjectPrivate *d = QObjectPrivate::get(this); + Q_ASSERT(!d->metaObject); + d->metaObject = valueType; } -} - -Q_GLOBAL_STATIC(QQmlValueTypeFactoryImpl, factoryImpl); - -bool QQmlValueTypeFactory::isValueType(int idx) +QQmlGadgetPtrWrapper::~QQmlGadgetPtrWrapper() { - return factoryImpl()->isValueType(idx); + QObjectPrivate *d = QObjectPrivate::get(this); + static_cast<const QQmlValueType *>(d->metaObject)->destroy(m_gadgetPtr); + d->metaObject = nullptr; } -QQmlValueType *QQmlValueTypeFactory::valueType(int idx) +void QQmlGadgetPtrWrapper::read(QObject *obj, int idx) { - return factoryImpl()->valueType(idx); + Q_ASSERT(m_gadgetPtr); + void *a[] = { m_gadgetPtr, nullptr }; + QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); } -const QMetaObject *QQmlValueTypeFactory::metaObjectForMetaType(int type) +void QQmlGadgetPtrWrapper::write( + QObject *obj, int idx, QQmlPropertyData::WriteFlags flags, int internalIndex) const { - return factoryImpl()->metaObjectForMetaType(type); + Q_ASSERT(m_gadgetPtr); + int status = -1; + void *a[] = { m_gadgetPtr, nullptr, &status, &flags, &internalIndex }; + QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a); } -void QQmlValueTypeFactory::registerValueTypes(const char *uri, int versionMajor, int versionMinor) +QVariant QQmlGadgetPtrWrapper::value() const { -#if QT_CONFIG(easingcurve) - qmlRegisterValueTypeEnums<QQmlEasingValueType>(uri, versionMajor, versionMinor, "Easing"); -#endif -} + Q_ASSERT(m_gadgetPtr); -QQmlValueType::QQmlValueType() : - _metaObject(nullptr), - gadgetPtr(nullptr), - metaType(QMetaType::UnknownType) -{ + const QMetaType m = metaType(); + return m == QMetaType::fromType<QVariant>() + ? *static_cast<const QVariant *>(m_gadgetPtr) + : QVariant(m, m_gadgetPtr); } -QQmlValueType::QQmlValueType(int typeId, const QMetaObject *gadgetMetaObject) - : gadgetPtr(QMetaType::create(typeId)) - , metaType(typeId) +void QQmlGadgetPtrWrapper::setValue(const QVariant &value) { - QObjectPrivate *op = QObjectPrivate::get(this); - Q_ASSERT(!op->metaObject); - op->metaObject = this; + Q_ASSERT(m_gadgetPtr); - QMetaObjectBuilder builder(gadgetMetaObject); - _metaObject = builder.toMetaObject(); - - *static_cast<QMetaObject*>(this) = *_metaObject; -} - -QQmlValueType::~QQmlValueType() -{ - QObjectPrivate *op = QObjectPrivate::get(this); - Q_ASSERT(op->metaObject == nullptr || op->metaObject == this); - op->metaObject = nullptr; - ::free(const_cast<QMetaObject *>(_metaObject)); - metaType.destroy(gadgetPtr); + const QMetaType m = metaType(); + m.destruct(m_gadgetPtr); + if (m == QMetaType::fromType<QVariant>()) { + m.construct(m_gadgetPtr, &value); + } else { + Q_ASSERT(m == value.metaType()); + m.construct(m_gadgetPtr, value.constData()); + } } -void QQmlValueType::read(QObject *obj, int idx) +int QQmlGadgetPtrWrapper::metaCall(QMetaObject::Call type, int id, void **argv) { - void *a[] = { gadgetPtr, nullptr }; - QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); + Q_ASSERT(m_gadgetPtr); + const QMetaObject *metaObject = valueType()->staticMetaObject(); + QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(type, &metaObject, &id); + metaObject->d.static_metacall(static_cast<QObject *>(m_gadgetPtr), type, id, argv); + return id; } -void QQmlValueType::write(QObject *obj, int idx, QQmlPropertyData::WriteFlags flags) +const QQmlValueType *QQmlGadgetPtrWrapper::valueType() const { - Q_ASSERT(gadgetPtr); - int status = -1; - void *a[] = { gadgetPtr, nullptr, &status, &flags }; - QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a); + const QObjectPrivate *d = QObjectPrivate::get(this); + return static_cast<const QQmlValueType *>(d->metaObject); } -QVariant QQmlValueType::value() +QMetaObject *QQmlValueType::toDynamicMetaObject(QObject *) { - Q_ASSERT(gadgetPtr); - return QVariant(metaType.id(), gadgetPtr); -} + if (!m_dynamicMetaObject) { + QMetaObjectBuilder builder(m_staticMetaObject); -void QQmlValueType::setValue(const QVariant &value) -{ - Q_ASSERT(metaType.id() == value.userType()); - metaType.destruct(gadgetPtr); - metaType.construct(gadgetPtr, value.constData()); -} + // Do not set PropertyAccessInStaticMetaCall here. QQmlGadgetPtrWrapper likes to + // to intercept the metacalls since it needs to use its gadgetPtr. + // For QQmlValueType::metaObject() we use the base type that has the flag. -QAbstractDynamicMetaObject *QQmlValueType::toDynamicMetaObject(QObject *) -{ - return this; + m_dynamicMetaObject = builder.toMetaObject(); + } + return m_dynamicMetaObject; } void QQmlValueType::objectDestroyed(QObject *) { } -int QQmlValueType::metaCall(QObject *, QMetaObject::Call type, int _id, void **argv) +int QQmlValueType::metaCall(QObject *object, QMetaObject::Call type, int _id, void **argv) { - const QMetaObject *mo = _metaObject; - QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(type, &mo, &_id); - mo->d.static_metacall(reinterpret_cast<QObject*>(gadgetPtr), type, _id, argv); - return _id; + return static_cast<QQmlGadgetPtrWrapper *>(object)->metaCall(type, _id, argv); } QString QQmlPointFValueType::toString() const @@ -318,6 +140,11 @@ void QQmlPointFValueType::setY(qreal y) } +QString QQmlPointValueType::toString() const +{ + return QString::asprintf("QPoint(%d, %d)", v.x(), v.y()); +} + int QQmlPointValueType::x() const { return v.x(); @@ -365,6 +192,11 @@ void QQmlSizeFValueType::setHeight(qreal h) } +QString QQmlSizeValueType::toString() const +{ + return QString::asprintf("QSize(%d, %d)", v.width(), v.height()); +} + int QQmlSizeValueType::width() const { return v.width(); @@ -450,6 +282,12 @@ qreal QQmlRectFValueType::bottom() const return v.bottom(); } + +QString QQmlRectValueType::toString() const +{ + return QString::asprintf("QRect(%d, %d, %d, %d)", v.x(), v.y(), v.width(), v.height()); +} + int QQmlRectValueType::x() const { return v.x(); @@ -511,9 +349,9 @@ int QQmlRectValueType::bottom() const } #if QT_CONFIG(easingcurve) -QQmlEasingValueType::Type QQmlEasingValueType::type() const +QQmlEasingEnums::Type QQmlEasingValueType::type() const { - return (QQmlEasingValueType::Type)v.type(); + return (QQmlEasingEnums::Type)v.type(); } qreal QQmlEasingValueType::amplitude() const @@ -531,7 +369,7 @@ qreal QQmlEasingValueType::period() const return v.period(); } -void QQmlEasingValueType::setType(QQmlEasingValueType::Type type) +void QQmlEasingValueType::setType(QQmlEasingEnums::Type type) { v.setType((QEasingCurve::Type)type); } @@ -556,7 +394,7 @@ void QQmlEasingValueType::setBezierCurve(const QVariantList &customCurveVariant) if (customCurveVariant.isEmpty()) return; - if ((customCurveVariant.count() % 6) != 0) + if ((customCurveVariant.size() % 6) != 0) return; auto convert = [](const QVariant &v, qreal &r) { |