diff options
-rw-r--r-- | src/qml/compiler/qqmlirbuilder.cpp | 4 | ||||
-rw-r--r-- | src/qml/compiler/qqmltypecompiler.cpp | 18 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4qobjectwrapper.cpp | 35 | ||||
-rw-r--r-- | src/qml/qml/qqmlglobal.cpp | 10 | ||||
-rw-r--r-- | src/qml/qml/qqmlglobal_p.h | 6 | ||||
-rw-r--r-- | src/qml/qml/qqmlproperty.cpp | 20 | ||||
-rw-r--r-- | src/qml/qml/qqmlvaluetype.cpp | 198 | ||||
-rw-r--r-- | src/qml/qml/qqmlvaluetype_p.h | 158 | ||||
-rw-r--r-- | src/qml/qml/qqmlvaluetypewrapper.cpp | 35 | ||||
-rw-r--r-- | src/qml/qml/qqmlvaluetypewrapper_p.h | 6 | ||||
-rw-r--r-- | src/qml/qml/v8/qv8engine.cpp | 8 | ||||
-rw-r--r-- | src/quick/util/qquickglobal.cpp | 25 | ||||
-rw-r--r-- | src/quick/util/qquickvaluetypes.cpp | 93 | ||||
-rw-r--r-- | src/quick/util/qquickvaluetypes_p.h | 70 | ||||
-rw-r--r-- | tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp | 23 | ||||
-rw-r--r-- | tests/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 339278fbe8..07ea2a6fff 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 ada848f31d..7f399f0879 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 daaa0c16f1..c2b3b44bba 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<QQmlValueType*>(object); - QVariant valueTypeValue; - if (valueTypeObject) - valueTypeValue = valueTypeObject->value(); - // Convert all arguments. QVarLengthArray<CallArgument, 9> 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<QQmlValueType*>(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 492836ae03..57c0993d00 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 1d0bf59670..2832d0338d 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 635e4d4a54..0ee8f94a66 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 f73b50ad46..20f3027e4c 100644 --- a/src/qml/qml/qqmlvaluetype.cpp +++ b/src/qml/qml/qqmlvaluetype.cpp @@ -36,6 +36,7 @@ #include <private/qqmlglobal_p.h> #include <QtCore/qdebug.h> +#include <private/qmetaobjectbuilder_p.h> 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<int, QQmlValueType *>::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<QQmlEasingValueType>(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<QMetaObject*>(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<QObject*>(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<QPointF>(QMetaType::QPointF, parent) +int QQmlValueType::metaCall(QObject *, QMetaObject::Call type, int _id, void **argv) { + d.static_metacall(reinterpret_cast<QObject*>(gadgetPtr), type, _id, argv); + return _id; } QString QQmlPointFValueType::toString() const @@ -203,16 +295,6 @@ void QQmlPointFValueType::setY(qreal y) } -QQmlPointValueType::QQmlPointValueType(QObject *parent) - : QQmlValueTypeBase<QPoint>(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<QSizeF>(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<QSize>(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<QRectF>(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<QRect>(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<QEasingCurve>(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 5a6bcdd003..2f6a192f77 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 <typename T> -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<T>(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<QPointF> +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<QPoint> +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<QSizeF> +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<QSize> +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<QRectF> +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<QRect> +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<QEasingCurve> +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 ede55d033f..d2fccb5273 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<QmlValueTypeReference> r(scope, v4->memoryManager->alloc<QmlValueTypeReference>(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<QmlValueTypeCopy> r(scope, v4->memoryManager->alloc<QmlValueTypeCopy>(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<QmlValueTypeWrapper *>(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<QmlValueTypeReference *>(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 d15a4b0cef..4946c13e42 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<QQmlValueType> 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 5e9e20b416..ee124aeed0 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<QQmlListReference>()) { @@ -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 b507b47e6b..e3250a6309 100644 --- a/src/quick/util/qquickglobal.cpp +++ b/src/quick/util/qquickglobal.cpp @@ -364,35 +364,28 @@ public: return QMatrix4x4(matVals); } - template<typename T> - 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<QQuickColorValueType>(v); + return &QQuickColorValueType::staticMetaObject; case QMetaType::QFont: - return typedCreate<QQuickFontValueType>(v); + return &QQuickFontValueType::staticMetaObject; case QMetaType::QVector2D: - return typedCreate<QQuickVector2DValueType>(v); + return &QQuickVector2DValueType::staticMetaObject; case QMetaType::QVector3D: - return typedCreate<QQuickVector3DValueType>(v); + return &QQuickVector3DValueType::staticMetaObject; case QMetaType::QVector4D: - return typedCreate<QQuickVector4DValueType>(v); + return &QQuickVector4DValueType::staticMetaObject; case QMetaType::QQuaternion: - return typedCreate<QQuickQuaternionValueType>(v); + return &QQuickQuaternionValueType::staticMetaObject; case QMetaType::QMatrix4x4: - return typedCreate<QQuickMatrix4x4ValueType>(v); + return &QQuickMatrix4x4ValueType::staticMetaObject; default: break; } - return false; + return 0; } template<typename T> diff --git a/src/quick/util/qquickvaluetypes.cpp b/src/quick/util/qquickvaluetypes.cpp index 37a5ba307f..2e4fec0599 100644 --- a/src/quick/util/qquickvaluetypes.cpp +++ b/src/quick/util/qquickvaluetypes.cpp @@ -48,11 +48,6 @@ namespace QQuickValueTypes { } } -QQuickColorValueType::QQuickColorValueType(QObject *parent) - : QQmlValueTypeBase<QColor>(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<QVector2D>(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<QVector2D>(); - 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<QVector3D>(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<QVector3D>(); - 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<QVector4D>(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<QVector4D>(); - 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<QQuaternion>(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<QMatrix4x4>(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<QMatrix4x4>()) - return false; - - QMatrix4x4 otherMatrix = other.value<QMatrix4x4>(); - return (v == otherMatrix); - -} - -QQuickFontValueType::QQuickFontValueType(QObject *parent) - : QQmlValueTypeBase<QFont>(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 7c1cdd1148..7bd6d71dce 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<QColor> +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<QVector2D> +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<QVector3D> +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<QVector4D> +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<QQuaternion> +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<QMatrix4x4> +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<QMat Q_PROPERTY(qreal m42 READ m42 WRITE setM42 FINAL) Q_PROPERTY(qreal m43 READ m43 WRITE setM43 FINAL) Q_PROPERTY(qreal m44 READ m44 WRITE setM44 FINAL) - Q_OBJECT + Q_GADGET public: - QQuickMatrix4x4ValueType(QObject *parent = 0); - - virtual QString toString() const; - virtual bool isEqual(const QVariant &other) const; - qreal m11() const { return v(0, 0); } qreal m12() const { return v(0, 1); } qreal m13() const { return v(0, 2); } @@ -274,9 +262,10 @@ public: Q_INVOKABLE bool fuzzyEquals(const QMatrix4x4 &m) const; }; -class Q_AUTOTEST_EXPORT QQuickFontValueType : public QQmlValueTypeBase<QFont> +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<int> dpi; }; QT_END_NAMESPACE diff --git a/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp b/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp index fdbcc0dbf2..cdbad96b2f 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<TestValue> +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<TestValue>(qMetaTypeId<TestValue>(), parent) {} - - virtual QString toString() const { return QString::number(property1()) + QLatin1Char(',') + QString::number(property2()); } - virtual bool isEqual(const QVariant &other) const { return (other.userType() == qMetaTypeId<TestValue>()) && (v == other.value<TestValue>()); } + 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<TestValue>()) { - v = new TestValueType; - return true; - } + if (type == qMetaTypeId<TestValue>()) + return &TestValueType::staticMetaObject; - return false; + return 0; } }; @@ -279,6 +277,7 @@ void tst_qqmlvaluetypeproviders::userType() Q_ASSERT(qMetaTypeId<TestValue>() >= QMetaType::User); qRegisterMetaType<TestValue>(); + QMetaType::registerComparators<TestValue>(); qmlRegisterType<TestValueExporter>("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 ce2723bbf9..e3703eac00 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() { { |