From fa3cf15e0577fe382ac577456422ad78325a3977 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 10 Nov 2014 11:39:03 +0100 Subject: [PATCH] Initial work on gadget support Changed built-in QtQml value types to use gadgets. This is in preparation for supporting external gadgets. This replaces the mostly direct inheritance of the concrete value types with gadgets and "dynamic" inheritance through QQmlValueType being generic. Over time as some of the value types may become gadgets, we can remove the ones here. It's important that these "separate" gadgets have the same memory layout as the actual types (QPointF, etc.). Also while QQmlValueType remains practically a singleton, it's not required anymore to be one. Consequently the JS wrappers for value types keep their own instance of QQmlValueType. This allows eliminating the qobject_cast in various places that dealt with the singleton nature. This comes at a cost, making the JS wrappers slightly heavier. However that is meant to be a temporary situation and finally the value type wrapper should merely store the meta-object in addition to the data and the type. Change-Id: I15071ded0a1e54203f29ec1ecf7a9ab646d1168e Reviewed-by: Lars Knoll --- src/qml/compiler/qqmlirbuilder.cpp | 4 +- src/qml/compiler/qqmltypecompiler.cpp | 18 +- src/qml/jsruntime/qv4qobjectwrapper.cpp | 35 +--- src/qml/qml/qqmlglobal.cpp | 10 +- src/qml/qml/qqmlglobal_p.h | 6 +- src/qml/qml/qqmlproperty.cpp | 20 +-- src/qml/qml/qqmlvaluetype.cpp | 198 +++++++++++++-------- src/qml/qml/qqmlvaluetype_p.h | 158 +++++----------- src/qml/qml/qqmlvaluetypewrapper.cpp | 35 ++-- src/qml/qml/qqmlvaluetypewrapper_p.h | 6 +- src/qml/qml/v8/qv8engine.cpp | 8 +- src/quick/util/qquickglobal.cpp | 25 +-- src/quick/util/qquickvaluetypes.cpp | 93 +--------- src/quick/util/qquickvaluetypes_p.h | 70 +++----- .../tst_qqmlvaluetypeproviders.cpp | 23 ++- .../auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp | 21 --- 16 files changed, 274 insertions(+), 456 deletions(-) diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index 339278f..07ea2a6 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -1941,8 +1941,8 @@ static QV4::IR::Type resolveMetaObjectProperty(QQmlEnginePrivate *qmlEngine, QV4 initMetaObjectResolver(resolver, cache); return QV4::IR::QObjectType; } - } else if (QQmlValueType *valueType = QQmlValueTypeFactory::valueType(property->propType)) { - if (QQmlPropertyCache *cache = qmlEngine->cache(valueType->metaObject())) { + } else if (const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(property->propType)) { + if (QQmlPropertyCache *cache = qmlEngine->cache(valueTypeMetaObject)) { initMetaObjectResolver(resolver, cache); resolver->flags |= ResolveTypeInformationOnly; return QV4::IR::QObjectType; diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index ada848f..7f399f0 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -463,8 +463,8 @@ bool QQmlPropertyCacheCreator::buildMetaObjectRecursively(int objectIndex, int r if (instantiatingProperty->isQObject()) { baseTypeCache = enginePrivate->rawPropertyCacheForType(instantiatingProperty->propType); Q_ASSERT(baseTypeCache); - } else if (QQmlValueType *vt = QQmlValueTypeFactory::valueType(instantiatingProperty->propType)) { - baseTypeCache = enginePrivate->cache(vt->metaObject()); + } else if (const QMetaObject *vtmo = QQmlValueTypeFactory::metaObjectForMetaType(instantiatingProperty->propType)) { + baseTypeCache = enginePrivate->cache(vtmo); Q_ASSERT(baseTypeCache); } } @@ -1630,8 +1630,8 @@ bool QQmlComponentAndAliasResolver::resolveAliases() notifySignal = targetProperty->notifyIndex; if (!subProperty.isEmpty()) { - QQmlValueType *valueType = QQmlValueTypeFactory::valueType(type); - if (!valueType) { + const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(type); + if (!valueTypeMetaObject) { recordError(p->aliasLocation, tr("Invalid alias location")); return false; } @@ -1639,7 +1639,7 @@ bool QQmlComponentAndAliasResolver::resolveAliases() propType = type; int valueTypeIndex = - valueType->metaObject()->indexOfProperty(subProperty.toString().toUtf8().constData()); + valueTypeMetaObject->indexOfProperty(subProperty.toString().toUtf8().constData()); if (valueTypeIndex == -1) { recordError(p->aliasLocation, tr("Invalid alias location")); return false; @@ -1647,10 +1647,10 @@ bool QQmlComponentAndAliasResolver::resolveAliases() Q_ASSERT(valueTypeIndex <= 0x0000FFFF); propIdx = QQmlPropertyData::encodeValueTypePropertyIndex(propIdx, valueTypeIndex); - if (valueType->metaObject()->property(valueTypeIndex).isEnumType()) + if (valueTypeMetaObject->property(valueTypeIndex).isEnumType()) type = QVariant::Int; else - type = valueType->metaObject()->property(valueTypeIndex).userType(); + type = valueTypeMetaObject->property(valueTypeIndex).userType(); } else { if (targetProperty->isEnum()) { @@ -1887,7 +1887,7 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD if (binding->type >= QV4::CompiledData::Binding::Type_Object && !customParser) { qSwap(_seenObjectWithId, seenSubObjectWithId); - const bool subObjectValid = validateObject(binding->value.objectIndex, binding, pd && QQmlValueTypeFactory::valueType(pd->propType)); + const bool subObjectValid = validateObject(binding->value.objectIndex, binding, pd && QQmlValueTypeFactory::metaObjectForMetaType(pd->propType)); qSwap(_seenObjectWithId, seenSubObjectWithId); if (!subObjectValid) return false; @@ -1961,7 +1961,7 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD return false; } else if (binding->isGroupProperty()) { if (QQmlValueTypeFactory::isValueType(pd->propType)) { - if (QQmlValueTypeFactory::valueType(pd->propType)) { + if (QQmlValueTypeFactory::metaObjectForMetaType(pd->propType)) { if (!pd->isWritable()) { recordError(binding->location, tr("Invalid property assignment: \"%1\" is a read-only property").arg(name)); return false; diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index daaa0c1..c2b3b44 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -201,16 +201,16 @@ static QV4::ReturnedValue LoadProperty(QV8Engine *engine, QObject *object, ReadFunction(object, property, &v, notifier); if (QQmlValueTypeFactory::isValueType(v.userType())) { - if (QQmlValueType *valueType = QQmlValueTypeFactory::valueType(v.userType())) - return QV4::QmlValueTypeWrapper::create(engine, object, property.coreIndex, valueType); // VariantReference value-type. + if (const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(v.userType())) + return QV4::QmlValueTypeWrapper::create(engine, object, property.coreIndex, valueTypeMetaObject, v.userType()); // VariantReference value-type. } return engine->fromVariant(v); } else if (QQmlValueTypeFactory::isValueType(property.propType)) { Q_ASSERT(notifier == 0); - if (QQmlValueType *valueType = QQmlValueTypeFactory::valueType(property.propType)) - return QV4::QmlValueTypeWrapper::create(engine, object, property.coreIndex, valueType); + if (const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(property.propType)) + return QV4::QmlValueTypeWrapper::create(engine, object, property.coreIndex, valueTypeMetaObject, property.propType); } else { Q_ASSERT(notifier == 0); @@ -1134,17 +1134,6 @@ static QV4::ReturnedValue CallMethod(QObject *object, int index, int returnType, int *argTypes, QV8Engine *engine, QV4::CallData *callArgs) { if (argCount > 0) { - - // Special handling is required for value types. - // We need to save the current value in a temporary, - // and reapply it after converting all arguments. - // This avoids the "overwriting copy-value-type-value" - // problem during Q_INVOKABLE function invocation. - QQmlValueType *valueTypeObject = qobject_cast(object); - QVariant valueTypeValue; - if (valueTypeObject) - valueTypeValue = valueTypeObject->value(); - // Convert all arguments. QVarLengthArray args(argCount + 1); args[0].initAsType(returnType); @@ -1154,10 +1143,6 @@ static QV4::ReturnedValue CallMethod(QObject *object, int index, int returnType, for (int ii = 0; ii < args.count(); ++ii) argData[ii] = args[ii].dataPtr(); - // Reinstate saved value type object value if required. - if (valueTypeObject) - valueTypeObject->setValue(valueTypeValue); - QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, argData.data()); return args[0].toValue(engine); @@ -1443,16 +1428,6 @@ static QV4::ReturnedValue CallOverloaded(QObject *object, const QQmlPropertyData int bestParameterScore = INT_MAX; int bestMatchScore = INT_MAX; - // Special handling is required for value types. - // We need to save the current value in a temporary, - // and reapply it after converting all arguments. - // This avoids the "overwriting copy-value-type-value" - // problem during Q_INVOKABLE function invocation. - QQmlValueType *valueTypeObject = qobject_cast(object); - QVariant valueTypeValue; - if (valueTypeObject) - valueTypeValue = valueTypeObject->value(); - QQmlPropertyData dummy; const QQmlPropertyData *attempt = &data; @@ -1496,8 +1471,6 @@ static QV4::ReturnedValue CallOverloaded(QObject *object, const QQmlPropertyData } while((attempt = RelatedMethod(object, attempt, dummy)) != 0); if (best.isValid()) { - if (valueTypeObject) - valueTypeObject->setValue(valueTypeValue); return CallPrecise(object, best, engine, callArgs); } else { QString error = QLatin1String("Unable to determine callable overload. Candidates are:"); diff --git a/src/qml/qml/qqmlglobal.cpp b/src/qml/qml/qqmlglobal.cpp index 492836a..57c0993 100644 --- a/src/qml/qml/qqmlglobal.cpp +++ b/src/qml/qml/qqmlglobal.cpp @@ -50,14 +50,12 @@ QQmlValueTypeProvider::~QQmlValueTypeProvider() QQml_removeValueTypeProvider(this); } -QQmlValueType *QQmlValueTypeProvider::createValueType(int type) +const QMetaObject *QQmlValueTypeProvider::metaObjectForMetaType(int type) { - QQmlValueType *value = 0; - QQmlValueTypeProvider *p = this; do { - if (p->create(type, value)) - return value; + if (const QMetaObject *mo = p->getMetaObjectForMetaType(type)) + return mo; } while ((p = p->next)); return 0; @@ -245,7 +243,7 @@ bool QQmlValueTypeProvider::writeValueType(int type, const void *src, void *dst, return false; } -bool QQmlValueTypeProvider::create(int, QQmlValueType *&) { return false; } +const QMetaObject *QQmlValueTypeProvider::getMetaObjectForMetaType(int) { return 0; } bool QQmlValueTypeProvider::init(int, void *, size_t) { return false; } bool QQmlValueTypeProvider::destroy(int, void *, size_t) { return false; } bool QQmlValueTypeProvider::copy(int, const void *, void *, size_t) { return false; } diff --git a/src/qml/qml/qqmlglobal_p.h b/src/qml/qml/qqmlglobal_p.h index 1d0bf59..2832d03 100644 --- a/src/qml/qml/qqmlglobal_p.h +++ b/src/qml/qml/qqmlglobal_p.h @@ -215,7 +215,6 @@ inline void QQml_setParent_noEvent(QObject *object, QObject *parent) } -class QQmlValueType; class QV8Engine; class Q_QML_PRIVATE_EXPORT QQmlValueTypeProvider { @@ -223,7 +222,7 @@ public: QQmlValueTypeProvider(); virtual ~QQmlValueTypeProvider(); - QQmlValueType *createValueType(int); + const QMetaObject *metaObjectForMetaType(int); bool initValueType(int, void *, size_t); bool destroyValueType(int, void *, size_t); @@ -243,8 +242,7 @@ public: bool writeValueType(int, const void *, void *, size_t); private: - virtual bool create(int, QQmlValueType *&); - + virtual const QMetaObject *getMetaObjectForMetaType(int); virtual bool init(int, void *, size_t); virtual bool destroy(int, void *, size_t); virtual bool copy(int, const void *, void *, size_t); diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp index 635e4d4..0ee8f94 100644 --- a/src/qml/qml/qqmlproperty.cpp +++ b/src/qml/qml/qqmlproperty.cpp @@ -284,13 +284,13 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name) if (ii == (path.count() - 2) && QQmlValueTypeFactory::isValueType(property->propType)) { // We're now at a value type property - QObject *typeObject = QQmlValueTypeFactory::valueType(property->propType); - if (!typeObject) return; // Not a value type + const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(property->propType); + if (!valueTypeMetaObject) return; // Not a value type - int idx = typeObject->metaObject()->indexOfProperty(path.last().toUtf8().constData()); + int idx = valueTypeMetaObject->indexOfProperty(path.last().toUtf8().constData()); if (idx == -1) return; // Value type property does not exist - QMetaProperty vtProp = typeObject->metaObject()->property(idx); + QMetaProperty vtProp = valueTypeMetaObject->property(idx); Q_ASSERT(QQmlPropertyData::flagsForProperty(vtProp) <= QQmlPropertyData::ValueTypeFlagMask); Q_ASSERT(vtProp.userType() <= 0x0000FFFF); @@ -463,9 +463,9 @@ const char *QQmlProperty::propertyTypeName() const if (!d) return 0; if (d->isValueType()) { - QQmlValueType *valueType = QQmlValueTypeFactory::valueType(d->core.propType); - Q_ASSERT(valueType); - return valueType->metaObject()->property(d->core.valueTypeCoreIndex).typeName(); + const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(d->core.propType); + Q_ASSERT(valueTypeMetaObject); + return valueTypeMetaObject->property(d->core.valueTypeCoreIndex).typeName(); } else if (d->object && type() & Property && d->core.isValid()) { return d->object->metaObject()->property(d->core.coreIndex).typeName(); } else { @@ -642,10 +642,10 @@ QString QQmlProperty::name() const } else if (d->isValueType()) { QString rv = d->core.name(d->object) + QLatin1Char('.'); - QQmlValueType *valueType = QQmlValueTypeFactory::valueType(d->core.propType); - Q_ASSERT(valueType); + const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(d->core.propType); + Q_ASSERT(valueTypeMetaObject); - const char *vtName = valueType->metaObject()->property(d->core.valueTypeCoreIndex).name(); + const char *vtName = valueTypeMetaObject->property(d->core.valueTypeCoreIndex).name(); rv += QString::fromUtf8(vtName); d->nameCache = rv; diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp index f73b50a..20f3027 100644 --- a/src/qml/qml/qqmlvaluetype.cpp +++ b/src/qml/qml/qqmlvaluetype.cpp @@ -36,6 +36,7 @@ #include #include +#include QT_BEGIN_NAMESPACE @@ -48,7 +49,7 @@ struct QQmlValueTypeFactoryImpl bool isValueType(int idx); - QQmlValueType *createValueType(int); + const QMetaObject *metaObjectForMetaType(int); QQmlValueType *valueType(int); QQmlValueType *valueTypes[QVariant::UserType]; @@ -83,39 +84,30 @@ bool QQmlValueTypeFactoryImpl::isValueType(int idx) return false; } -QQmlValueType *QQmlValueTypeFactoryImpl::createValueType(int t) +const QMetaObject *QQmlValueTypeFactoryImpl::metaObjectForMetaType(int t) { - QQmlValueType *rv = 0; - switch (t) { case QVariant::Point: - rv = new QQmlPointValueType; - break; + return &QQmlPointValueType::staticMetaObject; case QVariant::PointF: - rv = new QQmlPointFValueType; - break; + return &QQmlPointFValueType::staticMetaObject; case QVariant::Size: - rv = new QQmlSizeValueType; - break; + return &QQmlSizeValueType::staticMetaObject; case QVariant::SizeF: - rv = new QQmlSizeFValueType; - break; + return &QQmlSizeFValueType::staticMetaObject; case QVariant::Rect: - rv = new QQmlRectValueType; - break; + return &QQmlRectValueType::staticMetaObject; case QVariant::RectF: - rv = new QQmlRectFValueType; - break; + return &QQmlRectFValueType::staticMetaObject; case QVariant::EasingCurve: - rv = new QQmlEasingValueType; - break; + return &QQmlEasingValueType::staticMetaObject; default: - rv = QQml_valueTypeProvider()->createValueType(t); + if (const QMetaObject *mo = QQml_valueTypeProvider()->metaObjectForMetaType(t)) + return mo; break; } - Q_ASSERT(!rv || rv->metaObject()->propertyCount() < 32); - return rv; + return 0; } QQmlValueType *QQmlValueTypeFactoryImpl::valueType(int idx) @@ -126,7 +118,10 @@ QQmlValueType *QQmlValueTypeFactoryImpl::valueType(int idx) QHash::iterator it = userTypes.find(idx); if (it == userTypes.end()) { - it = userTypes.insert(idx, createValueType(idx)); + QQmlValueType *vt = 0; + if (const QMetaObject *mo = metaObjectForMetaType(idx)) + vt = new QQmlValueType(idx, mo); + it = userTypes.insert(idx, vt); } mutex.unlock(); @@ -139,7 +134,8 @@ QQmlValueType *QQmlValueTypeFactoryImpl::valueType(int idx) // TODO: Investigate the performance/memory characteristics of // removing the preallocated array - if ((rv = createValueType(idx))) { + if (const QMetaObject *mo = metaObjectForMetaType(idx)) { + rv = new QQmlValueType(idx, mo); valueTypes[idx] = rv; } } @@ -161,20 +157,116 @@ QQmlValueType *QQmlValueTypeFactory::valueType(int idx) return factoryImpl()->valueType(idx); } +const QMetaObject *QQmlValueTypeFactory::metaObjectForMetaType(int type) +{ + return factoryImpl()->metaObjectForMetaType(type); +} + void QQmlValueTypeFactory::registerValueTypes(const char *uri, int versionMajor, int versionMinor) { qmlRegisterValueTypeEnums(uri, versionMajor, versionMinor, "Easing"); } +QQmlValueType::QQmlValueType(int typeId, const QMetaObject *gadgetMetaObject) + : typeId(typeId) + , gadgetPtr(QMetaType::create(typeId)) +{ + QObjectPrivate *op = QObjectPrivate::get(this); + Q_ASSERT(!op->metaObject); + op->metaObject = this; + + QMetaObjectBuilder builder(gadgetMetaObject); + _metaObject = builder.toMetaObject(); + + *static_cast(this) = *_metaObject; +} + +QQmlValueType::~QQmlValueType() +{ + QObjectPrivate *op = QObjectPrivate::get(this); + Q_ASSERT(op->metaObject == this); + op->metaObject = 0; + ::free((void*)_metaObject); + QMetaType::destroy(typeId, gadgetPtr); +} + +void QQmlValueType::read(QObject *obj, int idx) +{ + readProperty(obj, idx, gadgetPtr); +} + +void QQmlValueType::readVariantValue(QObject *obj, int idx, QVariant *into) +{ + // important: must not change the userType of the variant + readProperty(obj, idx, into); +} + +void QQmlValueType::write(QObject *obj, int idx, QQmlPropertyPrivate::WriteFlags flags) +{ + Q_ASSERT(gadgetPtr); + writeProperty(obj, idx, flags, gadgetPtr); +} + +void QQmlValueType::writeVariantValue(QObject *obj, int idx, QQmlPropertyPrivate::WriteFlags flags, QVariant *from) +{ + writeProperty(obj, idx, flags, from); +} + +QVariant QQmlValueType::value() +{ + Q_ASSERT(gadgetPtr); + return QVariant(typeId, gadgetPtr); +} + +void QQmlValueType::setValue(const QVariant &value) +{ + Q_ASSERT(typeId == value.userType()); + QMetaType::destruct(typeId, gadgetPtr); + QMetaType::construct(typeId, gadgetPtr, value.constData()); +} + +bool QQmlValueType::isEqual(const QVariant &other) const +{ + Q_ASSERT(gadgetPtr); + return QVariant(typeId, gadgetPtr) == other; +} + +QString QQmlValueType::toString() const +{ + const QMetaObject *mo = metaObject(); + const int toStringIndex = mo->indexOfMethod("toString()"); + if (toStringIndex != -1) { + QString result; + void *args[] = { &result, 0 }; + _metaObject->d.static_metacall(reinterpret_cast(gadgetPtr), QMetaObject::InvokeMetaMethod, toStringIndex, args); + return result; + } + QString result = QString::fromUtf8(QMetaType::typeName(typeId)); + result += QLatin1Char('('); + const int propCount = mo->propertyCount(); + for (int i = 0; i < propCount; ++i) { + QVariant value = mo->property(i).read(this); + result += value.toString(); + if (i < propCount - 1) + result += QStringLiteral(", "); + } + result += QLatin1Char(')'); + return result; +} + +QAbstractDynamicMetaObject *QQmlValueType::toDynamicMetaObject(QObject *) +{ + return this; +} -QQmlValueType::QQmlValueType(int userType, QObject *parent) -: QObject(parent), m_userType(userType) +void QQmlValueType::objectDestroyed(QObject *) { } -QQmlPointFValueType::QQmlPointFValueType(QObject *parent) - : QQmlValueTypeBase(QMetaType::QPointF, parent) +int QQmlValueType::metaCall(QObject *, QMetaObject::Call type, int _id, void **argv) { + d.static_metacall(reinterpret_cast(gadgetPtr), type, _id, argv); + return _id; } QString QQmlPointFValueType::toString() const @@ -203,16 +295,6 @@ void QQmlPointFValueType::setY(qreal y) } -QQmlPointValueType::QQmlPointValueType(QObject *parent) - : QQmlValueTypeBase(QMetaType::QPoint, parent) -{ -} - -QString QQmlPointValueType::toString() const -{ - return QString(QLatin1String("QPoint(%1, %2)")).arg(v.x()).arg(v.y()); -} - int QQmlPointValueType::x() const { return v.x(); @@ -234,11 +316,6 @@ void QQmlPointValueType::setY(int y) } -QQmlSizeFValueType::QQmlSizeFValueType(QObject *parent) - : QQmlValueTypeBase(QMetaType::QSizeF, parent) -{ -} - QString QQmlSizeFValueType::toString() const { return QString(QLatin1String("QSizeF(%1, %2)")).arg(v.width()).arg(v.height()); @@ -265,16 +342,6 @@ void QQmlSizeFValueType::setHeight(qreal h) } -QQmlSizeValueType::QQmlSizeValueType(QObject *parent) - : QQmlValueTypeBase(QMetaType::QSize, parent) -{ -} - -QString QQmlSizeValueType::toString() const -{ - return QString(QLatin1String("QSize(%1, %2)")).arg(v.width()).arg(v.height()); -} - int QQmlSizeValueType::width() const { return v.width(); @@ -295,12 +362,6 @@ void QQmlSizeValueType::setHeight(int h) v.setHeight(h); } - -QQmlRectFValueType::QQmlRectFValueType(QObject *parent) - : QQmlValueTypeBase(QMetaType::QRectF, parent) -{ -} - QString QQmlRectFValueType::toString() const { return QString(QLatin1String("QRectF(%1, %2, %3, %4)")).arg(v.x()).arg(v.y()).arg(v.width()).arg(v.height()); @@ -346,17 +407,6 @@ void QQmlRectFValueType::setHeight(qreal h) v.setHeight(h); } - -QQmlRectValueType::QQmlRectValueType(QObject *parent) - : QQmlValueTypeBase(QMetaType::QRect, parent) -{ -} - -QString QQmlRectValueType::toString() const -{ - return QString(QLatin1String("QRect(%1, %2, %3, %4)")).arg(v.x()).arg(v.y()).arg(v.width()).arg(v.height()); -} - int QQmlRectValueType::x() const { return v.x(); @@ -398,16 +448,6 @@ void QQmlRectValueType::setHeight(int h) } -QQmlEasingValueType::QQmlEasingValueType(QObject *parent) - : QQmlValueTypeBase(QMetaType::QEasingCurve, parent) -{ -} - -QString QQmlEasingValueType::toString() const -{ - return QString(QLatin1String("QEasingCurve(%1, %2, %3, %4)")).arg(v.type()).arg(v.amplitude()).arg(v.overshoot()).arg(v.period()); -} - QQmlEasingValueType::Type QQmlEasingValueType::type() const { return (QQmlEasingValueType::Type)v.type(); diff --git a/src/qml/qml/qqmlvaluetype_p.h b/src/qml/qml/qqmlvaluetype_p.h index 5a6bcdd..2f6a192 100644 --- a/src/qml/qml/qqmlvaluetype_p.h +++ b/src/qml/qml/qqmlvaluetype_p.h @@ -57,34 +57,37 @@ QT_BEGIN_NAMESPACE -class Q_QML_PRIVATE_EXPORT QQmlValueType : public QObject +class Q_QML_PRIVATE_EXPORT QQmlValueType : public QObject, public QAbstractDynamicMetaObject { - Q_OBJECT public: - QQmlValueType(int userType, QObject *parent = 0); - virtual void read(QObject *, int) = 0; - virtual void readVariantValue(QObject *, int, QVariant *) = 0; - virtual void write(QObject *, int, QQmlPropertyPrivate::WriteFlags flags) = 0; - virtual void writeVariantValue(QObject *, int, QQmlPropertyPrivate::WriteFlags, QVariant *) = 0; - virtual QVariant value() = 0; - virtual void setValue(const QVariant &) = 0; - - virtual QString toString() const = 0; - virtual bool isEqual(const QVariant &value) const = 0; - - virtual void onLoad() {} + QQmlValueType(int userType, const QMetaObject *metaObject); + ~QQmlValueType(); + void read(QObject *, int); + void readVariantValue(QObject *, int, QVariant *); + void write(QObject *, int, QQmlPropertyPrivate::WriteFlags flags); + void writeVariantValue(QObject *, int, QQmlPropertyPrivate::WriteFlags, QVariant *); + QVariant value(); + void setValue(const QVariant &); + + QString toString() const; + bool isEqual(const QVariant &value) const; inline int userType() const { - return m_userType; + return typeId; + } + // ---- dynamic meta object data interface + virtual QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *); + virtual void objectDestroyed(QObject *); + virtual int metaCall(QObject *obj, QMetaObject::Call type, int _id, void **argv); + // ---- protected: inline void readProperty(QObject *obj, int idx, void *p) { void *a[] = { p, 0 }; QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); - onLoad(); } inline void writeProperty(QObject *obj, int idx, QQmlPropertyPrivate::WriteFlags flags, void *p) @@ -95,59 +98,9 @@ protected: } private: - int m_userType; -}; - -template -class QQmlValueTypeBase : public QQmlValueType -{ -public: - typedef T ValueType; - - QQmlValueTypeBase(int userType, QObject *parent) - : QQmlValueType(userType, parent) - { - } - - virtual void read(QObject *obj, int idx) - { - readProperty(obj, idx, &v); - } - - virtual void readVariantValue(QObject *obj, int idx, QVariant *into) - { - // important: must not change the userType of the variant - readProperty(obj, idx, into); - } - - virtual void write(QObject *obj, int idx, QQmlPropertyPrivate::WriteFlags flags) - { - writeProperty(obj, idx, flags, &v); - } - - virtual void writeVariantValue(QObject *obj, int idx, QQmlPropertyPrivate::WriteFlags flags, QVariant *from) - { - writeProperty(obj, idx, flags, from); - } - - virtual QVariant value() - { - return QVariant::fromValue(v); - } - - virtual void setValue(const QVariant &value) - { - v = qvariant_cast(value); - onLoad(); - } - - virtual bool isEqual(const QVariant &other) const - { - return QVariant::fromValue(v) == other; - } - -protected: - ValueType v; + const QMetaObject *_metaObject; + int typeId; + void *gadgetPtr; }; class Q_QML_PRIVATE_EXPORT QQmlValueTypeFactory @@ -155,86 +108,75 @@ class Q_QML_PRIVATE_EXPORT QQmlValueTypeFactory public: static bool isValueType(int); static QQmlValueType *valueType(int idx); + static const QMetaObject *metaObjectForMetaType(int type); static void registerValueTypes(const char *uri, int versionMajor, int versionMinor); }; -class Q_QML_PRIVATE_EXPORT QQmlPointFValueType : public QQmlValueTypeBase +struct QQmlPointFValueType { + QPointF v; Q_PROPERTY(qreal x READ x WRITE setX FINAL) Q_PROPERTY(qreal y READ y WRITE setY FINAL) - Q_OBJECT + Q_GADGET public: - QQmlPointFValueType(QObject *parent = 0); - - virtual QString toString() const; - + Q_INVOKABLE QString toString() const; qreal x() const; qreal y() const; void setX(qreal); void setY(qreal); }; -class Q_QML_PRIVATE_EXPORT QQmlPointValueType : public QQmlValueTypeBase +struct QQmlPointValueType { + QPoint v; Q_PROPERTY(int x READ x WRITE setX FINAL) Q_PROPERTY(int y READ y WRITE setY FINAL) - Q_OBJECT + Q_GADGET public: - QQmlPointValueType(QObject *parent = 0); - - virtual QString toString() const; - int x() const; int y() const; void setX(int); void setY(int); }; -class Q_QML_PRIVATE_EXPORT QQmlSizeFValueType : public QQmlValueTypeBase +struct QQmlSizeFValueType { + QSizeF v; Q_PROPERTY(qreal width READ width WRITE setWidth FINAL) Q_PROPERTY(qreal height READ height WRITE setHeight FINAL) - Q_OBJECT + Q_GADGET public: - QQmlSizeFValueType(QObject *parent = 0); - - virtual QString toString() const; - + Q_INVOKABLE QString toString() const; qreal width() const; qreal height() const; void setWidth(qreal); void setHeight(qreal); }; -class Q_QML_PRIVATE_EXPORT QQmlSizeValueType : public QQmlValueTypeBase +struct QQmlSizeValueType { + QSize v; Q_PROPERTY(int width READ width WRITE setWidth FINAL) Q_PROPERTY(int height READ height WRITE setHeight FINAL) - Q_OBJECT + Q_GADGET public: - QQmlSizeValueType(QObject *parent = 0); - - virtual QString toString() const; - int width() const; int height() const; void setWidth(int); void setHeight(int); }; -class Q_QML_PRIVATE_EXPORT QQmlRectFValueType : public QQmlValueTypeBase +struct QQmlRectFValueType { + QRectF v; Q_PROPERTY(qreal x READ x WRITE setX FINAL) Q_PROPERTY(qreal y READ y WRITE setY FINAL) Q_PROPERTY(qreal width READ width WRITE setWidth FINAL) Q_PROPERTY(qreal height READ height WRITE setHeight FINAL) - Q_OBJECT + Q_GADGET public: - QQmlRectFValueType(QObject *parent = 0); - - virtual QString toString() const; - + Q_INVOKABLE QString toString() const; qreal x() const; qreal y() const; void setX(qreal); @@ -246,18 +188,15 @@ public: void setHeight(qreal); }; -class Q_QML_PRIVATE_EXPORT QQmlRectValueType : public QQmlValueTypeBase +struct QQmlRectValueType { + QRect v; Q_PROPERTY(int x READ x WRITE setX FINAL) Q_PROPERTY(int y READ y WRITE setY FINAL) Q_PROPERTY(int width READ width WRITE setWidth FINAL) Q_PROPERTY(int height READ height WRITE setHeight FINAL) - Q_OBJECT + Q_GADGET public: - QQmlRectValueType(QObject *parent = 0); - - virtual QString toString() const; - int x() const; int y() const; void setX(int); @@ -269,9 +208,10 @@ public: void setHeight(int); }; -class Q_QML_PRIVATE_EXPORT QQmlEasingValueType : public QQmlValueTypeBase +struct QQmlEasingValueType { - Q_OBJECT + QEasingCurve v; + Q_GADGET Q_ENUMS(Type) Q_PROPERTY(QQmlEasingValueType::Type type READ type WRITE setType FINAL) @@ -307,10 +247,6 @@ public: Bezier = QEasingCurve::BezierSpline }; - QQmlEasingValueType(QObject *parent = 0); - - virtual QString toString() const; - Type type() const; qreal amplitude() const; qreal overshoot() const; diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp index ede55d0..d2fccb5 100644 --- a/src/qml/qml/qqmlvaluetypewrapper.cpp +++ b/src/qml/qml/qqmlvaluetypewrapper.cpp @@ -120,7 +120,10 @@ static bool readReferenceValue(const QmlValueTypeReference *reference) // We need to modify this reference to the updated value type, if // possible, or return false if it is not a value type. if (QQmlValueTypeFactory::isValueType(variantReferenceType)) { - reference->d()->type = QQmlValueTypeFactory::valueType(variantReferenceType); + QQmlValueType *vt = 0; + if (const QMetaObject *mo = QQmlValueTypeFactory::metaObjectForMetaType(variantReferenceType)) + vt = new QQmlValueType(variantReferenceType, mo); + reference->d()->type.reset(vt); if (!reference->d()->type) { return false; } @@ -147,7 +150,7 @@ void QmlValueTypeWrapper::initProto(ExecutionEngine *v4) v4->qmlExtensions()->valueTypeWrapperPrototype = o->d(); } -ReturnedValue QmlValueTypeWrapper::create(QV8Engine *v8, QObject *object, int property, QQmlValueType *type) +ReturnedValue QmlValueTypeWrapper::create(QV8Engine *v8, QObject *object, int property, const QMetaObject *metaObject, int typeId) { ExecutionEngine *v4 = QV8Engine::getV4(v8); Scope scope(v4); @@ -156,11 +159,11 @@ ReturnedValue QmlValueTypeWrapper::create(QV8Engine *v8, QObject *object, int pr Scoped r(scope, v4->memoryManager->alloc(v8)); ScopedObject proto(scope, v4->qmlExtensions()->valueTypeWrapperPrototype); r->setPrototype(proto); - r->d()->type = type; r->d()->object = object; r->d()->property = property; + r->d()->type.reset(new QQmlValueType(typeId, metaObject)); r->d()->object = object; r->d()->property = property; return r->asReturnedValue(); } -ReturnedValue QmlValueTypeWrapper::create(QV8Engine *v8, const QVariant &value, QQmlValueType *type) +ReturnedValue QmlValueTypeWrapper::create(QV8Engine *v8, const QVariant &value, const QMetaObject *metaObject, int typeId) { ExecutionEngine *v4 = QV8Engine::getV4(v8); Scope scope(v4); @@ -169,7 +172,7 @@ ReturnedValue QmlValueTypeWrapper::create(QV8Engine *v8, const QVariant &value, Scoped r(scope, v4->memoryManager->alloc(v8)); ScopedObject proto(scope, v4->qmlExtensions()->valueTypeWrapperPrototype); r->setPrototype(proto); - r->d()->type = type; r->d()->value = value; + r->d()->type.reset(new QQmlValueType(typeId, metaObject)); r->d()->value = value; return r->asReturnedValue(); } @@ -220,11 +223,11 @@ PropertyAttributes QmlValueTypeWrapper::query(const Managed *m, String *name) QQmlPropertyData local; QQmlPropertyData *result = 0; { - QQmlData *ddata = QQmlData::get(r->d()->type, false); + QQmlData *ddata = QQmlData::get(r->d()->type.data(), false); if (ddata && ddata->propertyCache) result = ddata->propertyCache->property(name, 0, 0); else - result = QQmlPropertyCache::property(r->d()->v8->engine(), r->d()->type, name, 0, local); + result = QQmlPropertyCache::property(r->d()->v8->engine(), r->d()->type.data(), name, 0, local); } return result ? Attr_Data : Attr_Invalid; } @@ -278,6 +281,10 @@ ReturnedValue QmlValueTypeWrapper::get(Managed *m, String *name, bool *hasProper QmlValueTypeWrapper *r = static_cast(m); QV4::ExecutionEngine *v4 = m->engine(); + // ### Remove this once we can do proper this calls. + if (name == v4->id_toString) + return Object::get(m, name, hasProperty); + // Note: readReferenceValue() can change the reference->type. if (r->d()->objectType == Heap::QmlValueTypeWrapper::Reference) { QmlValueTypeReference *reference = static_cast(r); @@ -296,11 +303,11 @@ ReturnedValue QmlValueTypeWrapper::get(Managed *m, String *name, bool *hasProper QQmlPropertyData local; QQmlPropertyData *result = 0; { - QQmlData *ddata = QQmlData::get(r->d()->type, false); + QQmlData *ddata = QQmlData::get(r->d()->type.data(), false); if (ddata && ddata->propertyCache) result = ddata->propertyCache->property(name, 0, 0); else - result = QQmlPropertyCache::property(r->d()->v8->engine(), r->d()->type, name, 0, local); + result = QQmlPropertyCache::property(r->d()->v8->engine(), r->d()->type.data(), name, 0, local); } if (!result) @@ -313,14 +320,14 @@ ReturnedValue QmlValueTypeWrapper::get(Managed *m, String *name, bool *hasProper // calling a Q_INVOKABLE function of a value type Scope scope(v4); ScopedContext c(scope, v4->rootContext()); - return QV4::QObjectMethod::create(c, r->d()->type, result->coreIndex); + return QV4::QObjectMethod::create(c, r->d()->type.data(), result->coreIndex); } #define VALUE_TYPE_LOAD(metatype, cpptype, constructor) \ if (result->propType == metatype) { \ cpptype v; \ void *args[] = { &v, 0 }; \ - r->d()->type->qt_metacall(QMetaObject::ReadProperty, result->coreIndex, args); \ + QMetaObject::metacall(r->d()->type.data(), QMetaObject::ReadProperty, result->coreIndex, args); \ return constructor(v); \ } @@ -332,7 +339,7 @@ ReturnedValue QmlValueTypeWrapper::get(Managed *m, String *name, bool *hasProper QVariant v(result->propType, (void *)0); void *args[] = { v.data(), 0 }; - r->d()->type->qt_metacall(QMetaObject::ReadProperty, result->coreIndex, args); + QMetaObject::metacall(r->d()->type.data(), QMetaObject::ReadProperty, result->coreIndex, args); return r->d()->v8->fromVariant(v); #undef VALUE_TYPE_ACCESSOR } @@ -402,7 +409,7 @@ void QmlValueTypeWrapper::put(Managed *m, String *name, const ValueRef value) if (p.isEnumType() && (QMetaType::Type)v.type() == QMetaType::Double) v = v.toInt(); - p.write(reference->d()->type, v); + p.write(reference->d()->type.data(), v); if (writebackProperty.userType() == QMetaType::QVariant) { QVariant variantReferenceValue = r->d()->type->value(); @@ -425,7 +432,7 @@ void QmlValueTypeWrapper::put(Managed *m, String *name, const ValueRef value) r->d()->type->setValue(copy->d()->value); QMetaProperty p = r->d()->type->metaObject()->property(index); - p.write(r->d()->type, v); + p.write(r->d()->type.data(), v); copy->d()->value = r->d()->type->value(); } } diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h index d15a4b0..4946c13 100644 --- a/src/qml/qml/qqmlvaluetypewrapper_p.h +++ b/src/qml/qml/qqmlvaluetypewrapper_p.h @@ -65,7 +65,7 @@ struct QmlValueTypeWrapper : Object { QmlValueTypeWrapper(QV8Engine *engine, ObjectType type); QV8Engine *v8; ObjectType objectType; - mutable QQmlValueType *type; + mutable QScopedPointer type; }; } @@ -77,8 +77,8 @@ struct Q_QML_EXPORT QmlValueTypeWrapper : Object public: - static ReturnedValue create(QV8Engine *v8, QObject *, int, QQmlValueType *); - static ReturnedValue create(QV8Engine *v8, const QVariant &, QQmlValueType *); + static ReturnedValue create(QV8Engine *v8, QObject *, int, const QMetaObject *metaObject, int typeId); + static ReturnedValue create(QV8Engine *v8, const QVariant &, const QMetaObject *metaObject, int typeId); QVariant toVariant() const; bool isEqual(const QVariant& value); diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp index 5e9e20b..ee124ae 100644 --- a/src/qml/qml/v8/qv8engine.cpp +++ b/src/qml/qml/v8/qv8engine.cpp @@ -413,8 +413,8 @@ QV4::ReturnedValue QV8Engine::fromVariant(const QVariant &variant) break; } - if (QQmlValueType *vt = QQmlValueTypeFactory::valueType(type)) - return QV4::QmlValueTypeWrapper::create(this, variant, vt); + if (const QMetaObject *vtmo = QQmlValueTypeFactory::metaObjectForMetaType(type)) + return QV4::QmlValueTypeWrapper::create(this, variant, vtmo, type); } else { QV4::Scope scope(m_v4Engine); if (type == qMetaTypeId()) { @@ -454,8 +454,8 @@ QV4::ReturnedValue QV8Engine::fromVariant(const QVariant &variant) if (succeeded) return retn.asReturnedValue(); - if (QQmlValueType *vt = QQmlValueTypeFactory::valueType(type)) - return QV4::QmlValueTypeWrapper::create(this, variant, vt); + if (const QMetaObject *vtmo = QQmlValueTypeFactory::metaObjectForMetaType(type)) + return QV4::QmlValueTypeWrapper::create(this, variant, vtmo, type); } // XXX TODO: To be compatible, we still need to handle: diff --git a/src/quick/util/qquickglobal.cpp b/src/quick/util/qquickglobal.cpp index b507b47..e3250a6 100644 --- a/src/quick/util/qquickglobal.cpp +++ b/src/quick/util/qquickglobal.cpp @@ -364,35 +364,28 @@ public: return QMatrix4x4(matVals); } - template - bool typedCreate(QQmlValueType *&v) - { - v = new T; - return true; - } - - bool create(int type, QQmlValueType *&v) + const QMetaObject *getMetaObjectForMetaType(int type) { switch (type) { case QMetaType::QColor: - return typedCreate(v); + return &QQuickColorValueType::staticMetaObject; case QMetaType::QFont: - return typedCreate(v); + return &QQuickFontValueType::staticMetaObject; case QMetaType::QVector2D: - return typedCreate(v); + return &QQuickVector2DValueType::staticMetaObject; case QMetaType::QVector3D: - return typedCreate(v); + return &QQuickVector3DValueType::staticMetaObject; case QMetaType::QVector4D: - return typedCreate(v); + return &QQuickVector4DValueType::staticMetaObject; case QMetaType::QQuaternion: - return typedCreate(v); + return &QQuickQuaternionValueType::staticMetaObject; case QMetaType::QMatrix4x4: - return typedCreate(v); + return &QQuickMatrix4x4ValueType::staticMetaObject; default: break; } - return false; + return 0; } template diff --git a/src/quick/util/qquickvaluetypes.cpp b/src/quick/util/qquickvaluetypes.cpp index 37a5ba3..2e4fec0 100644 --- a/src/quick/util/qquickvaluetypes.cpp +++ b/src/quick/util/qquickvaluetypes.cpp @@ -48,11 +48,6 @@ namespace QQuickValueTypes { } } -QQuickColorValueType::QQuickColorValueType(QObject *parent) - : QQmlValueTypeBase(QMetaType::QColor, parent) -{ -} - QString QQuickColorValueType::toString() const { // to maintain behaviour with QtQuick 1.0, we just output normal toString() value. @@ -99,26 +94,11 @@ void QQuickColorValueType::setA(qreal a) v.setAlphaF(a); } - -QQuickVector2DValueType::QQuickVector2DValueType(QObject *parent) - : QQmlValueTypeBase(QMetaType::QVector2D, parent) -{ -} - QString QQuickVector2DValueType::toString() const { return QString(QLatin1String("QVector2D(%1, %2)")).arg(v.x()).arg(v.y()); } -bool QQuickVector2DValueType::isEqual(const QVariant &other) const -{ - if (other.userType() != QMetaType::QVector2D) - return false; - - QVector2D otherVector = other.value(); - return (v == otherVector); -} - qreal QQuickVector2DValueType::x() const { return v.x(); @@ -199,26 +179,11 @@ bool QQuickVector2DValueType::fuzzyEquals(const QVector2D &vec) const return qFuzzyCompare(v, vec); } - -QQuickVector3DValueType::QQuickVector3DValueType(QObject *parent) - : QQmlValueTypeBase(QMetaType::QVector3D, parent) -{ -} - QString QQuickVector3DValueType::toString() const { return QString(QLatin1String("QVector3D(%1, %2, %3)")).arg(v.x()).arg(v.y()).arg(v.z()); } -bool QQuickVector3DValueType::isEqual(const QVariant &other) const -{ - if (other.userType() != QMetaType::QVector3D) - return false; - - QVector3D otherVector = other.value(); - return (v == otherVector); -} - qreal QQuickVector3DValueType::x() const { return v.x(); @@ -321,26 +286,11 @@ bool QQuickVector3DValueType::fuzzyEquals(const QVector3D &vec) const return qFuzzyCompare(v, vec); } - -QQuickVector4DValueType::QQuickVector4DValueType(QObject *parent) - : QQmlValueTypeBase(QMetaType::QVector4D, parent) -{ -} - QString QQuickVector4DValueType::toString() const { return QString(QLatin1String("QVector4D(%1, %2, %3, %4)")).arg(v.x()).arg(v.y()).arg(v.z()).arg(v.w()); } -bool QQuickVector4DValueType::isEqual(const QVariant &other) const -{ - if (other.userType() != QMetaType::QVector4D) - return false; - - QVector4D otherVector = other.value(); - return (v == otherVector); -} - qreal QQuickVector4DValueType::x() const { return v.x(); @@ -450,11 +400,6 @@ bool QQuickVector4DValueType::fuzzyEquals(const QVector4D &vec) const return qFuzzyCompare(v, vec); } -QQuickQuaternionValueType::QQuickQuaternionValueType(QObject *parent) - : QQmlValueTypeBase(QMetaType::QQuaternion, parent) -{ -} - QString QQuickQuaternionValueType::toString() const { return QString(QLatin1String("QQuaternion(%1, %2, %3, %4)")).arg(v.scalar()).arg(v.x()).arg(v.y()).arg(v.z()); @@ -500,12 +445,6 @@ void QQuickQuaternionValueType::setZ(qreal z) v.setZ(z); } - -QQuickMatrix4x4ValueType::QQuickMatrix4x4ValueType(QObject *parent) - : QQmlValueTypeBase(QMetaType::QMatrix4x4, parent) -{ -} - QMatrix4x4 QQuickMatrix4x4ValueType::times(const QMatrix4x4 &m) const { return v * m; @@ -579,30 +518,6 @@ bool QQuickMatrix4x4ValueType::fuzzyEquals(const QMatrix4x4 &m) const return qFuzzyCompare(v, m); } -QString QQuickMatrix4x4ValueType::toString() const -{ - return QString(QLatin1String("QMatrix4x4(%1, %2, %3, %4, %5, %6, %7, %8, %9, %10, %11, %12, %13, %14, %15, %16)")) - .arg(v(0, 0)).arg(v(0, 1)).arg(v(0, 2)).arg(v(0, 3)) - .arg(v(1, 0)).arg(v(1, 1)).arg(v(1, 2)).arg(v(1, 3)) - .arg(v(2, 0)).arg(v(2, 1)).arg(v(2, 2)).arg(v(2, 3)) - .arg(v(3, 0)).arg(v(3, 1)).arg(v(3, 2)).arg(v(3, 3)); -} - -bool QQuickMatrix4x4ValueType::isEqual(const QVariant &other) const -{ - if (other.userType() != qMetaTypeId()) - return false; - - QMatrix4x4 otherMatrix = other.value(); - return (v == otherMatrix); - -} - -QQuickFontValueType::QQuickFontValueType(QObject *parent) - : QQmlValueTypeBase(QMetaType::QFont, parent) -{ -} - QString QQuickFontValueType::toString() const { return QString(QLatin1String("QFont(%1)")).arg(v.toString()); @@ -681,9 +596,7 @@ void QQuickFontValueType::setStrikeout(bool b) qreal QQuickFontValueType::pointSize() const { if (v.pointSizeF() == -1) { - if (dpi.isNull) - dpi = qt_defaultDpi(); - return v.pixelSize() * qreal(72.) / qreal(dpi); + return v.pixelSize() * qreal(72.) / qreal(qt_defaultDpi()); } return v.pointSizeF(); } @@ -703,9 +616,7 @@ void QQuickFontValueType::setPointSize(qreal size) int QQuickFontValueType::pixelSize() const { if (v.pixelSize() == -1) { - if (dpi.isNull) - dpi = qt_defaultDpi(); - return (v.pointSizeF() * dpi) / qreal(72.); + return (v.pointSizeF() * qt_defaultDpi()) / qreal(72.); } return v.pixelSize(); } diff --git a/src/quick/util/qquickvaluetypes_p.h b/src/quick/util/qquickvaluetypes_p.h index 7c1cdd1..7bd6d71 100644 --- a/src/quick/util/qquickvaluetypes_p.h +++ b/src/quick/util/qquickvaluetypes_p.h @@ -54,17 +54,16 @@ void registerValueTypes(); } -class Q_AUTOTEST_EXPORT QQuickColorValueType : public QQmlValueTypeBase +class QQuickColorValueType { + QColor v; Q_PROPERTY(qreal r READ r WRITE setR FINAL) Q_PROPERTY(qreal g READ g WRITE setG FINAL) Q_PROPERTY(qreal b READ b WRITE setB FINAL) Q_PROPERTY(qreal a READ a WRITE setA FINAL) - Q_OBJECT + Q_GADGET public: - QQuickColorValueType(QObject *parent = 0); - - virtual QString toString() const; + Q_INVOKABLE QString toString() const; qreal r() const; qreal g() const; @@ -76,16 +75,14 @@ public: void setA(qreal); }; -class Q_AUTOTEST_EXPORT QQuickVector2DValueType : public QQmlValueTypeBase +class QQuickVector2DValueType { + QVector2D v; Q_PROPERTY(qreal x READ x WRITE setX FINAL) Q_PROPERTY(qreal y READ y WRITE setY FINAL) - Q_OBJECT + Q_GADGET public: - QQuickVector2DValueType(QObject *parent = 0); - - virtual QString toString() const; - virtual bool isEqual(const QVariant &other) const; + Q_INVOKABLE QString toString() const; qreal x() const; qreal y() const; @@ -105,17 +102,15 @@ public: Q_INVOKABLE bool fuzzyEquals(const QVector2D &vec) const; }; -class Q_AUTOTEST_EXPORT QQuickVector3DValueType : public QQmlValueTypeBase +class QQuickVector3DValueType { + QVector3D v; Q_PROPERTY(qreal x READ x WRITE setX FINAL) Q_PROPERTY(qreal y READ y WRITE setY FINAL) Q_PROPERTY(qreal z READ z WRITE setZ FINAL) - Q_OBJECT + Q_GADGET public: - QQuickVector3DValueType(QObject *parent = 0); - - virtual QString toString() const; - virtual bool isEqual(const QVariant &other) const; + Q_INVOKABLE QString toString() const; qreal x() const; qreal y() const; @@ -139,18 +134,16 @@ public: Q_INVOKABLE bool fuzzyEquals(const QVector3D &vec) const; }; -class Q_AUTOTEST_EXPORT QQuickVector4DValueType : public QQmlValueTypeBase +class QQuickVector4DValueType { + QVector4D v; Q_PROPERTY(qreal x READ x WRITE setX FINAL) Q_PROPERTY(qreal y READ y WRITE setY FINAL) Q_PROPERTY(qreal z READ z WRITE setZ FINAL) Q_PROPERTY(qreal w READ w WRITE setW FINAL) - Q_OBJECT + Q_GADGET public: - QQuickVector4DValueType(QObject *parent = 0); - - virtual QString toString() const; - virtual bool isEqual(const QVariant &other) const; + Q_INVOKABLE QString toString() const; qreal x() const; qreal y() const; @@ -175,17 +168,16 @@ public: Q_INVOKABLE bool fuzzyEquals(const QVector4D &vec) const; }; -class Q_AUTOTEST_EXPORT QQuickQuaternionValueType : public QQmlValueTypeBase +class QQuickQuaternionValueType { + QQuaternion v; Q_PROPERTY(qreal scalar READ scalar WRITE setScalar) Q_PROPERTY(qreal x READ x WRITE setX) Q_PROPERTY(qreal y READ y WRITE setY) Q_PROPERTY(qreal z READ z WRITE setZ) - Q_OBJECT + Q_GADGET public: - QQuickQuaternionValueType(QObject *parent = 0); - - virtual QString toString() const; + Q_INVOKABLE QString toString() const; qreal scalar() const; qreal x() const; @@ -197,8 +189,9 @@ public: void setZ(qreal); }; -class Q_AUTOTEST_EXPORT QQuickMatrix4x4ValueType : public QQmlValueTypeBase +class QQuickMatrix4x4ValueType { + QMatrix4x4 v; Q_PROPERTY(qreal m11 READ m11 WRITE setM11 FINAL) Q_PROPERTY(qreal m12 READ m12 WRITE setM12 FINAL) Q_PROPERTY(qreal m13 READ m13 WRITE setM13 FINAL) @@ -215,13 +208,8 @@ class Q_AUTOTEST_EXPORT QQuickMatrix4x4ValueType : public QQmlValueTypeBase +class QQuickFontValueType { - Q_OBJECT + QFont v; + Q_GADGET Q_ENUMS(FontWeight) Q_ENUMS(Capitalization) @@ -305,9 +294,7 @@ public: SmallCaps = QFont::SmallCaps, Capitalize = QFont::Capitalize }; - QQuickFontValueType(QObject *parent = 0); - - virtual QString toString() const; + Q_INVOKABLE QString toString() const; QString family() const; void setFamily(const QString &); @@ -344,9 +331,6 @@ public: qreal wordSpacing() const; void setWordSpacing(qreal spacing); - -private: - mutable QQmlNullableValue dpi; }; QT_END_NAMESPACE diff --git a/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp b/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp index fdbcc0d..cdbad96 100644 --- a/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp +++ b/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp @@ -199,6 +199,8 @@ public: bool operator==(const TestValue &other) const { return (m_p1 == other.m_p1) && (m_p2 == other.m_p2); } bool operator!=(const TestValue &other) const { return !operator==(other); } + bool operator<(const TestValue &other) const { if (m_p1 < other.m_p1) return true; return m_p2 < other.m_p2; } + private: int m_p1; double m_p2; @@ -210,16 +212,14 @@ Q_DECLARE_METATYPE(TestValue); namespace { -class TestValueType : public QQmlValueTypeBase +class TestValueType { - Q_OBJECT + TestValue v; + Q_GADGET Q_PROPERTY(int property1 READ property1 WRITE setProperty1) Q_PROPERTY(double property2 READ property2 WRITE setProperty2) public: - TestValueType(QObject *parent = 0) : QQmlValueTypeBase(qMetaTypeId(), parent) {} - - virtual QString toString() const { return QString::number(property1()) + QLatin1Char(',') + QString::number(property2()); } - virtual bool isEqual(const QVariant &other) const { return (other.userType() == qMetaTypeId()) && (v == other.value()); } + Q_INVOKABLE QString toString() const { return QString::number(property1()) + QLatin1Char(',') + QString::number(property2()); } int property1() const { return v.property1(); } void setProperty1(int p1) { v.setProperty1(p1); } @@ -231,14 +231,12 @@ public: class TestValueTypeProvider : public QQmlValueTypeProvider { public: - bool create(int type, QQmlValueType *&v) + const QMetaObject *getMetaObjectForMetaType(int type) { - if (type == qMetaTypeId()) { - v = new TestValueType; - return true; - } + if (type == qMetaTypeId()) + return &TestValueType::staticMetaObject; - return false; + return 0; } }; @@ -279,6 +277,7 @@ void tst_qqmlvaluetypeproviders::userType() Q_ASSERT(qMetaTypeId() >= QMetaType::User); qRegisterMetaType(); + QMetaType::registerComparators(); qmlRegisterType("Test", 1, 0, "TestValueExporter"); TestValueExporter exporter; diff --git a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp index ce2723b..e3703ea 100644 --- a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp +++ b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp @@ -79,7 +79,6 @@ private slots: void deletedObject(); void bindingVariantCopy(); void scriptVariantCopy(); - void cppClasses(); void enums(); void conflictingBindings(); void returnValues(); @@ -1166,26 +1165,6 @@ void tst_qqmlvaluetypes::scriptVariantCopy() delete object; } - -// Test that the value type classes can be used manually -void tst_qqmlvaluetypes::cppClasses() -{ - CPP_TEST(QQmlPointValueType, QPoint(19, 33)); - CPP_TEST(QQmlPointFValueType, QPointF(33.6, -23)); - CPP_TEST(QQmlSizeValueType, QSize(-100, 18)); - CPP_TEST(QQmlSizeFValueType, QSizeF(-100.7, 18.2)); - CPP_TEST(QQmlRectValueType, QRect(13, 39, 10928, 88)); - CPP_TEST(QQmlRectFValueType, QRectF(88.2, -90.1, 103.2, 118)); - CPP_TEST(QQuickVector2DValueType, QVector2D(19.7f, 1002)); - CPP_TEST(QQuickVector3DValueType, QVector3D(18.2f, 19.7f, 1002)); - CPP_TEST(QQuickVector4DValueType, QVector4D(18.2f, 19.7f, 1002, 54)); - CPP_TEST(QQuickQuaternionValueType, QQuaternion(18.2f, 19.7f, 1002, 54)); - CPP_TEST(QQuickMatrix4x4ValueType, - QMatrix4x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)); - CPP_TEST(QQuickFontValueType, QFont("Helvetica")); - -} - void tst_qqmlvaluetypes::enums() { { -- 2.7.4