aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml
diff options
context:
space:
mode:
authorChris Adams <christopher.adams@nokia.com>2012-07-16 16:32:49 +1000
committerQt by Nokia <qt-info@nokia.com>2012-08-09 07:58:06 +0200
commit42f9444e983b5257241c17242471ca63f208c3f6 (patch)
tree4847ae743a0e05b0ff9d3d4ab6003ea257a6c682 /src/qml/qml
parentf09517bd9c907698a05ee92ccf158a06db3340b8 (diff)
Allow invokable functions of value-type classes to be called
Previously, invokable functions of value-type classes were returned as properties. This commit fixes that bug by allowing such functions to be invoked normally. It also improves copy-value type handling. This commit also ensures that QMatrix4x4 value types are constructed with qreal values as this is the storage type used internally. Change-Id: Iab0fe4c522ed53d60154e8a8d46dda925fb9f4de Reviewed-by: Martin Jones <martin.jones@nokia.com>
Diffstat (limited to 'src/qml/qml')
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp10
-rw-r--r--src/qml/qml/v8/qv8qobjectwrapper.cpp38
-rw-r--r--src/qml/qml/v8/qv8valuetypewrapper.cpp15
3 files changed, 51 insertions, 12 deletions
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index ef1f3ea597..c8508e7ecd 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -542,7 +542,7 @@ v8::Handle<v8::Value> vector2d(const v8::Arguments &args)
if (args.Length() != 2)
V8THROW_ERROR("Qt.vector2d(): Invalid arguments");
- float xy[3];
+ float xy[3]; // qvector2d uses float internally
xy[0] = args[0]->ToNumber()->Value();
xy[1] = args[1]->ToNumber()->Value();
@@ -559,7 +559,7 @@ v8::Handle<v8::Value> vector3d(const v8::Arguments &args)
if (args.Length() != 3)
V8THROW_ERROR("Qt.vector3d(): Invalid arguments");
- float xyz[3];
+ float xyz[3]; // qvector3d uses float internally
xyz[0] = args[0]->ToNumber()->Value();
xyz[1] = args[1]->ToNumber()->Value();
xyz[2] = args[2]->ToNumber()->Value();
@@ -577,7 +577,7 @@ v8::Handle<v8::Value> vector4d(const v8::Arguments &args)
if (args.Length() != 4)
V8THROW_ERROR("Qt.vector4d(): Invalid arguments");
- float xyzw[4];
+ float xyzw[4]; // qvector4d uses float internally
xyzw[0] = args[0]->ToNumber()->Value();
xyzw[1] = args[1]->ToNumber()->Value();
xyzw[2] = args[2]->ToNumber()->Value();
@@ -596,7 +596,7 @@ v8::Handle<v8::Value> quaternion(const v8::Arguments &args)
if (args.Length() != 4)
V8THROW_ERROR("Qt.quaternion(): Invalid arguments");
- double sxyz[4];
+ qreal sxyz[4]; // qquaternion uses qreal internally
sxyz[0] = args[0]->ToNumber()->Value();
sxyz[1] = args[1]->ToNumber()->Value();
sxyz[2] = args[2]->ToNumber()->Value();
@@ -648,7 +648,7 @@ v8::Handle<v8::Value> matrix4x4(const v8::Arguments &args)
if (args.Length() != 16)
V8THROW_ERROR("Qt.matrix4x4(): Invalid arguments");
- float vals[16];
+ qreal vals[16]; // qmatrix4x4 uses qreal internally
vals[0] = args[0]->ToNumber()->Value();
vals[1] = args[1]->ToNumber()->Value();
vals[2] = args[2]->ToNumber()->Value();
diff --git a/src/qml/qml/v8/qv8qobjectwrapper.cpp b/src/qml/qml/v8/qv8qobjectwrapper.cpp
index 01ab252d7b..bee176f829 100644
--- a/src/qml/qml/v8/qv8qobjectwrapper.cpp
+++ b/src/qml/qml/v8/qv8qobjectwrapper.cpp
@@ -1552,16 +1552,29 @@ static v8::Handle<v8::Value> CallMethod(QObject *object, int index, int returnTy
{
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);
-
for (int ii = 0; ii < argCount; ++ii)
args[ii + 1].fromValue(argTypes[ii], engine, callArgs[ii]);
-
QVarLengthArray<void *, 9> argData(args.count());
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);
@@ -1664,6 +1677,11 @@ static int MatchScore(v8::Handle<v8::Value> actual, int conversionType)
case QMetaType::QStringList:
case QMetaType::QVariantList:
return 5;
+ case QMetaType::QVector4D:
+ case QMetaType::QMatrix4x4:
+ return 6;
+ case QMetaType::QVector3D:
+ return 7;
default:
return 10;
}
@@ -1699,6 +1717,10 @@ static int MatchScore(v8::Handle<v8::Value> actual, int conversionType)
return 0;
else
return 10;
+ } else if (r && r->resourceType() == QV8ObjectResource::ValueTypeType) {
+ if (r->engine->toVariant(actual, -1).userType() == conversionType)
+ return 0;
+ return 10;
} else if (conversionType == QMetaType::QJsonObject) {
return 5;
} else {
@@ -1831,6 +1853,16 @@ static v8::Handle<v8::Value> CallOverloaded(QObject *object, const QQmlPropertyD
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;
@@ -1871,6 +1903,8 @@ static v8::Handle<v8::Value> CallOverloaded(QObject *object, const QQmlPropertyD
} while((attempt = RelatedMethod(object, attempt, dummy)) != 0);
if (best) {
+ 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/v8/qv8valuetypewrapper.cpp b/src/qml/qml/v8/qv8valuetypewrapper.cpp
index cf6c530f5b..fe58546522 100644
--- a/src/qml/qml/v8/qv8valuetypewrapper.cpp
+++ b/src/qml/qml/v8/qv8valuetypewrapper.cpp
@@ -235,6 +235,9 @@ bool QV8ValueTypeWrapper::isEqual(QV8ObjectResource *r, const QVariant& value)
} else {
Q_ASSERT(resource->objectType == QV8ValueTypeResource::Copy);
QV8ValueTypeCopyResource *copy = static_cast<QV8ValueTypeCopyResource *>(resource);
+ resource->type->setValue(copy->value);
+ if (resource->type->isEqual(value))
+ return true;
return (value == copy->value);
}
}
@@ -260,11 +263,8 @@ v8::Handle<v8::Value> QV8ValueTypeWrapper::ToString(const v8::Arguments &args)
} else {
Q_ASSERT(resource->objectType == QV8ValueTypeResource::Copy);
QV8ValueTypeCopyResource *copy = static_cast<QV8ValueTypeCopyResource *>(resource);
- QString result = copy->value.toString();
- if (result.isEmpty() && !copy->value.canConvert(QVariant::String)) {
- result = QString::fromLatin1("QVariant(%0)").arg(QString::fromLatin1(copy->value.typeName()));
- }
- return resource->engine->toString(result);
+ resource->type->setValue(copy->value);
+ return resource->engine->toString(resource->type->toString());
}
} else {
return v8::Undefined();
@@ -317,6 +317,11 @@ v8::Handle<v8::Value> QV8ValueTypeWrapper::Getter(v8::Local<v8::String> property
if (!result)
return v8::Handle<v8::Value>();
+ if (result->isFunction()) {
+ // calling a Q_INVOKABLE function of a value type
+ return r->engine->qobjectWrapper()->getProperty(r->type, propertystring, QV8QObjectWrapper::IgnoreRevision);
+ }
+
#define VALUE_TYPE_LOAD(metatype, cpptype, constructor) \
if (result->propType == metatype) { \
cpptype v; \