diff options
author | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2020-02-06 01:00:11 +0100 |
---|---|---|
committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2020-02-06 08:41:57 +0100 |
commit | 7d86b35dc6833057cae86d9a70e8f2c598c68db5 (patch) | |
tree | c5b3e87bd0edef2d74bc16b5aba6cbb6b298cd81 /src/qml | |
parent | 4975a33ba9aa357ba2bca93e292b1fbcfb34c24e (diff) | |
parent | 4e15f2135cdbefd9999a17d4e4fff5ea93679fac (diff) |
Merge remote-tracking branch 'origin/5.14' into 5.15
Conflicts:
.qmake.conf
src/qml/types/qqmlbind.cpp
src/quick/items/qquicklistview.cpp
tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
Change-Id: Id6805c13256ad13d5651011e5dd09bba0ec02987
Diffstat (limited to 'src/qml')
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 25 | ||||
-rw-r--r-- | src/qml/qml/qqmlengine_p.h | 16 | ||||
-rw-r--r-- | src/qml/qml/qqmlobjectcreator.cpp | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmlproperty.cpp | 38 | ||||
-rw-r--r-- | src/qml/qml/qqmlvaluetype.cpp | 92 | ||||
-rw-r--r-- | src/qml/qml/qqmlvaluetype_p.h | 49 | ||||
-rw-r--r-- | src/qml/qml/qqmlvmemetaobject.cpp | 12 | ||||
-rw-r--r-- | src/qml/types/qqmlbind.cpp | 8 |
8 files changed, 175 insertions, 69 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 86e178d568..04650ab979 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -1512,12 +1512,35 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int return QVariant::fromValue(QV4::JsonObject::toJsonArray(a)); } + QVariant retn; #if QT_CONFIG(qml_sequence_object) bool succeeded = false; - QVariant retn = QV4::SequencePrototype::toVariant(value, typeHint, &succeeded); + retn = QV4::SequencePrototype::toVariant(value, typeHint, &succeeded); if (succeeded) return retn; #endif + retn = QVariant(typeHint, QMetaType::create(typeHint)); + auto retnAsIterable = retn.value<QtMetaTypePrivate::QSequentialIterableImpl>(); + if (retnAsIterable._iteratorCapabilities & QtMetaTypePrivate::ContainerIsAppendable) { + auto const length = a->getLength(); + QV4::ScopedValue arrayValue(scope); + for (qint64 i = 0; i < length; ++i) { + arrayValue = a->get(i); + QVariant asVariant = toVariant(e, arrayValue, retnAsIterable._metaType_id, false, visitedObjects); + auto originalType = asVariant.userType(); + bool couldConvert = asVariant.convert(retnAsIterable._metaType_id); + if (!couldConvert) { + qWarning() << QLatin1String("Could not convert array value at position %1 from %2 to %3") + .arg(QString::number(i), + QMetaType::typeName(originalType), + QMetaType::typeName(retnAsIterable._metaType_id)); + // create default constructed value + asVariant = QVariant(retnAsIterable._metaType_id, nullptr); + } + retnAsIterable.append(asVariant.constData()); + } + return retn; + } } if (value.isUndefined()) diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h index ed81e055e5..263c69e2d8 100644 --- a/src/qml/qml/qqmlengine_p.h +++ b/src/qml/qml/qqmlengine_p.h @@ -271,8 +271,24 @@ public: mutable QMutex networkAccessManagerMutex; + QQmlGadgetPtrWrapper *valueTypeInstance(int typeIndex) + { + auto it = cachedValueTypeInstances.find(typeIndex); + if (it != cachedValueTypeInstances.end()) + return *it; + + if (QQmlValueType *valueType = QQmlValueTypeFactory::valueType(typeIndex)) { + QQmlGadgetPtrWrapper *instance = new QQmlGadgetPtrWrapper(valueType, q_func()); + cachedValueTypeInstances.insert(typeIndex, instance); + return instance; + } + + return nullptr; + } + private: QHash<QQmlType, QJSValue> singletonInstances; + QHash<int, QQmlGadgetPtrWrapper *> cachedValueTypeInstances; // These members must be protected by a QQmlEnginePrivate::Locker as they are required by // the threaded loader. Only access them through their respective accessor methods. diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 50e1918b6c..28dd3d4ab4 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -856,12 +856,12 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper if (stringAt(obj->inheritedTypeNameIndex).isEmpty()) { QObject *groupObject = nullptr; - QQmlValueType *valueType = nullptr; + QQmlGadgetPtrWrapper *valueType = nullptr; const QQmlPropertyData *valueTypeProperty = nullptr; QObject *bindingTarget = _bindingTarget; if (QQmlValueTypeFactory::isValueType(bindingProperty->propType())) { - valueType = QQmlValueTypeFactory::valueType(bindingProperty->propType()); + valueType = QQmlGadgetPtrWrapper::instance(engine, bindingProperty->propType()); if (!valueType) { recordError(binding->location, tr("Cannot set properties on %1 as it is null").arg(stringAt(binding->propertyNameIndex))); return false; diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp index 93020661e2..92fb6209af 100644 --- a/src/qml/qml/qqmlproperty.cpp +++ b/src/qml/qml/qqmlproperty.cpp @@ -1044,13 +1044,19 @@ QVariant QQmlProperty::read(const QObject *object, const QString &name, QQmlEngi QVariant QQmlPropertyPrivate::readValueProperty() { - if (isValueType()) { - - QQmlValueType *valueType = QQmlValueTypeFactory::valueType(core.propType()); - Q_ASSERT(valueType); - valueType->read(object, core.coreIndex()); - return valueType->metaObject()->property(valueTypeData.coreIndex()).read(valueType); + auto doRead = [&](QQmlGadgetPtrWrapper *wrapper) { + wrapper->read(object, core.coreIndex()); + return wrapper->property(valueTypeData.coreIndex()).read(wrapper); + }; + if (isValueType()) { + if (QQmlGadgetPtrWrapper *wrapper = QQmlGadgetPtrWrapper::instance(engine, core.propType())) + return doRead(wrapper); + if (QQmlValueType *valueType = QQmlValueTypeFactory::valueType(core.propType())) { + QQmlGadgetPtrWrapper wrapper(valueType, nullptr); + return doRead(&wrapper); + } + return QVariant(); } else if (core.isQList()) { QQmlListProperty<QObject> prop; @@ -1183,10 +1189,22 @@ QQmlPropertyPrivate::writeValueProperty(QObject *object, bool rv = false; if (valueTypeData.isValid()) { - QQmlValueType *writeBack = QQmlValueTypeFactory::valueType(core.propType()); - writeBack->read(object, core.coreIndex()); - rv = write(writeBack, valueTypeData, value, context, flags); - writeBack->write(object, core.coreIndex(), flags); + auto doWrite = [&](QQmlGadgetPtrWrapper *wrapper) { + wrapper->read(object, core.coreIndex()); + rv = write(wrapper, valueTypeData, value, context, flags); + wrapper->write(object, core.coreIndex(), flags); + }; + + QQmlGadgetPtrWrapper *wrapper = context + ? QQmlGadgetPtrWrapper::instance(context->engine, core.propType()) + : nullptr; + if (wrapper) { + doWrite(wrapper); + } else if (QQmlValueType *valueType = QQmlValueTypeFactory::valueType(core.propType())) { + QQmlGadgetPtrWrapper wrapper(valueType, nullptr); + doWrite(&wrapper); + } + } else { rv = write(object, core, value, context, flags); } diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp index cb3f572e1f..a86564a49a 100644 --- a/src/qml/qml/qqmlvaluetype.cpp +++ b/src/qml/qml/qqmlvaluetype.cpp @@ -42,11 +42,11 @@ #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> Q_DECLARE_METATYPE(QQmlProperty) @@ -217,61 +217,82 @@ void QQmlValueTypeFactory::registerValueTypes(const char *uri, int versionMajor, qmlRegisterValueTypeEnums<QQmlEasingValueType>(uri, versionMajor, versionMinor, "Easing"); } -QQmlValueType::QQmlValueType() : - _metaObject(nullptr), - gadgetPtr(nullptr), - metaType(QMetaType::UnknownType) +QQmlValueType::QQmlValueType(int typeId, const QMetaObject *gadgetMetaObject) + : metaType(typeId) { + QMetaObjectBuilder builder(gadgetMetaObject); + dynamicMetaObject = builder.toMetaObject(); + *static_cast<QMetaObject*>(this) = *dynamicMetaObject; } -QQmlValueType::QQmlValueType(int typeId, const QMetaObject *gadgetMetaObject) - : gadgetPtr(QMetaType::create(typeId)) - , metaType(typeId) +QQmlValueType::~QQmlValueType() { - QObjectPrivate *op = QObjectPrivate::get(this); - Q_ASSERT(!op->metaObject); - op->metaObject = this; + ::free(dynamicMetaObject); +} - QMetaObjectBuilder builder(gadgetMetaObject); - _metaObject = builder.toMetaObject(); +QQmlGadgetPtrWrapper *QQmlGadgetPtrWrapper::instance(QQmlEngine *engine, int index) +{ + return engine ? QQmlEnginePrivate::get(engine)->valueTypeInstance(index) : nullptr; +} - *static_cast<QMetaObject*>(this) = *_metaObject; +QQmlGadgetPtrWrapper::QQmlGadgetPtrWrapper(QQmlValueType *valueType, QObject *parent) + : QObject(parent), m_gadgetPtr(valueType->create()) +{ + QObjectPrivate *d = QObjectPrivate::get(this); + Q_ASSERT(!d->metaObject); + d->metaObject = valueType; } -QQmlValueType::~QQmlValueType() +QQmlGadgetPtrWrapper::~QQmlGadgetPtrWrapper() { - QObjectPrivate *op = QObjectPrivate::get(this); - Q_ASSERT(op->metaObject == nullptr || op->metaObject == this); - op->metaObject = nullptr; - ::free(const_cast<QMetaObject *>(_metaObject)); - metaType.destroy(gadgetPtr); + QObjectPrivate *d = QObjectPrivate::get(this); + static_cast<const QQmlValueType *>(d->metaObject)->destroy(m_gadgetPtr); + d->metaObject = nullptr; } -void QQmlValueType::read(QObject *obj, int idx) +void QQmlGadgetPtrWrapper::read(QObject *obj, int idx) { - void *a[] = { gadgetPtr, nullptr }; + Q_ASSERT(m_gadgetPtr); + void *a[] = { m_gadgetPtr, nullptr }; QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); } -void QQmlValueType::write(QObject *obj, int idx, QQmlPropertyData::WriteFlags flags) +void QQmlGadgetPtrWrapper::write(QObject *obj, int idx, QQmlPropertyData::WriteFlags flags) { - Q_ASSERT(gadgetPtr); + Q_ASSERT(m_gadgetPtr); int status = -1; - void *a[] = { gadgetPtr, nullptr, &status, &flags }; + void *a[] = { m_gadgetPtr, nullptr, &status, &flags }; QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a); } -QVariant QQmlValueType::value() +QVariant QQmlGadgetPtrWrapper::value() +{ + Q_ASSERT(m_gadgetPtr); + return QVariant(metaTypeId(), m_gadgetPtr); +} + +void QQmlGadgetPtrWrapper::setValue(const QVariant &value) +{ + Q_ASSERT(m_gadgetPtr); + Q_ASSERT(metaTypeId() == value.userType()); + const QQmlValueType *type = valueType(); + type->destruct(m_gadgetPtr); + type->construct(m_gadgetPtr, value.constData()); +} + +int QQmlGadgetPtrWrapper::metaCall(QMetaObject::Call type, int id, void **argv) { - Q_ASSERT(gadgetPtr); - return QVariant(metaType.id(), gadgetPtr); + Q_ASSERT(m_gadgetPtr); + const QMetaObject *metaObject = valueType(); + QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(type, &metaObject, &id); + metaObject->d.static_metacall(static_cast<QObject *>(m_gadgetPtr), type, id, argv); + return id; } -void QQmlValueType::setValue(const QVariant &value) +const QQmlValueType *QQmlGadgetPtrWrapper::valueType() const { - Q_ASSERT(metaType.id() == value.userType()); - metaType.destruct(gadgetPtr); - metaType.construct(gadgetPtr, value.constData()); + const QObjectPrivate *d = QObjectPrivate::get(this); + return static_cast<const QQmlValueType *>(d->metaObject); } QAbstractDynamicMetaObject *QQmlValueType::toDynamicMetaObject(QObject *) @@ -283,12 +304,9 @@ 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 diff --git a/src/qml/qml/qqmlvaluetype_p.h b/src/qml/qml/qqmlvaluetype_p.h index 0d581c7be8..29fa999725 100644 --- a/src/qml/qml/qqmlvaluetype_p.h +++ b/src/qml/qml/qqmlvaluetype_p.h @@ -54,7 +54,9 @@ #include "qqml.h" #include "qqmlproperty.h" #include "qqmlproperty_p.h" + #include <private/qqmlnullablevalue_p.h> +#include <private/qmetatype_p.h> #include <QtCore/qobject.h> #include <QtCore/qrect.h> @@ -63,16 +65,20 @@ QT_BEGIN_NAMESPACE -class Q_QML_PRIVATE_EXPORT QQmlValueType : public QObject, public QAbstractDynamicMetaObject +class Q_QML_PRIVATE_EXPORT QQmlValueType : public QAbstractDynamicMetaObject { public: - QQmlValueType(); + QQmlValueType() : metaType(QMetaType::UnknownType) {} QQmlValueType(int userType, const QMetaObject *metaObject); - ~QQmlValueType() override; - void read(QObject *, int); - void write(QObject *, int, QQmlPropertyData::WriteFlags flags); - QVariant value(); - void setValue(const QVariant &); + ~QQmlValueType(); + + void *create() const { return metaType.create(); } + void destroy(void *gadgetPtr) const { metaType.destroy(gadgetPtr); } + + void construct(void *gadgetPtr, const void *copy) const { metaType.construct(gadgetPtr, copy); } + void destruct(void *gadgetPtr) const { metaType.destruct(gadgetPtr); } + + int metaTypeId() const { return metaType.id(); } // ---- dynamic meta object data interface QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *) override; @@ -80,12 +86,33 @@ public: int metaCall(QObject *obj, QMetaObject::Call type, int _id, void **argv) override; // ---- -private: - const QMetaObject *_metaObject; - void *gadgetPtr; - public: QMetaType metaType; + QMetaObject *dynamicMetaObject = nullptr; +}; + +class Q_QML_PRIVATE_EXPORT QQmlGadgetPtrWrapper : public QObject +{ + Q_OBJECT +public: + static QQmlGadgetPtrWrapper *instance(QQmlEngine *engine, int index); + + QQmlGadgetPtrWrapper(QQmlValueType *valueType, QObject *parent); + ~QQmlGadgetPtrWrapper(); + + void read(QObject *obj, int idx); + void write(QObject *obj, int idx, QQmlPropertyData::WriteFlags flags); + QVariant value(); + void setValue(const QVariant &value); + + int metaTypeId() const { return valueType()->metaTypeId(); } + int metaCall(QMetaObject::Call type, int id, void **argv); + QMetaProperty property(int index) { return valueType()->property(index); } + +private: + const QQmlValueType *valueType() const; + + void *m_gadgetPtr = nullptr; }; class Q_QML_PRIVATE_EXPORT QQmlValueTypeFactory diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index ecb86e2f10..c20bc24a49 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -289,11 +289,13 @@ bool QQmlInterceptorMetaObject::intercept(QMetaObject::Call c, int id, void **a) continue; const int valueIndex = vi->m_propertyIndex.valueTypeIndex(); - int type = QQmlData::get(object)->propertyCache->property(id)->propType(); + const QQmlData *data = QQmlData::get(object); + const int type = data->propertyCache->property(id)->propType(); if (type != QMetaType::UnknownType) { if (valueIndex != -1) { - QQmlValueType *valueType = QQmlValueTypeFactory::valueType(type); + QQmlGadgetPtrWrapper *valueType = QQmlGadgetPtrWrapper::instance( + data->context->engine, type); Q_ASSERT(valueType); // @@ -327,7 +329,7 @@ bool QQmlInterceptorMetaObject::intercept(QMetaObject::Call c, int id, void **a) // (7) Issue the interceptor call with the new component value. // - QMetaProperty valueProp = valueType->metaObject()->property(valueIndex); + QMetaProperty valueProp = valueType->property(valueIndex); QVariant newValue(type, a[0]); valueType->read(object, id); @@ -879,9 +881,9 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * return -1; const QQmlPropertyData *pd = targetDData->propertyCache->property(coreIndex); // Value type property or deep alias - QQmlValueType *valueType = QQmlValueTypeFactory::valueType(pd->propType()); + QQmlGadgetPtrWrapper *valueType = QQmlGadgetPtrWrapper::instance( + ctxt->engine, pd->propType()); if (valueType) { - valueType->read(target, coreIndex); int rv = QMetaObject::metacall(valueType, c, valueTypePropertyIndex, a); diff --git a/src/qml/types/qqmlbind.cpp b/src/qml/types/qqmlbind.cpp index 64c135b392..6d6553259e 100644 --- a/src/qml/types/qqmlbind.cpp +++ b/src/qml/types/qqmlbind.cpp @@ -486,9 +486,10 @@ void QQmlBind::eval() qmlWarning(this) << "Not restoring previous value because restoreMode has not been set.\n" << "This behavior is deprecated.\n" - << "You have to import QtQml 2.15 and set the restoreMode of the binding to fix this warning.\n" + << "You have to import QtQml 2.15 after any QtQuick imports and set\n" + << "the restoreMode of the binding to fix this warning.\n" << "In Qt < 6.0 the default is Binding.RestoreBinding.\n" - << "In Qt >= 6.0 the default is Binding.RestoreBindingOrValue.\n"; + << "In Qt >= 6.0 the default is Binding.RestoreBindingOrValue."; } } else if (d->prevIsVariant) { if (d->restoreValue) { @@ -498,7 +499,8 @@ void QQmlBind::eval() qmlWarning(this) << "Not restoring previous value because restoreMode has not been set.\n" << "This behavior is deprecated.\n" - << "You have to import QtQml 2.15 and set the restoreMode of the binding to fix this warning.\n" + << "You have to import QtQml 2.15 after any QtQuick imports and set\n" + << "the restoreMode of the binding to fix this warning.\n" << "In Qt < 6.0 the default is Binding.RestoreBinding.\n" << "In Qt >= 6.0 the default is Binding.RestoreBindingOrValue.\n"; } |