From f5cb65b35e076facbce45e896902a34da7036135 Mon Sep 17 00:00:00 2001 From: Chris Adams Date: Tue, 26 Jun 2012 18:02:35 +1000 Subject: Fix broken value-type support by allowing property definition In QtQuick 1.x the "variant" property type was supported, which could be used to allow value type properties to be defined in QML. In QtQuick 2.0, we have deprecated the "variant" property, but its replacement ("var") is not suited for defining lightweight C++ type values (such as QColor, QFont, QRectF, QVector3D etc). This commit allows those QML basic types to be used in QML once more, by supporting them in the property definition syntax. Note that since some value types are provided by QtQuick and others are provided by QtQml, if a client imports only QtQml they can define but not use properties of certain types (eg, font). Task-number: QTBUG-21034 Task-number: QTBUG-18217 Change-Id: Ia951a8522f223408d27293bb96c276281a710277 Reviewed-by: Matthew Vogt --- src/qml/qml/v8/qqmlbuiltinfunctions.cpp | 102 +++++++++++++++++++++++++++++++- src/qml/qml/v8/qqmlbuiltinfunctions_p.h | 4 ++ src/qml/qml/v8/qv8engine.cpp | 6 ++ src/qml/qml/v8/qv8valuetypewrapper.cpp | 9 +++ src/qml/qml/v8/qv8valuetypewrapper_p.h | 1 + 5 files changed, 121 insertions(+), 1 deletion(-) (limited to 'src/qml/qml/v8') diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index deaf5f5c80..5abc7cf7bb 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -494,6 +494,23 @@ v8::Handle size(const v8::Arguments &args) return V8ENGINE()->fromVariant(QVariant::fromValue(QSizeF(w, h))); } +/*! +\qmlmethod Qt::vector2d(real x, real y) +Returns a Vector2D with the specified \c x and \c y. +*/ +v8::Handle vector2d(const v8::Arguments &args) +{ + if (args.Length() != 2) + V8THROW_ERROR("Qt.vector2d(): Invalid arguments"); + + float xy[3]; + xy[0] = args[0]->ToNumber()->Value(); + xy[1] = args[1]->ToNumber()->Value(); + + const void *params[] = { xy }; + return V8ENGINE()->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector2D, 1, params)); +} + /*! \qmlmethod Qt::vector3d(real x, real y, real z) Returns a Vector3D with the specified \c x, \c y and \c z. @@ -501,7 +518,7 @@ Returns a Vector3D with the specified \c x, \c y and \c z. v8::Handle vector3d(const v8::Arguments &args) { if (args.Length() != 3) - V8THROW_ERROR("Qt.vector(): Invalid arguments"); + V8THROW_ERROR("Qt.vector3d(): Invalid arguments"); float xyz[3]; xyz[0] = args[0]->ToNumber()->Value(); @@ -531,6 +548,89 @@ v8::Handle vector4d(const v8::Arguments &args) return V8ENGINE()->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector4D, 1, params)); } +/*! +\qmlmethod Qt::quaternion(real scalar, real x, real y, real z) +Returns a Quaternion with the specified \c scalar, \c x, \c y, and \c z. +*/ +v8::Handle quaternion(const v8::Arguments &args) +{ + if (args.Length() != 4) + V8THROW_ERROR("Qt.quaternion(): Invalid arguments"); + + double sxyz[4]; + sxyz[0] = args[0]->ToNumber()->Value(); + sxyz[1] = args[1]->ToNumber()->Value(); + sxyz[2] = args[2]->ToNumber()->Value(); + sxyz[3] = args[3]->ToNumber()->Value(); + + const void *params[] = { sxyz }; + return V8ENGINE()->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QQuaternion, 1, params)); +} + +/*! +\qmlmethod Qt::font(object fontSpecifier) +Returns a Font with the properties specified in the \c fontSpecifier object +or the nearest matching font. The \c fontSpecifier object should contain +key-value pairs where valid keys are the \l{fontbasictypedocs}{font} type's +subproperty names, and the values are valid values for each subproperty. +Invalid keys will be ignored. +*/ +v8::Handle font(const v8::Arguments &args) +{ + if (args.Length() != 1 || !args[0]->IsObject()) + V8THROW_ERROR("Qt.font(): Invalid arguments"); + + v8::Handle obj = args[0]->ToObject(); + bool ok = false; + QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QFont, QQmlV8Handle::fromHandle(obj), V8ENGINE(), &ok); + if (!ok) + V8THROW_ERROR("Qt.font(): Invalid argument: no valid font subproperties specified"); + return V8ENGINE()->fromVariant(v); +} + +/*! +\qmlmethod Qt::matrix4x4(real m11, real m12, real m13, real m14, real m21, real m22, real m23, real m24, real m31, real m32, real m33, real m34, real m41, real m42, real m43, real m44) +Returns a Matrix4x4 with the specified values. +Alternatively, the function may be called with a single argument +where that argument is a JavaScript array which contains the sixteen +matrix values. +*/ +v8::Handle matrix4x4(const v8::Arguments &args) +{ + if (args.Length() == 1 && args[0]->IsObject()) { + v8::Handle obj = args[0]->ToObject(); + bool ok = false; + QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QMatrix4x4, QQmlV8Handle::fromHandle(obj), V8ENGINE(), &ok); + if (!ok) + V8THROW_ERROR("Qt.matrix4x4(): Invalid argument: not a valid matrix4x4 values array"); + return V8ENGINE()->fromVariant(v); + } + + if (args.Length() != 16) + V8THROW_ERROR("Qt.matrix4x4(): Invalid arguments"); + + float vals[16]; + vals[0] = args[0]->ToNumber()->Value(); + vals[1] = args[1]->ToNumber()->Value(); + vals[2] = args[2]->ToNumber()->Value(); + vals[3] = args[3]->ToNumber()->Value(); + vals[4] = args[4]->ToNumber()->Value(); + vals[5] = args[5]->ToNumber()->Value(); + vals[6] = args[6]->ToNumber()->Value(); + vals[7] = args[7]->ToNumber()->Value(); + vals[8] = args[8]->ToNumber()->Value(); + vals[9] = args[9]->ToNumber()->Value(); + vals[10] = args[10]->ToNumber()->Value(); + vals[11] = args[11]->ToNumber()->Value(); + vals[12] = args[12]->ToNumber()->Value(); + vals[13] = args[13]->ToNumber()->Value(); + vals[14] = args[14]->ToNumber()->Value(); + vals[15] = args[15]->ToNumber()->Value(); + + const void *params[] = { vals }; + return V8ENGINE()->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QMatrix4x4, 1, params)); +} + /*! \qmlmethod color Qt::lighter(color baseColor, real factor) Returns a color lighter than \c baseColor by the \c factor provided. diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h index bbfe88a292..0f43298338 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h +++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h @@ -75,11 +75,15 @@ v8::Handle consoleException(const v8::Arguments &args); v8::Handle isQtObject(const v8::Arguments &args); v8::Handle rgba(const v8::Arguments &args); v8::Handle hsla(const v8::Arguments &args); +v8::Handle font(const v8::Arguments &args); v8::Handle rect(const v8::Arguments &args); v8::Handle point(const v8::Arguments &args); v8::Handle size(const v8::Arguments &args); +v8::Handle vector2d(const v8::Arguments &args); v8::Handle vector3d(const v8::Arguments &args); v8::Handle vector4d(const v8::Arguments &args); +v8::Handle quaternion(const v8::Arguments &args); +v8::Handle matrix4x4(const v8::Arguments &args); v8::Handle lighter(const v8::Arguments &args); v8::Handle darker(const v8::Arguments &args); v8::Handle tint(const v8::Arguments &args); diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp index 732a04d437..be3c7def85 100644 --- a/src/qml/qml/v8/qv8engine.cpp +++ b/src/qml/qml/v8/qv8engine.cpp @@ -605,11 +605,17 @@ void QV8Engine::initializeGlobal(v8::Handle global) qt->Set(v8::String::New("isQtObject"), V8FUNCTION(isQtObject, this)); qt->Set(v8::String::New("rgba"), V8FUNCTION(rgba, this)); qt->Set(v8::String::New("hsla"), V8FUNCTION(hsla, this)); + qt->Set(v8::String::New("font"), V8FUNCTION(font, this)); + qt->Set(v8::String::New("rect"), V8FUNCTION(rect, this)); qt->Set(v8::String::New("point"), V8FUNCTION(point, this)); qt->Set(v8::String::New("size"), V8FUNCTION(size, this)); + + qt->Set(v8::String::New("vector2d"), V8FUNCTION(vector2d, this)); qt->Set(v8::String::New("vector3d"), V8FUNCTION(vector3d, this)); qt->Set(v8::String::New("vector4d"), V8FUNCTION(vector4d, this)); + qt->Set(v8::String::New("quaternion"), V8FUNCTION(quaternion, this)); + qt->Set(v8::String::New("matrix4x4"), V8FUNCTION(matrix4x4, this)); qt->Set(v8::String::New("formatDate"), V8FUNCTION(formatDate, this)); qt->Set(v8::String::New("formatTime"), V8FUNCTION(formatTime, this)); diff --git a/src/qml/qml/v8/qv8valuetypewrapper.cpp b/src/qml/qml/v8/qv8valuetypewrapper.cpp index cf2c13fce9..cdee5a4771 100644 --- a/src/qml/qml/v8/qv8valuetypewrapper.cpp +++ b/src/qml/qml/v8/qv8valuetypewrapper.cpp @@ -44,6 +44,7 @@ #include #include +#include QT_BEGIN_NAMESPACE @@ -148,6 +149,14 @@ v8::Local QV8ValueTypeWrapper::newValueType(const QVariant &value, Q return rv; } +QVariant QV8ValueTypeWrapper::toVariant(v8::Handle obj, int typeHint, bool *succeeded) +{ + // NOTE: obj must not be an external resource object (ie, wrapper object) + // instead, it is a normal js object which one of the value-type providers + // may know how to convert to the given type. + return QQml_valueTypeProvider()->createVariantFromJsObject(typeHint, QQmlV8Handle::fromHandle(obj), m_engine, succeeded); +} + QVariant QV8ValueTypeWrapper::toVariant(v8::Handle obj) { QV8ValueTypeResource *r = v8_resource_cast(obj); diff --git a/src/qml/qml/v8/qv8valuetypewrapper_p.h b/src/qml/qml/v8/qv8valuetypewrapper_p.h index b80d3cbbba..76b0087828 100644 --- a/src/qml/qml/v8/qv8valuetypewrapper_p.h +++ b/src/qml/qml/v8/qv8valuetypewrapper_p.h @@ -75,6 +75,7 @@ public: v8::Local newValueType(QObject *, int, QQmlValueType *); v8::Local newValueType(const QVariant &, QQmlValueType *); + QVariant toVariant(v8::Handle, int typeHint, bool *succeeded); QVariant toVariant(v8::Handle); QVariant toVariant(QV8ObjectResource *); -- cgit v1.2.3