aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Adams <christopher.adams@nokia.com>2012-06-26 18:02:35 +1000
committerQt by Nokia <qt-info@nokia.com>2012-07-11 01:46:52 +0200
commitf5cb65b35e076facbce45e896902a34da7036135 (patch)
tree7575065fde2d0c14c379a992bf8b3593e21f4881
parent5376906de58e1c25c77b7a61800365b6e542542f (diff)
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 <matthew.vogt@nokia.com>
-rw-r--r--src/qml/doc/src/syntax/objectattributes.qdoc2
-rw-r--r--src/qml/doc/src/typesystem/basictypes.qdoc118
-rw-r--r--src/qml/qml/qqmlcompiler.cpp8
-rw-r--r--src/qml/qml/qqmlengine.cpp14
-rw-r--r--src/qml/qml/qqmlglobal.cpp37
-rw-r--r--src/qml/qml/qqmlglobal_p.h13
-rw-r--r--src/qml/qml/qqmlscript.cpp8
-rw-r--r--src/qml/qml/qqmlscript_p.h4
-rw-r--r--src/qml/qml/qqmlvaluetype.cpp18
-rw-r--r--src/qml/qml/qqmlvaluetype_p.h14
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp66
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp102
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions_p.h4
-rw-r--r--src/qml/qml/v8/qv8engine.cpp6
-rw-r--r--src/qml/qml/v8/qv8valuetypewrapper.cpp9
-rw-r--r--src/qml/qml/v8/qv8valuetypewrapper_p.h1
-rw-r--r--src/quick/util/qquickglobal.cpp608
-rw-r--r--src/quick/util/qquickvaluetypes.cpp14
-rw-r--r--tests/auto/qml/qml.pro1
-rw-r--r--tests/auto/qml/qqmlglobal/tst_qqmlglobal.cpp8
-rw-r--r--tests/auto/qml/qqmlqt/data/font.qml8
-rw-r--r--tests/auto/qml/qqmlqt/data/matrix4x4.qml9
-rw-r--r--tests/auto/qml/qqmlqt/data/quaternion.qml8
-rw-r--r--tests/auto/qml/qqmlqt/data/vector2.qml8
-rw-r--r--tests/auto/qml/qqmlqt/tst_qqmlqt.cpp100
-rw-r--r--tests/auto/qml/qqmlvaluetypeproviders/data/comparisonSemantics.qml95
-rw-r--r--tests/auto/qml/qqmlvaluetypeproviders/data/cppIntegration.qml98
-rw-r--r--tests/auto/qml/qqmlvaluetypeproviders/data/jsObjectConversion.qml48
-rw-r--r--tests/auto/qml/qqmlvaluetypeproviders/data/qtqmlValueTypes.qml48
-rw-r--r--tests/auto/qml/qqmlvaluetypeproviders/data/qtquickValueTypes.qml119
-rw-r--r--tests/auto/qml/qqmlvaluetypeproviders/qqmlvaluetypeproviders.pro16
-rw-r--r--tests/auto/qml/qqmlvaluetypeproviders/testtypes.cpp46
-rw-r--r--tests/auto/qml/qqmlvaluetypeproviders/testtypes.h195
-rw-r--r--tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp173
34 files changed, 1894 insertions, 132 deletions
diff --git a/src/qml/doc/src/syntax/objectattributes.qdoc b/src/qml/doc/src/syntax/objectattributes.qdoc
index 1562aa6b1f..bfedd19d76 100644
--- a/src/qml/doc/src/syntax/objectattributes.qdoc
+++ b/src/qml/doc/src/syntax/objectattributes.qdoc
@@ -146,7 +146,7 @@ property int volume: "four" // generates an error; the property's object will n
Likewise if a property is assigned a value of the wrong type during run time, the new value will not be assigned, and an error will be generated.
-See \l {QML Basic Types} for a list of the types of properties that are supported by default. Additionally, any available \l {QML Object Types}QML object type} may also be used as a property type.
+See \l {QML Basic Types} for a list of the types of properties that are supported by default. Additionally, any available \l {QML Object Types}{QML object type} may also be used as a property type.
\section3 Special property types
diff --git a/src/qml/doc/src/typesystem/basictypes.qdoc b/src/qml/doc/src/typesystem/basictypes.qdoc
index 96aaf86d84..94ff682ee3 100644
--- a/src/qml/doc/src/typesystem/basictypes.qdoc
+++ b/src/qml/doc/src/typesystem/basictypes.qdoc
@@ -49,6 +49,10 @@ Basic types can be used to refer to:
\section1 Supported Basic Types
+Most basic types are supported by the engine by default and do not require an
+\l {Import Statements}{Import Statement} to be used, unlike QML object types.
+Some basic types which contain multiple property-value pairs (also known as \c{value types})
+do require an import, as they are provided by the QtQuick module.
The basic types supported in QML are listed below:
\annotatedlist qmlbasictypes
@@ -119,6 +123,8 @@ property is only invoked when the property is reassigned to a different object v
Item { width: 100; height: 200 }
\endqml
+ This basic type is provided by the QML language.
+
\sa {QML Basic Types}
*/
@@ -137,6 +143,8 @@ property is only invoked when the property is reassigned to a different object v
}
\endqml
+ This basic type is provided by the QML language.
+
\sa {QML Basic Types}
*/
@@ -157,6 +165,8 @@ property is only invoked when the property is reassigned to a different object v
{http://en.wikipedia.org/wiki/IEEE_754} {IEEE floating point}
format.
+ This basic type is provided by the QML language.
+
\sa {QML Basic Types}
*/
@@ -176,6 +186,8 @@ property is only invoked when the property is reassigned to a different object v
}
\endqml
+ This basic type is provided by the QML language.
+
\sa {QML Basic Types}
*/
@@ -201,6 +213,8 @@ property is only invoked when the property is reassigned to a different object v
\l{qtqml-cppintegration-data.html}{passed into QML from C++} is automatically
converted into a \c string value, and vice-versa.
+ This basic type is provided by the QML language.
+
\sa {QML Basic Types}
*/
@@ -270,6 +284,8 @@ property is only invoked when the property is reassigned to a different object v
Image { source: encodeURIComponent("/tmp/test#1.png") }
\endqml
+ This basic type is provided by the QML language.
+
\sa {QML Basic Types}
*/
@@ -314,6 +330,8 @@ property is only invoked when the property is reassigned to a different object v
\l{qtqml-cppintegration-data.html}{passed into QML from C++} is automatically
converted into a \c color value, and vice-versa.
+ This basic type is provided by the QtQuick import.
+
\sa {QML Basic Types}
*/
@@ -341,6 +359,8 @@ property is only invoked when the property is reassigned to a different object v
converted into a \c point value. When a \c point value is passed to C++, it
is automatically converted into a QPointF value.
+ This basic type is provided by the QML language.
+
\sa {QML Basic Types}
*/
@@ -378,6 +398,8 @@ property is only invoked when the property is reassigned to a different object v
converted into a \c size value, and vice-versa. When a \c size value is passed to C++, it
is automatically converted into a QSizeF value.
+ This basic type is provided by the QML language.
+
\sa {QML Basic Types}
*/
@@ -417,6 +439,7 @@ property is only invoked when the property is reassigned to a different object v
converted into a \c rect value, and vice-versa. When a \c rect value is passed to C++, it
is automatically converted into a QRectF value.
+ This basic type is provided by the QML language.
\sa {QML Basic Types}
*/
@@ -441,6 +464,13 @@ property is only invoked when the property is reassigned to a different object v
\l{qtqml-cppintegration-data.html}{passed into QML from C++} is automatically
converted into a \c date value, and vice-versa.
+ Note that the date type has comparison semantics which match
+ those of the JavaScript Date object. To compare the value
+ of two date properties, you should compare their "toString()"
+ values.
+
+ This basic type is provided by the QML language.
+
\sa {QML Basic Types}
*/
@@ -468,6 +498,8 @@ property is only invoked when the property is reassigned to a different object v
\l{qtqml-cppintegration-data.html}{passed into QML from C++} is automatically
converted into a \c time value, and vice-versa.
+ This basic type is provided by the QML language.
+
\sa {QML Basic Types}
*/
@@ -475,6 +507,7 @@ property is only invoked when the property is reassigned to a different object v
\qmlbasictype font
\ingroup qmlbasictypes
\brief a font value with the properties of QFont.
+ \target fontbasictypedocs
The \c font type refers to a font value with the properties of QFont.
@@ -498,6 +531,8 @@ property is only invoked when the property is reassigned to a different object v
\l{qtqml-cppintegration-data.html}{passed into QML from C++} is automatically
converted into a \c font value, and vice-versa.
+ This basic type is provided by the QtQuick import.
+
\sa {QML Basic Types}
*/
@@ -572,6 +607,8 @@ property is only invoked when the property is reassigned to a different object v
lists stored by the \c var type can be manipulated with greater
flexibility from within QML.
+ This basic type is provided by the QML language.
+
\sa {QML Basic Types}
*/
@@ -643,6 +680,8 @@ property is only invoked when the property is reassigned to a different object v
For more information regarding the usage of a scarce resource, please
see \l{Scarce Resources in JavaScript}.
+ This basic type is provided by the QML language.
+
\sa {QML Basic Types}
*/
@@ -758,6 +797,27 @@ property is only invoked when the property is reassigned to a different object v
extra data such as the object's JavaScript prototype chain is also lost in
the process.
+ This basic type is provided by the QML language.
+
+ \sa {QML Basic Types}
+*/
+
+/*!
+ \qmlbasictype vector2d
+ \ingroup qmlbasictypes
+
+ \brief A vector2d type has x and y attributes.
+
+ A \c vector2d type has \c x and \c y attributes, otherwise
+ it is similar to the \c vector3d type. Please see the
+ documentation about the \c vector3d type for more information.
+
+ To create a \c vector2d value, specify it as a "x,y" string,
+ or define the components individually, or compose it with
+ the Qt.vector2d() function.
+
+ This basic type is provided by the QtQuick import.
+
\sa {QML Basic Types}
*/
@@ -790,6 +850,61 @@ property is only invoked when the property is reassigned to a different object v
\l{qtqml-cppintegration-data.html}{passed into QML from C++} is automatically
converted into a \c vector3d value, and vice-versa.
+ This basic type is provided by the QtQuick import.
+
+ \sa {QML Basic Types}
+*/
+
+/*!
+ \qmlbasictype vector4d
+ \ingroup qmlbasictypes
+
+ \brief A vector4d type has x, y, z and w attributes.
+
+ A \c vector4d type has \c x, \c y, \c z and \c w attributes,
+ otherwise it is similar to the \c vector3d type. Please see the
+ documentation about the \c vector3d type for more information.
+
+ To create a \c vector4d value, specify it as a "x,y,z,w" string,
+ or define the components individually, or compose it with
+ the Qt.vector4d() function.
+
+ This basic type is provided by the QtQuick import.
+
+ \sa {QML Basic Types}
+*/
+
+/*!
+ \qmlbasictype quaternion
+ \ingroup qmlbasictypes
+
+ \brief A quaternion type has scalar, x, y, and z attributes.
+
+ A \c quaternion type has \c scalar, \c x, \c y and \c z attributes,
+ otherwise it is similar to the \c vector3d type. Please see the
+ documentation about the \c vector3d type for more information.
+
+ To create a \c quaternion value, specify it as a "scalar,x,y,z" string,
+ or define the components individually, or compose it with
+ the Qt.quaternion() function.
+
+ This basic type is provided by the QtQuick import.
+
+ \sa {QML Basic Types}
+*/
+
+/*!
+ \qmlbasictype matrix4x4
+ \ingroup qmlbasictypes
+
+ \brief A matrix4x4 type is a 4-row and 4-column matrix
+
+ A \c matrix4x4 type has sixteen values, but these values are
+ largely opaque to QML. Values of this type can be composed with
+ the Qt.matrix4x4() function.
+
+ This basic type is provided by the QtQuick import.
+
\sa {QML Basic Types}
*/
@@ -815,6 +930,9 @@ property is only invoked when the property is reassigned to a different object v
\l{qtqml-cppintegration-data.html}{passed into QML from C++} is automatically
converted into an \c enumeration value, and vice-versa.
+ This basic type is provided by the QML language. Some enumeration values
+ are provided by the QtQuick import.
+
\sa {QML Basic Types}
*/
diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp
index 6f2792570f..539b6c402a 100644
--- a/src/qml/qml/qqmlcompiler.cpp
+++ b/src/qml/qml/qqmlcompiler.cpp
@@ -2806,10 +2806,18 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod
{ Object::DynamicProperty::String, QMetaType::QString },
{ Object::DynamicProperty::Url, QMetaType::QUrl },
{ Object::DynamicProperty::Color, QMetaType::QColor },
+ { Object::DynamicProperty::Font, QMetaType::QFont },
{ Object::DynamicProperty::Time, QMetaType::QTime },
{ Object::DynamicProperty::Date, QMetaType::QDate },
{ Object::DynamicProperty::DateTime, QMetaType::QDateTime },
{ Object::DynamicProperty::Rect, QMetaType::QRectF },
+ { Object::DynamicProperty::Point, QMetaType::QPointF },
+ { Object::DynamicProperty::Size, QMetaType::QSizeF },
+ { Object::DynamicProperty::Vector2D, QMetaType::QVector2D },
+ { Object::DynamicProperty::Vector3D, QMetaType::QVector3D },
+ { Object::DynamicProperty::Vector4D, QMetaType::QVector4D },
+ { Object::DynamicProperty::Matrix4x4, QMetaType::QMatrix4x4 },
+ { Object::DynamicProperty::Quaternion, QMetaType::QQuaternion }
};
static const int builtinTypeCount = sizeof(builtinTypes) / sizeof(TypeData);
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 229a071789..e3db9d478a 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -271,16 +271,26 @@ the \l Qt::LeftButton and \l Qt::RightButton enumeration values as \c Qt.LeftBut
\section1 Types
+
The Qt object also contains helper functions for creating objects of specific
data types. This is primarily useful when setting the properties of an item
when the property has one of the following types:
-
\list
-\li \c color - use \l{Qt::rgba()}{Qt.rgba()}, \l{Qt::hsla()}{Qt.hsla()}, \l{Qt::darker()}{Qt.darker()}, \l{Qt::lighter()}{Qt.lighter()} or \l{Qt::tint()}{Qt.tint()}
\li \c rect - use \l{Qt::rect()}{Qt.rect()}
\li \c point - use \l{Qt::point()}{Qt.point()}
\li \c size - use \l{Qt::size()}{Qt.size()}
+\endlist
+
+If the QtQuick module has been imported, the following helper functions for
+creating objects of specific data types are also available for clients to use:
+\list
+\li \c color - use \l{Qt::rgba()}{Qt.rgba()}, \l{Qt::hsla()}{Qt.hsla()}, \l{Qt::darker()}{Qt.darker()}, \l{Qt::lighter()}{Qt.lighter()} or \l{Qt::tint()}{Qt.tint()}
+\li \c font - use \l{Qt::font()}{Qt.font()}
+\li \c vector2d - use \l{Qt::vector2d()}{Qt.vector2d()}
\li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
+\li \c vector4d - use \l{Qt::vector4d()}{Qt.vector4d()}
+\li \c quaternion - use \l{Qt::quaternion()}{Qt.quaternion()}
+\li \c matrix4x4 - use \l{Qt::matrix4x4()}{Qt.matrix4x4()}
\endlist
There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
diff --git a/src/qml/qml/qqmlglobal.cpp b/src/qml/qml/qqmlglobal.cpp
index 6f4942963f..0ebc802dec 100644
--- a/src/qml/qml/qqmlglobal.cpp
+++ b/src/qml/qml/qqmlglobal.cpp
@@ -175,42 +175,58 @@ QVariant QQmlValueTypeProvider::createVariantFromString(int type, const QString
return QVariant();
}
-bool QQmlValueTypeProvider::equalValueType(int type, const void *lhs, const void *rhs)
+QVariant QQmlValueTypeProvider::createVariantFromJsObject(int type, QQmlV8Handle obj, QV8Engine *e, bool *ok)
+{
+ QVariant v;
+
+ QQmlValueTypeProvider *p = this;
+ do {
+ if (p->variantFromJsObject(type, obj, e, &v)) {
+ if (ok) *ok = true;
+ return v;
+ }
+ } while ((p = p->next));
+
+ if (ok) *ok = false;
+ return QVariant();
+}
+
+bool QQmlValueTypeProvider::equalValueType(int type, const void *lhs, const void *rhs, size_t rhsSize)
{
Q_ASSERT(lhs);
Q_ASSERT(rhs);
QQmlValueTypeProvider *p = this;
do {
- if (p->equal(type, lhs, rhs))
+ if (p->equal(type, lhs, rhs, rhsSize))
return true;
} while ((p = p->next));
return false;
}
-bool QQmlValueTypeProvider::storeValueType(int type, const void *src, void *dst, size_t n)
+bool QQmlValueTypeProvider::storeValueType(int type, const void *src, void *dst, size_t dstSize)
{
Q_ASSERT(src);
Q_ASSERT(dst);
QQmlValueTypeProvider *p = this;
do {
- if (p->store(type, src, dst, n))
+ if (p->store(type, src, dst, dstSize))
return true;
} while ((p = p->next));
return false;
}
-bool QQmlValueTypeProvider::readValueType(int srcType, const void *src, int dstType, void *dst)
+bool QQmlValueTypeProvider::readValueType(int srcType, const void *src, size_t srcSize, int dstType, void *dst)
{
Q_ASSERT(src);
Q_ASSERT(dst);
QQmlValueTypeProvider *p = this;
do {
- if (p->read(srcType, src, dstType, dst))
+ if (p->read(srcType, src, srcSize, dstType, dst))
return true;
} while ((p = p->next));
@@ -240,9 +256,10 @@ bool QQmlValueTypeProvider::createFromString(int, const QString &, void *, size_
bool QQmlValueTypeProvider::createStringFrom(int, const void *, QString *) { return false; }
bool QQmlValueTypeProvider::variantFromString(const QString &, QVariant *) { return false; }
bool QQmlValueTypeProvider::variantFromString(int, const QString &, QVariant *) { return false; }
-bool QQmlValueTypeProvider::equal(int, const void *, const void *) { return false; }
+bool QQmlValueTypeProvider::variantFromJsObject(int, QQmlV8Handle, QV8Engine *, QVariant *) { return false; }
+bool QQmlValueTypeProvider::equal(int, const void *, const void *, size_t) { return false; }
bool QQmlValueTypeProvider::store(int, const void *, void *, size_t) { return false; }
-bool QQmlValueTypeProvider::read(int, const void *, int, void *) { return false; }
+bool QQmlValueTypeProvider::read(int, const void *, size_t, int, void *) { return false; }
bool QQmlValueTypeProvider::write(int, const void *, void *, size_t) { return false; }
static QQmlValueTypeProvider *valueTypeProvider = 0;
@@ -266,10 +283,6 @@ Q_QML_PRIVATE_EXPORT void QQml_addValueTypeProvider(QQmlValueTypeProvider *newPr
Q_AUTOTEST_EXPORT QQmlValueTypeProvider *QQml_valueTypeProvider(void)
{
- if (valueTypeProvider == 0) {
- qWarning() << "Warning: QQml_valueTypeProvider: no value type provider has been set!";
- }
-
static QQmlValueTypeProvider **providerPtr = getValueTypeProvider();
return *providerPtr;
}
diff --git a/src/qml/qml/qqmlglobal_p.h b/src/qml/qml/qqmlglobal_p.h
index b3e8eb6421..b10457bd29 100644
--- a/src/qml/qml/qqmlglobal_p.h
+++ b/src/qml/qml/qqmlglobal_p.h
@@ -46,6 +46,7 @@
#include <QtCore/QObject>
#include <private/qqmlpropertycache_p.h>
#include <private/qmetaobject_p.h>
+#include <private/qv8engine_p.h>
QT_BEGIN_HEADER
@@ -208,7 +209,7 @@ inline void QQml_setParent_noEvent(QObject *object, QObject *parent)
class QQmlValueType;
-
+class QV8Engine;
class Q_QML_PRIVATE_EXPORT QQmlValueTypeProvider
{
public:
@@ -226,10 +227,11 @@ public:
QVariant createVariantFromString(const QString &);
QVariant createVariantFromString(int, const QString &, bool *);
+ QVariant createVariantFromJsObject(int, QQmlV8Handle, QV8Engine *, bool*);
- bool equalValueType(int, const void *, const void *);
+ bool equalValueType(int, const void *, const void *, size_t);
bool storeValueType(int, const void *, void *, size_t);
- bool readValueType(int, const void *, int, void *);
+ bool readValueType(int, const void *, size_t, int, void *);
bool writeValueType(int, const void *, void *, size_t);
private:
@@ -245,10 +247,11 @@ private:
virtual bool variantFromString(const QString &, QVariant *);
virtual bool variantFromString(int, const QString &, QVariant *);
+ virtual bool variantFromJsObject(int, QQmlV8Handle, QV8Engine *, QVariant *);
- virtual bool equal(int, const void *, const void *);
+ virtual bool equal(int, const void *, const void *, size_t);
virtual bool store(int, const void *, void *, size_t);
- virtual bool read(int, const void *, int, void *);
+ virtual bool read(int, const void *, size_t, int, void *);
virtual bool write(int, const void *, void *, size_t);
friend Q_QML_PRIVATE_EXPORT void QQml_addValueTypeProvider(QQmlValueTypeProvider *);
diff --git a/src/qml/qml/qqmlscript.cpp b/src/qml/qml/qqmlscript.cpp
index f4a928c784..469b5d5291 100644
--- a/src/qml/qml/qqmlscript.cpp
+++ b/src/qml/qml/qqmlscript.cpp
@@ -912,6 +912,14 @@ bool ProcessAST::visit(AST::UiPublicMember *node)
// { "date", strlen("date"), Object::DynamicProperty::Date },
{ "date", strlen("date"), Object::DynamicProperty::DateTime },
{ "rect", strlen("rect"), Object::DynamicProperty::Rect },
+ { "point", strlen("point"), Object::DynamicProperty::Point },
+ { "size", strlen("size"), Object::DynamicProperty::Size },
+ { "font", strlen("font"), Object::DynamicProperty::Font },
+ { "vector2d", strlen("vector2d"), Object::DynamicProperty::Vector2D },
+ { "vector3d", strlen("vector3d"), Object::DynamicProperty::Vector3D },
+ { "vector4d", strlen("vector4d"), Object::DynamicProperty::Vector4D },
+ { "quaternion", strlen("quaternion"), Object::DynamicProperty::Quaternion },
+ { "matrix4x4", strlen("matrix4x4"), Object::DynamicProperty::Matrix4x4 },
{ "variant", strlen("variant"), Object::DynamicProperty::Variant },
{ "var", strlen("var"), Object::DynamicProperty::Var }
};
diff --git a/src/qml/qml/qqmlscript_p.h b/src/qml/qml/qqmlscript_p.h
index 486c573754..718faa33ca 100644
--- a/src/qml/qml/qqmlscript_p.h
+++ b/src/qml/qml/qqmlscript_p.h
@@ -381,7 +381,9 @@ public:
DynamicProperty();
enum Type { Var, Variant, Int, Bool, Real, String, Url, Color,
- Time, Date, DateTime, Rect, Alias, Custom, CustomList };
+ Font, Time, Date, DateTime, Rect, Point, Size,
+ Vector2D, Vector3D, Vector4D, Matrix4x4, Quaternion,
+ Alias, Custom, CustomList };
quint32 isDefaultProperty:1;
quint32 isReadOnly:1;
diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp
index c0759a31b4..165024adfe 100644
--- a/src/qml/qml/qqmlvaluetype.cpp
+++ b/src/qml/qml/qqmlvaluetype.cpp
@@ -112,14 +112,14 @@ QQmlValueType *QQmlValueTypeFactory::valueType(int t)
return rv;
}
-QQmlValueType::QQmlValueType(QObject *parent)
-: QObject(parent)
+QQmlValueType::QQmlValueType(int userType, QObject *parent)
+: QObject(parent), m_userType(userType)
{
}
QQmlPointFValueType::QQmlPointFValueType(QObject *parent)
- : QQmlValueTypeBase<QPointF>(parent)
+ : QQmlValueTypeBase<QPointF>(QMetaType::QPointF, parent)
{
}
@@ -150,7 +150,7 @@ void QQmlPointFValueType::setY(qreal y)
QQmlPointValueType::QQmlPointValueType(QObject *parent)
- : QQmlValueTypeBase<QPoint>(parent)
+ : QQmlValueTypeBase<QPoint>(QMetaType::QPoint, parent)
{
}
@@ -181,7 +181,7 @@ void QQmlPointValueType::setY(int y)
QQmlSizeFValueType::QQmlSizeFValueType(QObject *parent)
- : QQmlValueTypeBase<QSizeF>(parent)
+ : QQmlValueTypeBase<QSizeF>(QMetaType::QSizeF, parent)
{
}
@@ -212,7 +212,7 @@ void QQmlSizeFValueType::setHeight(qreal h)
QQmlSizeValueType::QQmlSizeValueType(QObject *parent)
- : QQmlValueTypeBase<QSize>(parent)
+ : QQmlValueTypeBase<QSize>(QMetaType::QSize, parent)
{
}
@@ -243,7 +243,7 @@ void QQmlSizeValueType::setHeight(int h)
QQmlRectFValueType::QQmlRectFValueType(QObject *parent)
- : QQmlValueTypeBase<QRectF>(parent)
+ : QQmlValueTypeBase<QRectF>(QMetaType::QRectF, parent)
{
}
@@ -294,7 +294,7 @@ void QQmlRectFValueType::setHeight(qreal h)
QQmlRectValueType::QQmlRectValueType(QObject *parent)
- : QQmlValueTypeBase<QRect>(parent)
+ : QQmlValueTypeBase<QRect>(QMetaType::QRect, parent)
{
}
@@ -345,7 +345,7 @@ void QQmlRectValueType::setHeight(int h)
QQmlEasingValueType::QQmlEasingValueType(QObject *parent)
- : QQmlValueTypeBase<QEasingCurve>(parent)
+ : QQmlValueTypeBase<QEasingCurve>(QMetaType::QEasingCurve, parent)
{
}
diff --git a/src/qml/qml/qqmlvaluetype_p.h b/src/qml/qml/qqmlvaluetype_p.h
index f704da2c8e..02be333037 100644
--- a/src/qml/qml/qqmlvaluetype_p.h
+++ b/src/qml/qml/qqmlvaluetype_p.h
@@ -69,7 +69,7 @@ class Q_QML_PRIVATE_EXPORT QQmlValueType : public QObject
{
Q_OBJECT
public:
- QQmlValueType(QObject *parent = 0);
+ QQmlValueType(int userType, QObject *parent = 0);
virtual void read(QObject *, int) = 0;
virtual void write(QObject *, int, QQmlPropertyPrivate::WriteFlags flags) = 0;
virtual QVariant value() = 0;
@@ -80,6 +80,11 @@ public:
virtual void onLoad() {}
+ inline int userType() const
+ {
+ return m_userType;
+ }
+
protected:
inline void readProperty(QObject *obj, int idx, void *p)
{
@@ -94,6 +99,9 @@ protected:
void *a[] = { p, 0, &status, &flags };
QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
}
+
+private:
+ int m_userType;
};
template <typename T>
@@ -102,8 +110,8 @@ class QQmlValueTypeBase : public QQmlValueType
public:
typedef T ValueType;
- QQmlValueTypeBase(QObject *parent)
- : QQmlValueType(parent)
+ QQmlValueTypeBase(int userType, QObject *parent)
+ : QQmlValueType(userType, parent)
{
}
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index 1c07dd676e..c982856453 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -101,6 +101,8 @@ public:
inline const QDate &asQDate();
inline const QDateTime &asQDateTime();
inline const QRectF &asQRectF();
+ inline const QPointF &asQPointF();
+ inline const QSizeF &asQSizeF();
inline const QJSValue &asQJSValue();
inline void setValue(QObject *v, QQmlVMEMetaObject *target, int index);
@@ -114,6 +116,8 @@ public:
inline void setValue(const QDate &);
inline void setValue(const QDateTime &);
inline void setValue(const QRectF &);
+ inline void setValue(const QPointF &);
+ inline void setValue(const QSizeF &);
inline void setValue(const QJSValue &);
inline void setDataType(int t);
@@ -176,6 +180,12 @@ void QQmlVMEVariant::cleanup()
} else if (type == QMetaType::QRectF) {
((QRectF *)dataPtr())->~QRectF();
type = QVariant::Invalid;
+ } else if (type == QMetaType::QPointF) {
+ ((QPointF *)dataPtr())->~QPointF();
+ type = QVariant::Invalid;
+ } else if (type == QMetaType::QSizeF) {
+ ((QSizeF *)dataPtr())->~QSizeF();
+ type = QVariant::Invalid;
} else if (type == qMetaTypeId<QVariant>()) {
((QVariant *)dataPtr())->~QVariant();
type = QVariant::Invalid;
@@ -297,6 +307,22 @@ const QRectF &QQmlVMEVariant::asQRectF()
return *(QRectF *)(dataPtr());
}
+const QSizeF &QQmlVMEVariant::asQSizeF()
+{
+ if (type != QMetaType::QSizeF)
+ setValue(QSizeF());
+
+ return *(QSizeF *)(dataPtr());
+}
+
+const QPointF &QQmlVMEVariant::asQPointF()
+{
+ if (type != QMetaType::QPointF)
+ setValue(QPointF());
+
+ return *(QPointF *)(dataPtr());
+}
+
const QJSValue &QQmlVMEVariant::asQJSValue()
{
if (type != qMetaTypeId<QJSValue>())
@@ -419,6 +445,28 @@ void QQmlVMEVariant::setValue(const QRectF &v)
}
}
+void QQmlVMEVariant::setValue(const QPointF &v)
+{
+ if (type != QMetaType::QPointF) {
+ cleanup();
+ type = QMetaType::QPointF;
+ new (dataPtr()) QPointF(v);
+ } else {
+ *(QPointF *)(dataPtr()) = v;
+ }
+}
+
+void QQmlVMEVariant::setValue(const QSizeF &v)
+{
+ if (type != QMetaType::QSizeF) {
+ cleanup();
+ type = QMetaType::QSizeF;
+ new (dataPtr()) QSizeF(v);
+ } else {
+ *(QSizeF *)(dataPtr()) = v;
+ }
+}
+
void QQmlVMEVariant::setValue(const QJSValue &v)
{
if (type != qMetaTypeId<QJSValue>()) {
@@ -685,6 +733,12 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
case QVariant::RectF:
*reinterpret_cast<QRectF *>(a[0]) = data[id].asQRectF();
break;
+ case QVariant::SizeF:
+ *reinterpret_cast<QSizeF *>(a[0]) = data[id].asQSizeF();
+ break;
+ case QVariant::PointF:
+ *reinterpret_cast<QPointF *>(a[0]) = data[id].asQPointF();
+ break;
case QMetaType::QObjectStar:
*reinterpret_cast<QObject **>(a[0]) = data[id].asQObject();
break;
@@ -692,7 +746,7 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
*reinterpret_cast<QVariant *>(a[0]) = readPropertyAsVariant(id);
break;
default:
- QQml_valueTypeProvider()->readValueType(data[id].dataType(), data[id].dataPtr(), t, a[0]);
+ QQml_valueTypeProvider()->readValueType(data[id].dataType(), data[id].dataPtr(), data->dataSize(), t, a[0]);
break;
}
if (t == qMetaTypeId<QQmlListProperty<QObject> >()) {
@@ -739,6 +793,14 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
needActivate = *reinterpret_cast<QRectF *>(a[0]) != data[id].asQRectF();
data[id].setValue(*reinterpret_cast<QRectF *>(a[0]));
break;
+ case QVariant::SizeF:
+ needActivate = *reinterpret_cast<QSizeF *>(a[0]) != data[id].asQSizeF();
+ data[id].setValue(*reinterpret_cast<QSizeF *>(a[0]));
+ break;
+ case QVariant::PointF:
+ needActivate = *reinterpret_cast<QPointF *>(a[0]) != data[id].asQPointF();
+ data[id].setValue(*reinterpret_cast<QPointF *>(a[0]));
+ break;
case QMetaType::QObjectStar:
needActivate = *reinterpret_cast<QObject **>(a[0]) != data[id].asQObject();
data[id].setValue(*reinterpret_cast<QObject **>(a[0]), this, id);
@@ -748,7 +810,7 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
break;
default:
data[id].ensureValueType(t);
- needActivate = !QQml_valueTypeProvider()->equalValueType(t, a[0], data[id].dataPtr());
+ needActivate = !QQml_valueTypeProvider()->equalValueType(t, a[0], data[id].dataPtr(), data[id].dataSize());
QQml_valueTypeProvider()->writeValueType(t, a[0], data[id].dataPtr(), data[id].dataSize());
break;
}
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
@@ -495,13 +495,30 @@ v8::Handle<v8::Value> size(const v8::Arguments &args)
}
/*!
+\qmlmethod Qt::vector2d(real x, real y)
+Returns a Vector2D with the specified \c x and \c y.
+*/
+v8::Handle<v8::Value> 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.
*/
v8::Handle<v8::Value> 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();
@@ -532,6 +549,89 @@ v8::Handle<v8::Value> vector4d(const v8::Arguments &args)
}
/*!
+\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<v8::Value> 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<v8::Value> font(const v8::Arguments &args)
+{
+ if (args.Length() != 1 || !args[0]->IsObject())
+ V8THROW_ERROR("Qt.font(): Invalid arguments");
+
+ v8::Handle<v8::Object> 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<v8::Value> matrix4x4(const v8::Arguments &args)
+{
+ if (args.Length() == 1 && args[0]->IsObject()) {
+ v8::Handle<v8::Object> 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<v8::Value> consoleException(const v8::Arguments &args);
v8::Handle<v8::Value> isQtObject(const v8::Arguments &args);
v8::Handle<v8::Value> rgba(const v8::Arguments &args);
v8::Handle<v8::Value> hsla(const v8::Arguments &args);
+v8::Handle<v8::Value> font(const v8::Arguments &args);
v8::Handle<v8::Value> rect(const v8::Arguments &args);
v8::Handle<v8::Value> point(const v8::Arguments &args);
v8::Handle<v8::Value> size(const v8::Arguments &args);
+v8::Handle<v8::Value> vector2d(const v8::Arguments &args);
v8::Handle<v8::Value> vector3d(const v8::Arguments &args);
v8::Handle<v8::Value> vector4d(const v8::Arguments &args);
+v8::Handle<v8::Value> quaternion(const v8::Arguments &args);
+v8::Handle<v8::Value> matrix4x4(const v8::Arguments &args);
v8::Handle<v8::Value> lighter(const v8::Arguments &args);
v8::Handle<v8::Value> darker(const v8::Arguments &args);
v8::Handle<v8::Value> 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<v8::Object> 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 <private/qqmlvaluetype_p.h>
#include <private/qqmlbinding_p.h>
+#include <private/qqmlglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -148,6 +149,14 @@ v8::Local<v8::Object> QV8ValueTypeWrapper::newValueType(const QVariant &value, Q
return rv;
}
+QVariant QV8ValueTypeWrapper::toVariant(v8::Handle<v8::Object> 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<v8::Object> obj)
{
QV8ValueTypeResource *r = v8_resource_cast<QV8ValueTypeResource>(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<v8::Object> newValueType(QObject *, int, QQmlValueType *);
v8::Local<v8::Object> newValueType(const QVariant &, QQmlValueType *);
+ QVariant toVariant(v8::Handle<v8::Object>, int typeHint, bool *succeeded);
QVariant toVariant(v8::Handle<v8::Object>);
QVariant toVariant(QV8ObjectResource *);
diff --git a/src/quick/util/qquickglobal.cpp b/src/quick/util/qquickglobal.cpp
index 99caf218a6..1708cf7331 100644
--- a/src/quick/util/qquickglobal.cpp
+++ b/src/quick/util/qquickglobal.cpp
@@ -42,6 +42,8 @@
#include <private/qquickvaluetypes_p.h>
#include <private/qquickapplication_p.h>
#include <private/qqmlglobal_p.h>
+#include <private/qv8_p.h>
+#include <private/qv8engine_p.h>
#include <QtGui/QGuiApplication>
#include <QtGui/qdesktopservices.h>
@@ -188,6 +190,32 @@ private:
class QQuickValueTypeProvider : public QQmlValueTypeProvider
{
public:
+
+#if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS)
+ #define ASSERT_VALID_SIZE(size, min) Q_UNUSED(size)
+#else
+ #define ASSERT_VALID_SIZE(size, min) Q_ASSERT(size >= min)
+#endif
+
+ static QVector2D vector2DFromString(const QString &s, bool *ok)
+ {
+ if (s.count(QLatin1Char(',')) == 1) {
+ int index = s.indexOf(QLatin1Char(','));
+
+ bool xGood, yGood;
+ qreal xCoord = s.left(index).toDouble(&xGood);
+ qreal yCoord = s.mid(index+1).toDouble(&yGood);
+
+ if (xGood && yGood) {
+ if (ok) *ok = true;
+ return QVector2D(xCoord, yCoord);
+ }
+ }
+
+ if (ok) *ok = false;
+ return QVector2D();
+ }
+
static QVector3D vector3DFromString(const QString &s, bool *ok)
{
if (s.count(QLatin1Char(',')) == 2) {
@@ -232,67 +260,292 @@ public:
return QVector4D();
}
+ static QQuaternion quaternionFromString(const QString &s, bool *ok)
+ {
+ if (s.count(QLatin1Char(',')) == 3) {
+ int index = s.indexOf(QLatin1Char(','));
+ int index2 = s.indexOf(QLatin1Char(','), index+1);
+ int index3 = s.indexOf(QLatin1Char(','), index2+1);
+
+ bool sGood, xGood, yGood, zGood;
+ qreal sCoord = s.left(index).toDouble(&sGood);
+ qreal xCoord = s.mid(index+1, index2-index-1).toDouble(&xGood);
+ qreal yCoord = s.mid(index2+1, index3-index2-1).toDouble(&yGood);
+ qreal zCoord = s.mid(index3+1).toDouble(&zGood);
+
+ if (sGood && xGood && yGood && zGood) {
+ if (ok) *ok = true;
+ return QQuaternion(sCoord, xCoord, yCoord, zCoord);
+ }
+ }
+
+ if (ok) *ok = false;
+ return QQuaternion();
+ }
+
+ static QMatrix4x4 matrix4x4FromString(const QString &s, bool *ok)
+ {
+ if (s.count(QLatin1Char(',')) == 15) {
+ qreal matValues[16];
+ bool vOK = true;
+ QString mutableStr = s;
+ for (int i = 0; vOK && i < 16; ++i) {
+ int cidx = mutableStr.indexOf(QLatin1Char(','));
+ matValues[i] = mutableStr.left(cidx).toDouble(&vOK);
+ mutableStr = mutableStr.mid(cidx + 1);
+ }
+
+ if (vOK) {
+ if (ok) *ok = true;
+ return QMatrix4x4(matValues);
+ }
+ }
+
+ if (ok) *ok = false;
+ return QMatrix4x4();
+ }
+
+ static QFont fontFromObject(QQmlV8Handle object, QV8Engine *e, bool *ok)
+ {
+ if (ok) *ok = false;
+ QFont retn;
+ v8::Handle<v8::Object> obj = object.toHandle()->ToObject();
+
+ v8::Handle<v8::Value> vbold = obj->Get(v8::String::New("bold"));
+ v8::Handle<v8::Value> vcap = obj->Get(v8::String::New("capitalization"));
+ v8::Handle<v8::Value> vfam = obj->Get(v8::String::New("family"));
+ v8::Handle<v8::Value> vital = obj->Get(v8::String::New("italic"));
+ v8::Handle<v8::Value> vlspac = obj->Get(v8::String::New("letterSpacing"));
+ v8::Handle<v8::Value> vpixsz = obj->Get(v8::String::New("pixelSize"));
+ v8::Handle<v8::Value> vpntsz = obj->Get(v8::String::New("pointSize"));
+ v8::Handle<v8::Value> vstrk = obj->Get(v8::String::New("strikeout"));
+ v8::Handle<v8::Value> vundl = obj->Get(v8::String::New("underline"));
+ v8::Handle<v8::Value> vweight = obj->Get(v8::String::New("weight"));
+ v8::Handle<v8::Value> vwspac = obj->Get(v8::String::New("wordSpacing"));
+
+ // pull out the values, set ok to true if at least one valid field is given.
+ if (!vbold.IsEmpty() && !vbold->IsNull() && !vbold->IsUndefined() && vbold->IsBoolean()) {
+ retn.setBold(vbold->BooleanValue());
+ if (ok) *ok = true;
+ }
+ if (!vcap.IsEmpty() && !vcap->IsNull() && !vcap->IsUndefined() && vcap->IsInt32()) {
+ retn.setCapitalization(static_cast<QFont::Capitalization>(vcap->Int32Value()));
+ if (ok) *ok = true;
+ }
+ if (!vfam.IsEmpty() && !vfam->IsNull() && !vfam->IsUndefined() && vfam->IsString()) {
+ retn.setFamily(e->toString(vfam->ToString()));
+ if (ok) *ok = true;
+ }
+ if (!vital.IsEmpty() && !vital->IsNull() && !vital->IsUndefined() && vital->IsBoolean()) {
+ retn.setItalic(vital->BooleanValue());
+ if (ok) *ok = true;
+ }
+ if (!vlspac.IsEmpty() && !vlspac->IsNull() && !vlspac->IsUndefined() && vlspac->IsNumber()) {
+ retn.setLetterSpacing(QFont::AbsoluteSpacing, vlspac->NumberValue());
+ if (ok) *ok = true;
+ }
+ if (!vpixsz.IsEmpty() && !vpixsz->IsNull() && !vpixsz->IsUndefined() && vpixsz->IsInt32()) {
+ retn.setPixelSize(vpixsz->Int32Value());
+ if (ok) *ok = true;
+ }
+ if (!vpntsz.IsEmpty() && !vpntsz->IsNull() && !vpntsz->IsUndefined() && vpntsz->IsNumber()) {
+ retn.setPointSize(vpntsz->NumberValue());
+ if (ok) *ok = true;
+ }
+ if (!vstrk.IsEmpty() && !vstrk->IsNull() && !vstrk->IsUndefined() && vstrk->IsBoolean()) {
+ retn.setStrikeOut(vstrk->BooleanValue());
+ if (ok) *ok = true;
+ }
+ if (!vundl.IsEmpty() && !vundl->IsNull() && !vundl->IsUndefined() && vundl->IsBoolean()) {
+ retn.setUnderline(vundl->BooleanValue());
+ if (ok) *ok = true;
+ }
+ if (!vweight.IsEmpty() && !vweight->IsNull() && !vweight->IsUndefined() && vweight->IsInt32()) {
+ retn.setWeight(static_cast<QFont::Weight>(vweight->Int32Value()));
+ if (ok) *ok = true;
+ }
+ if (!vwspac.IsEmpty() && !vwspac->IsNull() && !vwspac->IsUndefined() && vwspac->IsNumber()) {
+ retn.setWordSpacing(vwspac->NumberValue());
+ if (ok) *ok = true;
+ }
+
+ return retn;
+ }
+
+ static QMatrix4x4 matrix4x4FromObject(QQmlV8Handle object, bool *ok)
+ {
+ if (ok) *ok = false;
+ v8::Handle<v8::Object> obj = object.toHandle()->ToObject();
+ if (!obj->IsArray())
+ return QMatrix4x4();
+
+ v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(obj);
+ if (array->Length() != 16)
+ return QMatrix4x4();
+
+ qreal matVals[16];
+ for (uint32_t i = 0; i < 16; ++i) {
+ v8::Handle<v8::Value> v = array->Get(i);
+ if (!v->IsNumber())
+ return QMatrix4x4();
+ matVals[i] = v->NumberValue();
+ }
+
+ if (ok) *ok = true;
+ return QMatrix4x4(matVals);
+ }
+
+ template<typename T>
+ bool typedCreate(QQmlValueType *&v)
+ {
+ v = new T;
+ return true;
+ }
+
bool create(int type, QQmlValueType *&v)
{
switch (type) {
case QMetaType::QColor:
- v = new QQuickColorValueType;
- return true;
+ return typedCreate<QQuickColorValueType>(v);
+ case QMetaType::QFont:
+ return typedCreate<QQuickFontValueType>(v);
case QMetaType::QVector2D:
- v = new QQuickVector2DValueType;
- return true;
+ return typedCreate<QQuickVector2DValueType>(v);
case QMetaType::QVector3D:
- v = new QQuickVector3DValueType;
- return true;
+ return typedCreate<QQuickVector3DValueType>(v);
case QMetaType::QVector4D:
- v = new QQuickVector4DValueType;
- return true;
+ return typedCreate<QQuickVector4DValueType>(v);
case QMetaType::QQuaternion:
- v = new QQuickQuaternionValueType;
- return true;
+ return typedCreate<QQuickQuaternionValueType>(v);
case QMetaType::QMatrix4x4:
- v = new QQuickMatrix4x4ValueType;
- return true;
- case QMetaType::QFont:
- v = new QQuickFontValueType;
- return true;
+ return typedCreate<QQuickMatrix4x4ValueType>(v);
default:
- return false;
+ break;
}
+
+ return false;
}
- bool init(int type, void *data, size_t n)
+ template<typename T>
+ bool typedInit(void *data, size_t dataSize)
{
- if (type == QMetaType::QColor) {
- Q_ASSERT(n >= sizeof(QColor));
- QColor *color = reinterpret_cast<QColor *>(data);
- new (color) QColor();
+ ASSERT_VALID_SIZE(dataSize, sizeof(T));
+ T *t = reinterpret_cast<T *>(data);
+ new (t) T();
+ return true;
+ }
+
+ bool init(int type, void *data, size_t dataSize)
+ {
+ switch (type) {
+ case QMetaType::QColor:
+ return typedInit<QColor>(data, dataSize);
+ case QMetaType::QFont:
+ return typedInit<QFont>(data, dataSize);
+ case QMetaType::QVector2D:
+ return typedInit<QVector2D>(data, dataSize);
+ case QMetaType::QVector3D:
+ return typedInit<QVector3D>(data, dataSize);
+ case QMetaType::QVector4D:
+ return typedInit<QVector4D>(data, dataSize);
+ case QMetaType::QQuaternion:
+ return typedInit<QQuaternion>(data, dataSize);
+ case QMetaType::QMatrix4x4:
+ {
+ if (dataSize >= sizeof(QMatrix4x4))
+ return typedInit<QMatrix4x4>(data, dataSize);
+
+ // special case: init matrix-containing qvariant.
+ Q_ASSERT(dataSize >= sizeof(QVariant));
+ QVariant *matvar = reinterpret_cast<QVariant *>(data);
+ new (matvar) QVariant(QMatrix4x4());
return true;
+ }
+ default: break;
}
return false;
}
- bool destroy(int type, void *data, size_t n)
+ template<typename T>
+ bool typedDestroy(void *data, size_t dataSize)
{
- if (type == QMetaType::QColor) {
- Q_ASSERT(n >= sizeof(QColor));
- QColor *color = reinterpret_cast<QColor *>(data);
- color->~QColor();
+ ASSERT_VALID_SIZE(dataSize, sizeof(T));
+ T *t = reinterpret_cast<T *>(data);
+ t->~T();
+ return true;
+ }
+
+ bool destroy(int type, void *data, size_t dataSize)
+ {
+ switch (type) {
+ case QMetaType::QColor:
+ return typedDestroy<QColor>(data, dataSize);
+ case QMetaType::QFont:
+ return typedDestroy<QFont>(data, dataSize);
+ case QMetaType::QVector2D:
+ return typedDestroy<QVector2D>(data, dataSize);
+ case QMetaType::QVector3D:
+ return typedDestroy<QVector3D>(data, dataSize);
+ case QMetaType::QVector4D:
+ return typedDestroy<QVector4D>(data, dataSize);
+ case QMetaType::QQuaternion:
+ return typedDestroy<QQuaternion>(data, dataSize);
+ case QMetaType::QMatrix4x4:
+ {
+ if (dataSize >= sizeof(QMatrix4x4))
+ return typedDestroy<QMatrix4x4>(data, dataSize);
+
+ // special case: destroying matrix-containing qvariant.
+ Q_ASSERT(dataSize >= sizeof(QVariant));
+ QVariant *matvar = reinterpret_cast<QVariant *>(data);
+ matvar->~QVariant();
return true;
+ }
+ default: break;
}
return false;
}
- bool copy(int type, const void *src, void *dst, size_t n)
+ template<typename T>
+ bool typedCopyConstruct(const void *src, void *dst, size_t dstSize)
{
- if (type == QMetaType::QColor) {
- Q_ASSERT(n >= sizeof(QColor));
- const QColor *srcColor = reinterpret_cast<const QColor *>(src);
- QColor *dstColor = reinterpret_cast<QColor *>(dst);
- new (dstColor) QColor(*srcColor);
+ ASSERT_VALID_SIZE(dstSize, sizeof(T));
+ const T *srcT = reinterpret_cast<const T *>(src);
+ T *destT = reinterpret_cast<T *>(dst);
+ new (destT) T(*srcT);
+ return true;
+ }
+
+ bool copy(int type, const void *src, void *dst, size_t dstSize)
+ {
+ switch (type) {
+ case QMetaType::QColor:
+ return typedCopyConstruct<QColor>(src, dst, dstSize);
+ case QMetaType::QFont:
+ return typedCopyConstruct<QFont>(src, dst, dstSize);
+ case QMetaType::QVector2D:
+ return typedCopyConstruct<QVector2D>(src, dst, dstSize);
+ case QMetaType::QVector3D:
+ return typedCopyConstruct<QVector3D>(src, dst, dstSize);
+ case QMetaType::QVector4D:
+ return typedCopyConstruct<QVector4D>(src, dst, dstSize);
+ case QMetaType::QQuaternion:
+ return typedCopyConstruct<QQuaternion>(src, dst, dstSize);
+ case QMetaType::QMatrix4x4:
+ {
+ if (dstSize >= sizeof(QMatrix4x4))
+ return typedCopyConstruct<QMatrix4x4>(src, dst, dstSize);
+
+ // special case: copying matrix into variant.
+ Q_ASSERT(dstSize >= sizeof(QVariant));
+ const QMatrix4x4 *srcMatrix = reinterpret_cast<const QMatrix4x4 *>(src);
+ QVariant *dstMatrixVar = reinterpret_cast<QVariant *>(dst);
+ new (dstMatrixVar) QVariant(*srcMatrix);
return true;
+ }
+ default: break;
}
return false;
@@ -301,6 +554,16 @@ public:
bool create(int type, int argc, const void *argv[], QVariant *v)
{
switch (type) {
+ case QMetaType::QFont: // must specify via js-object.
+ break;
+ case QMetaType::QVector2D:
+ if (argc == 1) {
+ const float *xy = reinterpret_cast<const float*>(argv[0]);
+ QVector2D v2(xy[0], xy[1]);
+ *v = QVariant(v2);
+ return true;
+ }
+ break;
case QMetaType::QVector3D:
if (argc == 1) {
const float *xyz = reinterpret_cast<const float*>(argv[0]);
@@ -317,37 +580,66 @@ public:
return true;
}
break;
+ case QMetaType::QQuaternion:
+ if (argc == 1) {
+ const double *sxyz = reinterpret_cast<const double*>(argv[0]);
+ QQuaternion q(sxyz[0], sxyz[1], sxyz[2], sxyz[3]);
+ *v = QVariant(q);
+ return true;
+ }
+ break;
+ case QMetaType::QMatrix4x4:
+ if (argc == 1) {
+ const float *vals = reinterpret_cast<const float*>(argv[0]);
+ QMatrix4x4 m(vals[0], vals[1], vals[2], vals[3],
+ vals[4], vals[5], vals[6], vals[7],
+ vals[8], vals[9], vals[10], vals[11],
+ vals[12], vals[13], vals[14], vals[15]);
+ *v = QVariant(m);
+ return true;
+ }
+ break;
+ default: break;
}
return false;
}
- bool createFromString(int type, const QString &s, void *data, size_t n)
+ template<typename T>
+ bool createFromStringTyped(void *data, size_t dataSize, T initValue)
+ {
+ ASSERT_VALID_SIZE(dataSize, sizeof(T));
+ T *t = reinterpret_cast<T *>(data);
+ new (t) T(initValue);
+ return true;
+ }
+
+ bool createFromString(int type, const QString &s, void *data, size_t dataSize)
{
bool ok = false;
switch (type) {
case QMetaType::QColor:
- {
- Q_ASSERT(n >= sizeof(QColor));
- QColor *color = reinterpret_cast<QColor *>(data);
- new (color) QColor(QQuickColorProvider::QColorFromString(s));
- return true;
- }
+ return createFromStringTyped<QColor>(data, dataSize, QQuickColorProvider::QColorFromString(s));
+ case QMetaType::QVector2D:
+ return createFromStringTyped<QVector2D>(data, dataSize, vector2DFromString(s, &ok));
case QMetaType::QVector3D:
- {
- Q_ASSERT(n >= sizeof(QVector3D));
- QVector3D *v3 = reinterpret_cast<QVector3D *>(data);
- new (v3) QVector3D(vector3DFromString(s, &ok));
- return true;
- }
+ return createFromStringTyped<QVector3D>(data, dataSize, vector3DFromString(s, &ok));
case QMetaType::QVector4D:
+ return createFromStringTyped<QVector4D>(data, dataSize, vector4DFromString(s, &ok));
+ case QMetaType::QQuaternion:
+ return createFromStringTyped<QQuaternion>(data, dataSize, quaternionFromString(s, &ok));
+ case QMetaType::QMatrix4x4:
{
- Q_ASSERT(n >= sizeof(QVector4D));
- QVector4D *v4 = reinterpret_cast<QVector4D *>(data);
- new (v4) QVector4D(vector4DFromString(s, &ok));
+ if (dataSize >= sizeof(QMatrix4x4))
+ return createFromStringTyped<QMatrix4x4>(data, dataSize, matrix4x4FromString(s, &ok));
+
+ Q_ASSERT(dataSize >= sizeof(QVariant));
+ QVariant *matVar = reinterpret_cast<QVariant *>(data);
+ new (matVar) QVariant(matrix4x4FromString(s, &ok));
return true;
}
+ default: break;
}
return false;
@@ -374,6 +666,12 @@ public:
bool ok = false;
+ QVector2D v2 = vector2DFromString(s, &ok);
+ if (ok) {
+ *v = QVariant::fromValue(v2);
+ return true;
+ }
+
QVector3D v3 = vector3DFromString(s, &ok);
if (ok) {
*v = QVariant::fromValue(v3);
@@ -386,6 +684,18 @@ public:
return true;
}
+ QQuaternion q = quaternionFromString(s, &ok);
+ if (ok) {
+ *v = QVariant::fromValue(q);
+ return true;
+ }
+
+ QMatrix4x4 m = matrix4x4FromString(s, &ok);
+ if (ok) {
+ *v = QVariant::fromValue(m);
+ return true;
+ }
+
return false;
}
@@ -400,99 +710,245 @@ public:
*v = QVariant::fromValue(c);
return true;
}
+ case QMetaType::QVector2D:
+ {
+ *v = QVariant::fromValue(vector2DFromString(s, &ok));
+ return true;
+ }
case QMetaType::QVector3D:
+ {
*v = QVariant::fromValue(vector3DFromString(s, &ok));
return true;
+ }
case QMetaType::QVector4D:
+ {
*v = QVariant::fromValue(vector4DFromString(s, &ok));
return true;
+ }
+ case QMetaType::QQuaternion:
+ {
+ *v = QVariant::fromValue(quaternionFromString(s, &ok));
+ return true;
+ }
+ case QMetaType::QMatrix4x4:
+ {
+ *v = QVariant::fromValue(matrix4x4FromString(s, &ok));
+ return true;
+ }
+ default:
+ break;
}
return false;
}
+ bool variantFromJsObject(int type, QQmlV8Handle object, QV8Engine *e, QVariant *v)
+ {
+ // must be called with a valid v8 context.
+ Q_ASSERT(object.toHandle()->IsObject());
+ bool ok = false;
+ switch (type) {
+ case QMetaType::QFont:
+ *v = QVariant::fromValue(fontFromObject(object, e, &ok));
+ break;
+ case QMetaType::QMatrix4x4:
+ *v = QVariant::fromValue(matrix4x4FromObject(object, &ok));
+ default: break;
+ }
+
+ return ok;
+ }
+
template<typename T>
bool typedEqual(const void *lhs, const void *rhs)
{
return (*(reinterpret_cast<const T *>(lhs)) == *(reinterpret_cast<const T *>(rhs)));
}
- bool equal(int type, const void *lhs, const void *rhs)
+ bool equal(int type, const void *lhs, const void *rhs, size_t rhsSize)
{
switch (type) {
case QMetaType::QColor:
return typedEqual<QColor>(lhs, rhs);
+ case QMetaType::QFont:
+ return typedEqual<QFont>(lhs, rhs);
+ case QMetaType::QVector2D:
+ return typedEqual<QVector2D>(lhs, rhs);
case QMetaType::QVector3D:
return typedEqual<QVector3D>(lhs, rhs);
case QMetaType::QVector4D:
return typedEqual<QVector4D>(lhs, rhs);
+ case QMetaType::QQuaternion:
+ return typedEqual<QQuaternion>(lhs, rhs);
+ case QMetaType::QMatrix4x4:
+ {
+ if (rhsSize >= sizeof(QMatrix4x4))
+ return typedEqual<QMatrix4x4>(lhs, rhs);
+
+ Q_ASSERT(rhsSize >= sizeof(QVariant));
+ QMatrix4x4 rhsmat = reinterpret_cast<const QVariant *>(rhs)->value<QMatrix4x4>();
+ return typedEqual<QMatrix4x4>(lhs, &rhsmat);
+ }
+ default: break;
}
return false;
}
- bool store(int type, const void *src, void *dst, size_t n)
+ template<typename T>
+ bool typedStore(const void *src, void *dst, size_t dstSize)
+ {
+ ASSERT_VALID_SIZE(dstSize, sizeof(T));
+ const T *srcT = reinterpret_cast<const T *>(src);
+ T *dstT = reinterpret_cast<T *>(dst);
+ new (dstT) T(*srcT);
+ return true;
+ }
+
+ bool store(int type, const void *src, void *dst, size_t dstSize)
{
switch (type) {
case QMetaType::QColor:
{
- Q_ASSERT(n >= sizeof(QColor));
+ Q_ASSERT(dstSize >= sizeof(QColor));
const QRgb *rgb = reinterpret_cast<const QRgb *>(src);
QColor *color = reinterpret_cast<QColor *>(dst);
new (color) QColor(QColor::fromRgba(*rgb));
return true;
}
+ case QMetaType::QFont:
+ return typedStore<QFont>(src, dst, dstSize);
+ case QMetaType::QVector2D:
+ return typedStore<QVector2D>(src, dst, dstSize);
case QMetaType::QVector3D:
- {
- Q_ASSERT(n >= sizeof(QVector3D));
- const QVector3D *srcVector = reinterpret_cast<const QVector3D *>(src);
- QVector3D *dstVector = reinterpret_cast<QVector3D *>(dst);
- new (dstVector) QVector3D(*srcVector);
- return true;
- }
+ return typedStore<QVector3D>(src, dst, dstSize);
case QMetaType::QVector4D:
+ return typedStore<QVector4D>(src, dst, dstSize);
+ case QMetaType::QQuaternion:
+ return typedStore<QQuaternion>(src, dst, dstSize);
+ case QMetaType::QMatrix4x4:
{
- Q_ASSERT(n >= sizeof(QVector4D));
- const QVector4D *srcVector = reinterpret_cast<const QVector4D *>(src);
- QVector4D *dstVector = reinterpret_cast<QVector4D *>(dst);
- new (dstVector) QVector4D(*srcVector);
+ if (dstSize >= sizeof(QMatrix4x4))
+ return typedStore<QMatrix4x4>(src, dst, dstSize);
+
+ // special case: storing matrix into variant
+ // eg, QVMEMO QVMEVariant data cell is big enough to store
+ // QVariant, but not large enough to store QMatrix4x4.
+ Q_ASSERT(dstSize >= sizeof(QVariant));
+ const QMatrix4x4 *srcMat = reinterpret_cast<const QMatrix4x4 *>(src);
+ QVariant *dstMatVar = reinterpret_cast<QVariant *>(dst);
+ new (dstMatVar) QVariant(*srcMat);
return true;
}
+ default: break;
}
return false;
}
- bool read(int srcType, const void *src, int dstType, void *dst)
+ template<typename T>
+ bool typedRead(int srcType, const void *src, size_t srcSize, int dstType, void *dst)
+ {
+ T *dstT = reinterpret_cast<T *>(dst);
+ if (srcType == dstType) {
+ ASSERT_VALID_SIZE(srcSize, sizeof(T));
+ const T *srcT = reinterpret_cast<const T *>(src);
+ *dstT = *srcT;
+ } else {
+ *dstT = T();
+ }
+ return true;
+ }
+
+ bool read(int srcType, const void *src, size_t srcSize, int dstType, void *dst)
{
- if (dstType == QMetaType::QColor) {
- QColor *dstColor = reinterpret_cast<QColor *>(dst);
- if (srcType == QMetaType::QColor) {
- const QColor *srcColor = reinterpret_cast<const QColor *>(src);
- *dstColor = *srcColor;
+ switch (dstType) {
+ case QMetaType::QColor:
+ return typedRead<QColor>(srcType, src, srcSize, dstType, dst);
+ case QMetaType::QFont:
+ return typedRead<QFont>(srcType, src, srcSize, dstType, dst);
+ case QMetaType::QVector2D:
+ return typedRead<QVector2D>(srcType, src, srcSize, dstType, dst);
+ case QMetaType::QVector3D:
+ return typedRead<QVector3D>(srcType, src, srcSize, dstType, dst);
+ case QMetaType::QVector4D:
+ return typedRead<QVector4D>(srcType, src, srcSize, dstType, dst);
+ case QMetaType::QQuaternion:
+ return typedRead<QQuaternion>(srcType, src, srcSize, dstType, dst);
+ case QMetaType::QMatrix4x4:
+ {
+ if (srcSize >= sizeof(QMatrix4x4))
+ return typedRead<QMatrix4x4>(srcType, src, srcSize, dstType, dst);
+
+ // the source data may be stored in a QVariant.
+ QMatrix4x4 *dstMat = reinterpret_cast<QMatrix4x4 *>(dst);
+ if (srcType == dstType) {
+ Q_ASSERT(srcSize >= sizeof(QVariant));
+ const QVariant *srcMatVar = reinterpret_cast<const QVariant *>(src);
+ *dstMat = srcMatVar->value<QMatrix4x4>();
} else {
- *dstColor = QColor();
+ *dstMat = QMatrix4x4();
}
return true;
+ }
+ default: break;
}
return false;
}
- bool write(int type, const void *src, void *dst, size_t n)
+ template<typename T>
+ bool typedWrite(const void *src, void *dst, size_t dstSize)
{
- if (type == QMetaType::QColor) {
- Q_ASSERT(n >= sizeof(QColor));
- const QColor *srcColor = reinterpret_cast<const QColor *>(src);
- QColor *dstColor = reinterpret_cast<QColor *>(dst);
- if (*dstColor != *srcColor) {
- *dstColor = *srcColor;
+ ASSERT_VALID_SIZE(dstSize, sizeof(T));
+ const T *srcT = reinterpret_cast<const T *>(src);
+ T *dstT = reinterpret_cast<T *>(dst);
+ if (*dstT != *srcT) {
+ *dstT = *srcT;
+ return true;
+ }
+ return false;
+ }
+
+ bool write(int type, const void *src, void *dst, size_t dstSize)
+ {
+ switch (type) {
+ case QMetaType::QColor:
+ return typedWrite<QColor>(src, dst, dstSize);
+ case QMetaType::QFont:
+ return typedWrite<QFont>(src, dst, dstSize);
+ case QMetaType::QVector2D:
+ return typedWrite<QVector2D>(src, dst, dstSize);
+ case QMetaType::QVector3D:
+ return typedWrite<QVector3D>(src, dst, dstSize);
+ case QMetaType::QVector4D:
+ return typedWrite<QVector4D>(src, dst, dstSize);
+ case QMetaType::QQuaternion:
+ return typedWrite<QQuaternion>(src, dst, dstSize);
+ case QMetaType::QMatrix4x4:
+ {
+ if (dstSize >= sizeof(QMatrix4x4))
+ return typedWrite<QMatrix4x4>(src, dst, dstSize);
+
+ // special case: storing matrix into variant
+ // eg, QVMEMO QVMEVariant data cell is big enough to store
+ // QVariant, but not large enough to store QMatrix4x4.
+ Q_ASSERT(dstSize >= sizeof(QVariant));
+ const QMatrix4x4 *srcMat = reinterpret_cast<const QMatrix4x4 *>(src);
+ QVariant *dstMatVar = reinterpret_cast<QVariant *>(dst);
+ QMatrix4x4 dstMatVal = dstMatVar->value<QMatrix4x4>();
+ if (dstMatVal != *srcMat) {
+ *dstMatVar = QVariant(*srcMat);
return true;
}
+ return false;
+ }
+ default: break;
}
return false;
}
+#undef ASSERT_VALID_SIZE
};
diff --git a/src/quick/util/qquickvaluetypes.cpp b/src/quick/util/qquickvaluetypes.cpp
index e3da2658b4..4224847311 100644
--- a/src/quick/util/qquickvaluetypes.cpp
+++ b/src/quick/util/qquickvaluetypes.cpp
@@ -57,7 +57,7 @@ namespace QQuickValueTypes {
}
QQuickColorValueType::QQuickColorValueType(QObject *parent)
- : QQmlValueTypeBase<QColor>(parent)
+ : QQmlValueTypeBase<QColor>(QMetaType::QColor, parent)
{
}
@@ -109,7 +109,7 @@ void QQuickColorValueType::setA(qreal a)
QQuickVector2DValueType::QQuickVector2DValueType(QObject *parent)
- : QQmlValueTypeBase<QVector2D>(parent)
+ : QQmlValueTypeBase<QVector2D>(QMetaType::QVector2D, parent)
{
}
@@ -140,7 +140,7 @@ void QQuickVector2DValueType::setY(qreal y)
QQuickVector3DValueType::QQuickVector3DValueType(QObject *parent)
- : QQmlValueTypeBase<QVector3D>(parent)
+ : QQmlValueTypeBase<QVector3D>(QMetaType::QVector3D, parent)
{
}
@@ -181,7 +181,7 @@ void QQuickVector3DValueType::setZ(qreal z)
QQuickVector4DValueType::QQuickVector4DValueType(QObject *parent)
- : QQmlValueTypeBase<QVector4D>(parent)
+ : QQmlValueTypeBase<QVector4D>(QMetaType::QVector4D, parent)
{
}
@@ -232,7 +232,7 @@ void QQuickVector4DValueType::setW(qreal w)
QQuickQuaternionValueType::QQuickQuaternionValueType(QObject *parent)
- : QQmlValueTypeBase<QQuaternion>(parent)
+ : QQmlValueTypeBase<QQuaternion>(QMetaType::QQuaternion, parent)
{
}
@@ -283,7 +283,7 @@ void QQuickQuaternionValueType::setZ(qreal z)
QQuickMatrix4x4ValueType::QQuickMatrix4x4ValueType(QObject *parent)
- : QQmlValueTypeBase<QMatrix4x4>(parent)
+ : QQmlValueTypeBase<QMatrix4x4>(QMetaType::QMatrix4x4, parent)
{
}
@@ -298,7 +298,7 @@ QString QQuickMatrix4x4ValueType::toString() const
QQuickFontValueType::QQuickFontValueType(QObject *parent)
- : QQmlValueTypeBase<QFont>(parent),
+ : QQmlValueTypeBase<QFont>(QMetaType::QFont, parent),
pixelSizeSet(false),
pointSizeSet(false)
{
diff --git a/tests/auto/qml/qml.pro b/tests/auto/qml/qml.pro
index 48613a4ce5..2c5d367b88 100644
--- a/tests/auto/qml/qml.pro
+++ b/tests/auto/qml/qml.pro
@@ -38,6 +38,7 @@ PRIVATETESTS += \
qqmlpropertymap \
qqmlsqldatabase \
qqmlvaluetypes \
+ qqmlvaluetypeproviders \
qquickbinding \
qquickchangeset \
qquickconnection \
diff --git a/tests/auto/qml/qqmlglobal/tst_qqmlglobal.cpp b/tests/auto/qml/qqmlglobal/tst_qqmlglobal.cpp
index e2cdd50883..e32c13b98e 100644
--- a/tests/auto/qml/qqmlglobal/tst_qqmlglobal.cpp
+++ b/tests/auto/qml/qqmlglobal/tst_qqmlglobal.cpp
@@ -53,7 +53,6 @@ public:
private slots:
void initTestCase();
- void valueTypeProviderWarning();
void colorProviderWarning();
void guiProviderWarning();
};
@@ -62,13 +61,6 @@ void tst_qqmlglobal::initTestCase()
{
}
-void tst_qqmlglobal::valueTypeProviderWarning()
-{
- const QLatin1String expected("Warning: QQml_valueTypeProvider: no value type provider has been set! ");
- QTest::ignoreMessage(QtWarningMsg, expected.data());
- QQml_valueTypeProvider();
-}
-
void tst_qqmlglobal::colorProviderWarning()
{
const QLatin1String expected("Warning: QQml_colorProvider: no color provider has been set! ");
diff --git a/tests/auto/qml/qqmlqt/data/font.qml b/tests/auto/qml/qqmlqt/data/font.qml
new file mode 100644
index 0000000000..9ebf460caf
--- /dev/null
+++ b/tests/auto/qml/qqmlqt/data/font.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.0
+
+QtObject {
+ property variant test1: Qt.font({ family: "Arial", pointSize: 22 });
+ property variant test2: Qt.font({ family: "Arial", pointSize: 20, weight: Font.DemiBold, italic: true });
+ property variant test3: Qt.font("Arial", 22);
+ property variant test4: Qt.font({ something: "Arial", other: 22 });
+}
diff --git a/tests/auto/qml/qqmlqt/data/matrix4x4.qml b/tests/auto/qml/qqmlqt/data/matrix4x4.qml
new file mode 100644
index 0000000000..0185fcb635
--- /dev/null
+++ b/tests/auto/qml/qqmlqt/data/matrix4x4.qml
@@ -0,0 +1,9 @@
+import QtQuick 2.0
+
+QtObject {
+ property variant test1: Qt.matrix4x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
+ property variant test2: Qt.matrix4x4([1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4]);
+ property variant test3: Qt.matrix4x4(1,2,3,4,5,6);
+ property variant test4: Qt.matrix4x4([1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5]);
+ property variant test5: Qt.matrix4x4({ test: 5, subprop: "hello" });
+}
diff --git a/tests/auto/qml/qqmlqt/data/quaternion.qml b/tests/auto/qml/qqmlqt/data/quaternion.qml
new file mode 100644
index 0000000000..6203bd1e32
--- /dev/null
+++ b/tests/auto/qml/qqmlqt/data/quaternion.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.0
+
+QtObject {
+ property variant test1: Qt.quaternion(2, 17, 0.9, 0.6);
+ property variant test2: Qt.quaternion(102, -10, -982.1, 10);
+ property variant test3: Qt.quaternion(102, -10, -982.1);
+ property variant test4: Qt.quaternion(102, -10, -982.1, 10, 15);
+}
diff --git a/tests/auto/qml/qqmlqt/data/vector2.qml b/tests/auto/qml/qqmlqt/data/vector2.qml
new file mode 100644
index 0000000000..1ca513eaba
--- /dev/null
+++ b/tests/auto/qml/qqmlqt/data/vector2.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.0
+
+QtObject {
+ property variant test1: Qt.vector2d(1, 0.9);
+ property variant test2: Qt.vector2d(102, -982.1);
+ property variant test3: Qt.vector2d(102);
+ property variant test4: Qt.vector2d(102, -982.1, 10);
+}
diff --git a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
index c81e6771b8..6fd6fc8822 100644
--- a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
+++ b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
@@ -48,12 +48,15 @@
#include <QQmlComponent>
#include <QDesktopServices>
#include <QDir>
-#include <QVector3D>
#include <QCryptographicHash>
#include <QtQuick/QQuickItem>
#include <QSignalSpy>
+#include <QVector2D>
#include <QVector3D>
#include <QVector4D>
+#include <QQuaternion>
+#include <QMatrix4x4>
+#include <QFont>
#include "../../shared/util.h"
class tst_qqmlqt : public QQmlDataTest
@@ -69,8 +72,12 @@ private slots:
void rect();
void point();
void size();
- void vector();
+ void vector2d();
+ void vector3d();
void vector4d();
+ void quaternion();
+ void matrix4x4();
+ void font();
void lighter();
void darker();
void tint();
@@ -217,12 +224,32 @@ void tst_qqmlqt::size()
delete object;
}
-void tst_qqmlqt::vector()
+void tst_qqmlqt::vector2d()
+{
+ QQmlComponent component(&engine, testFileUrl("vector2.qml"));
+
+ QString warning1 = component.url().toString() + ":6: Error: Qt.vector2d(): Invalid arguments";
+ QString warning2 = component.url().toString() + ":7: Error: Qt.vector2d(): Invalid arguments";
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
+
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(qvariant_cast<QVector2D>(object->property("test1")), QVector2D(1, 0.9));
+ QCOMPARE(qvariant_cast<QVector2D>(object->property("test2")), QVector2D(102, -982.1));
+ QCOMPARE(qvariant_cast<QVector2D>(object->property("test3")), QVector2D());
+ QCOMPARE(qvariant_cast<QVector2D>(object->property("test4")), QVector2D());
+
+ delete object;
+}
+
+void tst_qqmlqt::vector3d()
{
QQmlComponent component(&engine, testFileUrl("vector.qml"));
- QString warning1 = component.url().toString() + ":6: Error: Qt.vector(): Invalid arguments";
- QString warning2 = component.url().toString() + ":7: Error: Qt.vector(): Invalid arguments";
+ QString warning1 = component.url().toString() + ":6: Error: Qt.vector3d(): Invalid arguments";
+ QString warning2 = component.url().toString() + ":7: Error: Qt.vector3d(): Invalid arguments";
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
@@ -257,6 +284,69 @@ void tst_qqmlqt::vector4d()
delete object;
}
+void tst_qqmlqt::quaternion()
+{
+ QQmlComponent component(&engine, testFileUrl("quaternion.qml"));
+
+ QString warning1 = component.url().toString() + ":6: Error: Qt.quaternion(): Invalid arguments";
+ QString warning2 = component.url().toString() + ":7: Error: Qt.quaternion(): Invalid arguments";
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
+
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(qvariant_cast<QQuaternion>(object->property("test1")), QQuaternion(2, 17, 0.9, 0.6));
+ QCOMPARE(qvariant_cast<QQuaternion>(object->property("test2")), QQuaternion(102, -10, -982.1, 10));
+ QCOMPARE(qvariant_cast<QQuaternion>(object->property("test3")), QQuaternion());
+ QCOMPARE(qvariant_cast<QQuaternion>(object->property("test4")), QQuaternion());
+
+ delete object;
+}
+
+void tst_qqmlqt::matrix4x4()
+{
+ QQmlComponent component(&engine, testFileUrl("matrix4x4.qml"));
+
+ QString warning1 = component.url().toString() + ":6: Error: Qt.matrix4x4(): Invalid arguments";
+ QString warning2 = component.url().toString() + ":7: Error: Qt.matrix4x4(): Invalid argument: not a valid matrix4x4 values array";
+ QString warning3 = component.url().toString() + ":8: Error: Qt.matrix4x4(): Invalid argument: not a valid matrix4x4 values array";
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning3));
+
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(qvariant_cast<QMatrix4x4>(object->property("test1")), QMatrix4x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16));
+ QCOMPARE(qvariant_cast<QMatrix4x4>(object->property("test2")), QMatrix4x4(1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4));
+ QCOMPARE(qvariant_cast<QMatrix4x4>(object->property("test3")), QMatrix4x4());
+ QCOMPARE(qvariant_cast<QMatrix4x4>(object->property("test4")), QMatrix4x4());
+ QCOMPARE(qvariant_cast<QMatrix4x4>(object->property("test5")), QMatrix4x4());
+
+ delete object;
+}
+
+void tst_qqmlqt::font()
+{
+ QQmlComponent component(&engine, testFileUrl("font.qml"));
+
+ QString warning1 = component.url().toString() + ":6: Error: Qt.font(): Invalid arguments";
+ QString warning2 = component.url().toString() + ":7: Error: Qt.font(): Invalid argument: no valid font subproperties specified";
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
+
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(qvariant_cast<QFont>(object->property("test1")), QFont("Arial", 22));
+ QCOMPARE(qvariant_cast<QFont>(object->property("test2")), QFont("Arial", 20, QFont::DemiBold, true));
+ QCOMPARE(qvariant_cast<QFont>(object->property("test3")), QFont());
+ QCOMPARE(qvariant_cast<QFont>(object->property("test4")), QFont());
+
+ delete object;
+}
+
void tst_qqmlqt::lighter()
{
QQmlComponent component(&engine, testFileUrl("lighter.qml"));
diff --git a/tests/auto/qml/qqmlvaluetypeproviders/data/comparisonSemantics.qml b/tests/auto/qml/qqmlvaluetypeproviders/data/comparisonSemantics.qml
new file mode 100644
index 0000000000..e37cf9bc8d
--- /dev/null
+++ b/tests/auto/qml/qqmlvaluetypeproviders/data/comparisonSemantics.qml
@@ -0,0 +1,95 @@
+import QtQuick 2.0
+
+QtObject {
+ property bool comparisonSuccess: false
+
+ property date d: new Date(1999, 8, 8)
+ property date d2: new Date(1998, 8, 8)
+
+ property rect g: Qt.rect(1, 2, 3, 4)
+ property rect g2: Qt.rect(5, 6, 7, 8)
+ property point p: Qt.point(1, 2)
+ property point p2: Qt.point(3, 4)
+ property size z: Qt.size(1, 2)
+ property size z2: Qt.size(3, 4)
+
+ property vector2d v2: Qt.vector2d(1,2)
+ property vector2d v22: Qt.vector2d(3,4)
+ property vector3d v3: Qt.vector3d(1,2,3)
+ property vector3d v32: Qt.vector3d(4,5,6)
+ property vector4d v4: Qt.vector4d(1,2,3,4)
+ property vector4d v42: Qt.vector4d(5,6,7,8)
+ property quaternion q: Qt.quaternion(1,2,3,4)
+ property quaternion q2: Qt.quaternion(5,6,7,8)
+ property matrix4x4 m: Qt.matrix4x4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)
+ property matrix4x4 m2: Qt.matrix4x4(21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36)
+ property color c: "red"
+ property color c2: "blue"
+ property font f: Qt.font({family: "Arial", pointSize: 20})
+ property font f2: Qt.font({family: "Arial", pointSize: 22})
+
+ Component.onCompleted: {
+ comparisonSuccess = true;
+
+ // same type comparison.
+ if (d == d2) comparisonSuccess = false;
+ d = d2;
+ if (d == d2) comparisonSuccess = false; // QML date uses same comparison semantics as JS date!
+ if (d.toString() != d2.toString()) comparisonSuccess = false;
+
+ if (g == g2) comparisonSuccess = false;
+ g = g2;
+ if (g != g2) comparisonSuccess = false;
+
+ if (p == p2) comparisonSuccess = false;
+ p = p2;
+ if (p != p2) comparisonSuccess = false;
+
+ if (z == z2) comparisonSuccess = false;
+ z = z2;
+ if (z != z2) comparisonSuccess = false;
+
+ if (v2 == v22) comparisonSuccess = false;
+ v2 = v22;
+ if (v2 != v22) comparisonSuccess = false;
+
+ if (v3 == v32) comparisonSuccess = false;
+ v3 = v32;
+ if (v3 != v32) comparisonSuccess = false;
+
+ if (v4 == v42) comparisonSuccess = false;
+ v4 = v42;
+ if (v4 != v42) comparisonSuccess = false;
+
+ if (q == q2) comparisonSuccess = false;
+ q = q2;
+ if (q != q2) comparisonSuccess = false;
+
+ if (m == m2) comparisonSuccess = false;
+ m = m2;
+ if (m != m2) comparisonSuccess = false;
+
+ if (c == c2) comparisonSuccess = false;
+ c = c2;
+ if (c != c2) comparisonSuccess = false;
+
+ if (f == f2) comparisonSuccess = false;
+ f = f2;
+ if (f != f2) comparisonSuccess = false;
+
+ // cross-type comparison.
+ p = Qt.point(1,2);
+ z = Qt.size(1,2);
+ v2 = Qt.vector2d(1,2);
+ if (p == z || p == v2 || z == v2) comparisonSuccess = false;
+ if (z == p || v2 == p || v2 == z) comparisonSuccess = false;
+
+ g = Qt.rect(1,2,3,4);
+ q = Qt.quaternion(1,2,3,4);
+ v4 = Qt.vector4d(1,2,3,4);
+ if (g == q || g == v4 || q == v4) comparisonSuccess = false;
+ if (q == g || v4 == g || v4 == q) comparisonSuccess = false;
+
+ if (c == f) comparisonSuccess = false;
+ }
+}
diff --git a/tests/auto/qml/qqmlvaluetypeproviders/data/cppIntegration.qml b/tests/auto/qml/qqmlvaluetypeproviders/data/cppIntegration.qml
new file mode 100644
index 0000000000..06756f7a18
--- /dev/null
+++ b/tests/auto/qml/qqmlvaluetypeproviders/data/cppIntegration.qml
@@ -0,0 +1,98 @@
+import QtQuick 2.0
+import Test 1.0
+
+MyTypeObject {
+ property bool success: false
+
+ // the values come from the MyTypeObject property definitions,
+ // which were defined in C++.
+
+ property rect g: rectf
+ property point p: pointf
+ property size z: sizef
+
+ property vector2d v2: vector2
+ property vector3d v3: vector
+ property vector4d v4: vector4
+ property quaternion q: quaternion
+ property matrix4x4 m: matrix
+ property color c: color
+ property font f: font
+
+ Component.onCompleted: {
+ success = true;
+
+ // ensure that the semantics of the properties
+ // defined in C++ match those of the properties
+ // defined in QML, and that we can compare/assign etc.
+
+ if (g != rectf) success = false;
+ g = Qt.rect(1,2,3,4);
+ if (g == rectf) success = false;
+ g = rectf;
+ if (g != rectf) success = false;
+ g = rect;
+ if (g != rect) success = false;
+ g = rectf; // for the cpp-size value comparison.
+
+ if (p != pointf) success = false;
+ p = Qt.point(1,2);
+ if (p == pointf) success = false;
+ p = pointf;
+ if (p != pointf) success = false;
+ p = point;
+ if (p != point) success = false;
+ p = pointf; // for the cpp-size value comparison.
+
+ if (z != sizef) success = false;
+ z = Qt.size(1,2);
+ if (z == sizef) success = false;
+ z = sizef;
+ if (z != sizef) success = false;
+ z = size;
+ if (z != size) success = false;
+ z = sizef; // for the cpp-size value comparison.
+
+ if (v2 != vector2) success = false;
+ v2 = Qt.vector2d(1,2);
+ if (v2 == vector2) success = false;
+ v2 = vector2;
+ if (v2 != vector2) success = false;
+
+ if (v3 != vector) success = false;
+ v3 = Qt.vector3d(1,2,3);
+ if (v3 == vector) success = false;
+ v3 = vector;
+ if (v3 != vector) success = false;
+
+ if (v4 != vector4) success = false;
+ v4 = Qt.vector4d(1,2,3,4);
+ if (v4 == vector4) success = false;
+ v4 = vector4;
+ if (v4 != vector4) success = false;
+
+ if (q != quaternion) success = false;
+ q = Qt.quaternion(1,2,3,4);
+ if (q == quaternion) success = false;
+ q = quaternion;
+ if (q != quaternion) success = false;
+
+ if (m != matrix) success = false;
+ m = Qt.matrix4x4(120, 230, 340, 450, 560, 670, 780, 890, 900, 1010, 1120, 1230, 1340, 1450, 1560, 1670);
+ if (m == matrix) success = false;
+ m = matrix;
+ if (m != matrix) success = false;
+
+ if (c != color) success = false;
+ c = Qt.rgba(1,0,0,.5);
+ if (c == color) success = false;
+ c = color;
+ if (c != color) success = false;
+
+ if (f != font) success = false;
+ f = Qt.font({family: "Arial", pointSize: 15, weight: Font.DemiBold, italic: false});
+ if (f == font) success = false;
+ f = font;
+ if (f != font) success = false;
+ }
+}
diff --git a/tests/auto/qml/qqmlvaluetypeproviders/data/jsObjectConversion.qml b/tests/auto/qml/qqmlvaluetypeproviders/data/jsObjectConversion.qml
new file mode 100644
index 0000000000..cd51b6c8cb
--- /dev/null
+++ b/tests/auto/qml/qqmlvaluetypeproviders/data/jsObjectConversion.qml
@@ -0,0 +1,48 @@
+import QtQuick 2.0
+
+QtObject {
+ property bool qtquickTypeSuccess: false
+
+ // currently, only conversion from js object to font and matrix is supported.
+ property matrix4x4 m: Qt.matrix4x4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)
+ property matrix4x4 m2: Qt.matrix4x4([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16])
+ property font f: Qt.font({ family: "Arial", pointSize: 10, weight: Font.Bold, italic: true })
+ property font f2: Qt.font({ family: "Arial", pointSize: 10, weight: Font.Bold, italic: true })
+
+ Component.onCompleted: {
+ qtquickTypeSuccess = true;
+
+ // check that the initialisation worked
+ if (m != m2) qtquickTypeSuccess = false;
+ if (f != f2) qtquickTypeSuccess = false;
+
+ // check that assignment works
+ m = Qt.matrix4x4(1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4)
+ m2 = Qt.matrix4x4([1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4])
+ if (m != m2) qtquickTypeSuccess = false;
+ f = Qt.font({ family: "Arial", pointSize: 16, weight: Font.Black, italic: false });
+ f2 = Qt.font({ family: "Arial", pointSize: 16, weight: Font.Black, italic: false });
+ if (f != f2) qtquickTypeSuccess = false;
+
+ // ensure that equality works as required.
+ if (m2 != Qt.matrix4x4([1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4])) qtquickTypeSucces = false;
+ if (f2 != Qt.font({ family: "Arial", pointSize: 16, weight: Font.Black, italic: false })) qtquickTypeSuccess = false;
+
+ // just to ensure comparison of values from js object assigned values is consistent.
+ m = Qt.matrix4x4(5,5,5,5,2,2,2,2,3,3,3,3,4,4,4,4);
+ m2 = Qt.matrix4x4([6,6,6,6,2,2,2,2,3,3,3,3,4,4,4,4]);
+ if (m == m2) qtquickTypeSuccess = false;
+ m = Qt.matrix4x4(6,6,6,6,2,2,2,2,3,3,3,3,4,4,4,4);
+ if (m != m2) qtquickTypeSuccess = false;
+ m = Qt.matrix4x4([7,7,7,7,2,2,2,2,3,3,3,3,4,4,4,4]);
+ if (m == m2) qtquickTypeSuccess = false;
+ m = Qt.matrix4x4([6,6,6,6,2,2,2,2,3,3,3,3,4,4,4,4]);
+ if (m != m2) qtquickTypeSuccess = false;
+
+ f = Qt.font({ family: "Arial", pointSize: 10, weight: Font.Bold, italic: true });
+ f2 = Qt.font({ family: "Arial", pointSize: 16, weight: Font.Black, italic: false });
+ if (f == f2) qtquickTypeSuccess = false;
+ f = Qt.font({ family: "Arial", pointSize: 16, weight: Font.Black, italic: false });
+ if (f != f2) qtquickTypeSuccess = false;
+ }
+}
diff --git a/tests/auto/qml/qqmlvaluetypeproviders/data/qtqmlValueTypes.qml b/tests/auto/qml/qqmlvaluetypeproviders/data/qtqmlValueTypes.qml
new file mode 100644
index 0000000000..30bc92d8af
--- /dev/null
+++ b/tests/auto/qml/qqmlvaluetypeproviders/data/qtqmlValueTypes.qml
@@ -0,0 +1,48 @@
+import QtQml 2.0
+
+QtObject {
+ property bool qtqmlTypeSuccess: false
+ property bool qtquickTypeSuccess: false
+
+ property int i: 10
+ property bool b: true
+ property real r: 5.5
+ property string s: "Hello"
+
+ property date d: new Date(1999, 8, 8)
+
+ property rect g: Qt.rect(1, 2, 3, 4)
+ property point p: Qt.point(1, 2)
+ property size z: Qt.size(1, 2)
+
+ // the following property types are valid syntax in QML
+ // but their valuetype implementation is provided by QtQuick.
+ // Thus, we can define properties of the type, but not use them.
+ property vector2d v2
+ property vector3d v3
+ property vector4d v4
+ property quaternion q
+ property matrix4x4 m
+ property color c
+ property font f
+
+ Component.onCompleted: {
+ qtqmlTypeSuccess = true;
+ qtquickTypeSuccess = true;
+
+ // test that the base qtqml provided types work
+ if (i != 10) qtqmlTypeSuccess = false;
+ if (b != true) qtqmlTypeSuccess = false;
+ if (r != 5.5) qtqmlTypeSuccess = false;
+ if (s != "Hello") qtqmlTypeSuccess = false;
+ if (d.toDateString() != (new Date(1999,8,8)).toDateString()) qtqmlTypeSuccess = false;
+ if (g != Qt.rect(1, 2, 3, 4)) qtqmlTypeSuccess = false;
+ if (p != Qt.point(1, 2)) qtqmlTypeSuccess = false;
+ if (z != Qt.size(1, 2)) qtqmlTypeSuccess = false;
+
+ // This should also work, as the base value types are provided by QtQml.
+ if (g.x != 1 || g.y != 2 || g.width != 3 || g.height != 4) qtqmlTypeSuccess = false;
+ if (p.x != 1 || p.y != 2) qtqmlTypeSuccess = false;
+ if (z.width != 1 || z.height != 2) qtqmlTypeSuccess = false;
+ }
+}
diff --git a/tests/auto/qml/qqmlvaluetypeproviders/data/qtquickValueTypes.qml b/tests/auto/qml/qqmlvaluetypeproviders/data/qtquickValueTypes.qml
new file mode 100644
index 0000000000..f723dc3e2e
--- /dev/null
+++ b/tests/auto/qml/qqmlvaluetypeproviders/data/qtquickValueTypes.qml
@@ -0,0 +1,119 @@
+import QtQuick 2.0
+
+QtObject {
+ property bool qtqmlTypeSuccess: false
+ property bool qtquickTypeSuccess: false
+
+ property int i: 10
+ property bool b: true
+ property real r: 5.5
+ property string s: "Hello"
+
+ property date d: new Date(1999, 8, 8)
+
+ property rect g: Qt.rect(1, 2, 3, 4)
+ property point p: Qt.point(1, 2)
+ property size z: Qt.size(1, 2)
+
+ property vector2d v2: Qt.vector2d(1,2)
+ property vector3d v3: Qt.vector3d(1,2,3)
+ property vector4d v4: Qt.vector4d(1,2,3,4)
+ property quaternion q: Qt.quaternion(1,2,3,4)
+ property matrix4x4 m: Qt.matrix4x4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)
+ property color c: "red"
+ property color c2: "red"
+ property font f: Qt.font({ family: "Arial", pointSize: 20 })
+
+ // ensure that group property specification works as expected.
+ property font f2
+ f2.family: "Arial"
+ f2.pointSize: 45
+ f2.italic: true
+ v22.x: 5
+ v22.y: 10
+ property vector2d v22
+ property font f3 // note: cannot specify grouped subproperties inline with property declaration :-/
+ f3 {
+ family: "Arial"
+ pointSize: 45
+ italic: true
+ }
+
+ Component.onCompleted: {
+ qtqmlTypeSuccess = true;
+ qtquickTypeSuccess = true;
+
+ // check base types still work even though we imported QtQuick
+ if (i != 10) qtqmlTypeSuccess = false;
+ if (b != true) qtqmlTypeSuccess = false;
+ if (r != 5.5) qtqmlTypeSuccess = false;
+ if (s != "Hello") qtqmlTypeSuccess = false;
+ if (d.toDateString() != (new Date(1999,8,8)).toDateString()) qtqmlTypeSuccess = false;
+
+ // check language-provided value types still work.
+ if (g != Qt.rect(1, 2, 3, 4)) qtqmlTypeSuccess = false;
+ if (g.x != 1 || g.y != 2 || g.width != 3 || g.height != 4) qtqmlTypeSuccess = false;
+ if (p != Qt.point(1, 2)) qtqmlTypeSuccess = false;
+ if (p.x != 1 || p.y != 2) qtqmlTypeSuccess = false;
+ if (z != Qt.size(1, 2)) qtqmlTypeSuccess = false;
+ if (z.width != 1 || z.height != 2) qtqmlTypeSuccess = false;
+
+ // Check that the value type provider for vector3d and other non-QtQml value-types is provided by QtQuick.
+ if (v2.x != 1 || v2.y != 2) qtquickTypeSuccess = false;
+ if (v2 != Qt.vector2d(1,2)) qtquickTypeSuccess = false;
+ if (v3.x != 1 || v3.y != 2 || v3.z != 3) qtquickTypeSuccess = false;
+ if (v3 != Qt.vector3d(1,2,3)) qtquickTypeSuccess = false;
+ if (v4.x != 1 || v4.y != 2 || v4.z != 3 || v4.w != 4) qtquickTypeSuccess = false;
+ if (v4 != Qt.vector4d(1,2,3,4)) qtquickTypeSuccess = false;
+ if (q.scalar != 1 || q.x != 2 || q.y != 3 || q.z != 4) qtquickTypeSuccess = false;
+ if (q != Qt.quaternion(1,2,3,4)) qtquickTypeSuccess = false;
+ if (m != Qt.matrix4x4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)) qtquickTypeSuccess = false;
+ if (c != Qt.rgba(1,0,0,1)) qtquickTypeSuccess = false;
+ if (c != c2) qtquickTypeSuccess = false; // can compare two colors directly.
+ if (f.family != "Arial" || f.pointSize != 20) qtquickTypeSuccess = false;
+ if (f != Qt.font({ family: "Arial", pointSize: 20 })) qtquickTypeSuccess = false;
+ if (f2.family != "Arial" || f2.pointSize != 45 || f2.italic != true) qtquickTypeSuccess = false;
+ if (f2 != f3) qtquickTypeSuccess = false;
+ if (v22.x != 5 || v22.y != 10) qtquickTypeSuccess = false;
+
+ // font has some optional parameters.
+ var defaultFont = Qt.font({ family: "Arial", pointSize: 22 }); // normal should be default weight.
+ var lightFont = Qt.font({ family: "Arial", pointSize: 22, weight: Font.Light });
+ var normalFont = Qt.font({ family: "Arial", pointSize: 22, weight: Font.Normal });
+ var demiboldFont = Qt.font({ family: "Arial", pointSize: 22, weight: Font.DemiBold });
+ var boldFont = Qt.font({ family: "Arial", pointSize: 22, weight: Font.Bold });
+ var blackFont = Qt.font({ family: "Arial", pointSize: 22, weight: Font.Black });
+
+ f = Qt.font({ family: "Arial", pointSize: 22, weight: Font.Light });
+ if (f.family != "Arial" || f.pointSize != 22 || f.weight != lightFont.weight || f.weight == normalFont.weight) qtquickTypeSuccess = false;
+ f = Qt.font({ family: "Arial", pointSize: 22, weight: Font.Normal, italic: true });
+ if (f.family != "Arial" || f.pointSize != 22 || f.weight != normalFont.weight || f.italic != true) qtquickTypeSuccess = false;
+ f = Qt.font({ family: "Arial", pointSize: 22, weight: Font.DemiBold, italic: false });
+ if (f.family != "Arial" || f.pointSize != 22 || f.weight != demiboldFont.weight || f.italic != false) qtquickTypeSuccess = false;
+ f = Qt.font({ family: "Arial", pointSize: 22, weight: Font.Bold }); // italic should be false by default
+ if (f.family != "Arial" || f.pointSize != 22 || f.weight != boldFont.weight || f.italic != false) qtquickTypeSuccess = false;
+ f = Qt.font({ family: "Arial", pointSize: 22, weight: Font.Black }); // italic should be false by default
+ if (f.family != "Arial" || f.pointSize != 22 || f.weight != blackFont.weight || f.italic != false) qtquickTypeSuccess = false;
+
+ // Check the string conversion codepaths.
+ v2 = "5,6";
+ if (v2 != Qt.vector2d(5,6)) qtquickTypeSuccess = false;
+ if (v2.toString() != "QVector2D(5, 6)") qtquickTypeSuccess = false;
+ v3 = "5,6,7";
+ if (v3 != Qt.vector3d(5,6,7)) qtquickTypeSuccess = false;
+ if (v3.toString() != "QVector3D(5, 6, 7)") qtquickTypeSuccess = false;
+ v4 = "5,6,7,8";
+ if (v4 != Qt.vector4d(5,6,7,8)) qtquickTypeSuccess = false;
+ if (v4.toString() != "QVector4D(5, 6, 7, 8)") qtquickTypeSuccess = false;
+ q = "5,6,7,8";
+ if (q != Qt.quaternion(5,6,7,8)) qtquickTypeSuccess = false;
+ if (q.toString() != "QQuaternion(5, 6, 7, 8)") qtquickTypeSuccess = false;
+ m = "4,4,4,4,5,5,5,5,6,6,6,6,7,7,7,7";
+ if (m != Qt.matrix4x4(4,4,4,4,5,5,5,5,6,6,6,6,7,7,7,7)) qtquickTypeSuccess = false;
+ if (m.toString() != "QMatrix4x4(4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7)") qtquickTypeSuccess = false;
+ c = "blue";
+ if (c.toString() != Qt.rgba(0,0,1,0).toString()) qtquickTypeSuccess = false;
+ if (c.toString() != "#0000FF" && c.toString() != "#0000ff") qtquickTypeSuccess = false; // color string converter is special
+ // no string converter for fonts.
+ }
+}
diff --git a/tests/auto/qml/qqmlvaluetypeproviders/qqmlvaluetypeproviders.pro b/tests/auto/qml/qqmlvaluetypeproviders/qqmlvaluetypeproviders.pro
new file mode 100644
index 0000000000..fb670606e2
--- /dev/null
+++ b/tests/auto/qml/qqmlvaluetypeproviders/qqmlvaluetypeproviders.pro
@@ -0,0 +1,16 @@
+CONFIG += testcase
+TARGET = tst_qqmlvaluetypeproviders
+macx:CONFIG -= app_bundle
+
+HEADERS += testtypes.h
+
+SOURCES += tst_qqmlvaluetypeproviders.cpp \
+ testtypes.cpp
+
+include (../../shared/util.pri)
+
+TESTDATA = data/*
+
+CONFIG += parallel_test
+
+QT += core-private gui-private v8-private qml-private quick-private gui testlib
diff --git a/tests/auto/qml/qqmlvaluetypeproviders/testtypes.cpp b/tests/auto/qml/qqmlvaluetypeproviders/testtypes.cpp
new file mode 100644
index 0000000000..c70179744c
--- /dev/null
+++ b/tests/auto/qml/qqmlvaluetypeproviders/testtypes.cpp
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "testtypes.h"
+
+void registerTypes()
+{
+ qmlRegisterType<MyTypeObject>("Test", 1, 0, "MyTypeObject");
+}
diff --git a/tests/auto/qml/qqmlvaluetypeproviders/testtypes.h b/tests/auto/qml/qqmlvaluetypeproviders/testtypes.h
new file mode 100644
index 0000000000..bdd5ce656b
--- /dev/null
+++ b/tests/auto/qml/qqmlvaluetypeproviders/testtypes.h
@@ -0,0 +1,195 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef TESTTYPES_H
+#define TESTTYPES_H
+
+#include <QObject>
+#include <QPoint>
+#include <QPointF>
+#include <QSize>
+#include <QSizeF>
+#include <QRect>
+#include <QRectF>
+#include <QVector2D>
+#include <QVector3D>
+#include <QVector4D>
+#include <QQuaternion>
+#include <QMatrix4x4>
+#include <QFont>
+#include <QColor>
+#include <qqml.h>
+
+class MyTypeObject : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QPoint point READ point WRITE setPoint NOTIFY changed)
+ Q_PROPERTY(QPointF pointf READ pointf WRITE setPointf NOTIFY changed)
+ Q_PROPERTY(QPointF pointfpoint READ pointfpoint WRITE setPointfpoint NOTIFY changed)
+ Q_PROPERTY(QSize size READ size WRITE setSize NOTIFY changed)
+ Q_PROPERTY(QSizeF sizef READ sizef WRITE setSizef NOTIFY changed)
+ Q_PROPERTY(QSizeF sizefsize READ sizefsize WRITE setSizefsize NOTIFY changed)
+ Q_PROPERTY(QSize sizereadonly READ size NOTIFY changed)
+ Q_PROPERTY(QRect rect READ rect WRITE setRect NOTIFY changed)
+ Q_PROPERTY(QRectF rectf READ rectf WRITE setRectf NOTIFY changed)
+ Q_PROPERTY(QRectF rectfrect READ rectfrect WRITE setRectfrect NOTIFY changed)
+ Q_PROPERTY(QVector2D vector2 READ vector2 WRITE setVector2 NOTIFY changed)
+ Q_PROPERTY(QVector3D vector READ vector WRITE setVector NOTIFY changed)
+ Q_PROPERTY(QVector4D vector4 READ vector4 WRITE setVector4 NOTIFY changed)
+ Q_PROPERTY(QQuaternion quaternion READ quaternion WRITE setQuaternion NOTIFY changed)
+ Q_PROPERTY(QMatrix4x4 matrix READ matrix WRITE setMatrix NOTIFY changed)
+ Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY changed)
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY changed)
+ Q_PROPERTY(QVariant variant READ variant NOTIFY changed)
+
+public:
+ MyTypeObject() :
+ m_point(10, 4),
+ m_pointf(11.3, -10.9),
+ m_pointfpoint(10.0, 4.0),
+ m_size(1912, 1913),
+ m_sizef(0.1, 100923.2),
+ m_sizefsize(1912.0, 1913.0),
+ m_rect(2, 3, 109, 102),
+ m_rectf(103.8, 99.2, 88.1, 77.6),
+ m_rectfrect(2.0, 3.0, 109.0, 102.0),
+ m_vector2(32.88, 1.3),
+ m_vector(23.88, 3.1, 4.3),
+ m_vector4(54.2, 23.88, 3.1, 4.3),
+ m_quaternion(4.3, 54.2, 23.88, 3.1),
+ m_matrix(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)
+ {
+ m_font.setFamily("Arial");
+ m_font.setBold(true);
+ m_font.setWeight(QFont::DemiBold);
+ m_font.setItalic(true);
+ m_font.setUnderline(true);
+ m_font.setOverline(true);
+ m_font.setStrikeOut(true);
+ m_font.setPointSize(29);
+ m_font.setCapitalization(QFont::AllLowercase);
+ m_font.setLetterSpacing(QFont::AbsoluteSpacing, 10.2);
+ m_font.setWordSpacing(19.7);
+ m_color.setRedF(0.2);
+ m_color.setGreenF(0.88);
+ m_color.setBlueF(0.6);
+ m_color.setAlphaF(0.34);
+ }
+
+ QPoint m_point;
+ QPoint point() const { return m_point; }
+ void setPoint(const QPoint &v) { m_point = v; emit changed(); }
+
+ QPointF m_pointf;
+ QPointF pointf() const { return m_pointf; }
+ void setPointf(const QPointF &v) { m_pointf = v; emit changed(); }
+
+ QPointF m_pointfpoint;
+ QPointF pointfpoint() const { return m_pointfpoint; }
+ void setPointfpoint(const QPointF &v) { m_pointfpoint = v; emit changed(); }
+
+ QSize m_size;
+ QSize size() const { return m_size; }
+ void setSize(const QSize &v) { m_size = v; emit changed(); }
+
+ QSizeF m_sizef;
+ QSizeF sizef() const { return m_sizef; }
+ void setSizef(const QSizeF &v) { m_sizef = v; emit changed(); }
+
+ QSizeF m_sizefsize;
+ QSizeF sizefsize() const { return m_sizefsize; }
+ void setSizefsize(const QSizeF &v) { m_sizefsize = v; emit changed(); }
+
+ QRect m_rect;
+ QRect rect() const { return m_rect; }
+ void setRect(const QRect &v) { m_rect = v; emit changed(); }
+
+ QRectF m_rectf;
+ QRectF rectf() const { return m_rectf; }
+ void setRectf(const QRectF &v) { m_rectf = v; emit changed(); }
+
+ QRectF m_rectfrect;
+ QRectF rectfrect() const { return m_rectfrect; }
+ void setRectfrect(const QRectF &v) { m_rectfrect = v; emit changed(); }
+
+ QVector2D m_vector2;
+ QVector2D vector2() const { return m_vector2; }
+ void setVector2(const QVector2D &v) { m_vector2 = v; emit changed(); }
+
+ QVector3D m_vector;
+ QVector3D vector() const { return m_vector; }
+ void setVector(const QVector3D &v) { m_vector = v; emit changed(); }
+
+ QVector4D m_vector4;
+ QVector4D vector4() const { return m_vector4; }
+ void setVector4(const QVector4D &v) { m_vector4 = v; emit changed(); }
+
+ QQuaternion m_quaternion;
+ QQuaternion quaternion() const { return m_quaternion; }
+ void setQuaternion(const QQuaternion &v) { m_quaternion = v; emit changed(); }
+
+ QMatrix4x4 m_matrix;
+ QMatrix4x4 matrix() const { return m_matrix; }
+ void setMatrix(const QMatrix4x4 &v) { m_matrix = v; emit changed(); }
+
+ QFont m_font;
+ QFont font() const { return m_font; }
+ void setFont(const QFont &v) { m_font = v; emit changed(); }
+
+ QColor m_color;
+ QColor color() const { return m_color; }
+ void setColor(const QColor &v) { m_color = v; emit changed(); }
+
+ QVariant variant() const { return sizef(); }
+
+ void emitRunScript() { emit runScript(); }
+
+signals:
+ void changed();
+ void runScript();
+
+public slots:
+ QSize method() { return QSize(13, 14); }
+};
+
+void registerTypes();
+
+#endif // TESTTYPES_H
diff --git a/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp b/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp
new file mode 100644
index 0000000000..d811767489
--- /dev/null
+++ b/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtest.h>
+#include <QQmlEngine>
+#include <QQmlComponent>
+#include <QDebug>
+#include <private/qquickvaluetypes_p.h>
+#include "../../shared/util.h"
+#include "testtypes.h"
+
+QT_BEGIN_NAMESPACE
+extern int qt_defaultDpi(void);
+QT_END_NAMESPACE
+
+// There is some overlap between the qqmllanguage and qqmlvaluetypes
+// test here, but it needs to be separate to ensure that no QML plugins
+// are loaded prior to these tests, which could contaminate the type
+// system with more providers.
+
+class tst_qqmlvaluetypeproviders : public QQmlDataTest
+{
+ Q_OBJECT
+public:
+ tst_qqmlvaluetypeproviders() {}
+
+private slots:
+ void initTestCase();
+
+ void qtqmlValueTypes(); // This test function _must_ be the first test function run.
+ void qtquickValueTypes();
+ void comparisonSemantics();
+ void cppIntegration();
+ void jsObjectConversion();
+};
+
+void tst_qqmlvaluetypeproviders::initTestCase()
+{
+ QQmlDataTest::initTestCase();
+ registerTypes();
+}
+
+void tst_qqmlvaluetypeproviders::qtqmlValueTypes()
+{
+ QQmlEngine e;
+ QQmlComponent component(&e, testFileUrl("qtqmlValueTypes.qml"));
+ QVERIFY(!component.isError());
+ QVERIFY(component.errors().isEmpty());
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QVERIFY(object->property("qtqmlTypeSuccess").toBool());
+ QVERIFY(object->property("qtquickTypeSuccess").toBool());
+ delete object;
+}
+
+void tst_qqmlvaluetypeproviders::qtquickValueTypes()
+{
+ QQmlEngine e;
+ QQmlComponent component(&e, testFileUrl("qtquickValueTypes.qml"));
+ QVERIFY(!component.isError());
+ QVERIFY(component.errors().isEmpty());
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QVERIFY(object->property("qtqmlTypeSuccess").toBool());
+ QVERIFY(object->property("qtquickTypeSuccess").toBool());
+ delete object;
+}
+
+void tst_qqmlvaluetypeproviders::comparisonSemantics()
+{
+ QQmlEngine e;
+ QQmlComponent component(&e, testFileUrl("comparisonSemantics.qml"));
+ QVERIFY(!component.isError());
+ QVERIFY(component.errors().isEmpty());
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QVERIFY(object->property("comparisonSuccess").toBool());
+ delete object;
+}
+
+void tst_qqmlvaluetypeproviders::cppIntegration()
+{
+ QQmlEngine e;
+ QQmlComponent component(&e, testFileUrl("cppIntegration.qml"));
+ QVERIFY(!component.isError());
+ QVERIFY(component.errors().isEmpty());
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ // ensure accessing / comparing / assigning cpp-defined props
+ // and qml-defined props works in QML.
+ QVERIFY(object->property("success").toBool());
+
+ // ensure types match
+ QCOMPARE(object->property("g").userType(), object->property("rectf").userType());
+ QCOMPARE(object->property("p").userType(), object->property("pointf").userType());
+ QCOMPARE(object->property("z").userType(), object->property("sizef").userType());
+ QCOMPARE(object->property("v2").userType(), object->property("vector2").userType());
+ QCOMPARE(object->property("v3").userType(), object->property("vector").userType());
+ QCOMPARE(object->property("v4").userType(), object->property("vector4").userType());
+ QCOMPARE(object->property("q").userType(), object->property("quaternion").userType());
+ QCOMPARE(object->property("m").userType(), object->property("matrix").userType());
+ QCOMPARE(object->property("c").userType(), object->property("color").userType());
+ QCOMPARE(object->property("f").userType(), object->property("font").userType());
+
+ // ensure values match
+ QCOMPARE(object->property("g").value<QRectF>(), object->property("rectf").value<QRectF>());
+ QCOMPARE(object->property("p").value<QPointF>(), object->property("pointf").value<QPointF>());
+ QCOMPARE(object->property("z").value<QSizeF>(), object->property("sizef").value<QSizeF>());
+ QCOMPARE(object->property("v2").value<QVector2D>(), object->property("vector2").value<QVector2D>());
+ QCOMPARE(object->property("v3").value<QVector3D>(), object->property("vector").value<QVector3D>());
+ QCOMPARE(object->property("v4").value<QVector4D>(), object->property("vector4").value<QVector4D>());
+ QCOMPARE(object->property("q").value<QQuaternion>(), object->property("quaternion").value<QQuaternion>());
+ QCOMPARE(object->property("m").value<QMatrix4x4>(), object->property("matrix").value<QMatrix4x4>());
+ QCOMPARE(object->property("c").value<QColor>(), object->property("color").value<QColor>());
+ QCOMPARE(object->property("f").value<QFont>(), object->property("font").value<QFont>());
+
+ delete object;
+}
+
+void tst_qqmlvaluetypeproviders::jsObjectConversion()
+{
+ QQmlEngine e;
+ QQmlComponent component(&e, testFileUrl("jsObjectConversion.qml"));
+ QVERIFY(!component.isError());
+ QVERIFY(component.errors().isEmpty());
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QVERIFY(object->property("qtquickTypeSuccess").toBool());
+ delete object;
+}
+
+QTEST_MAIN(tst_qqmlvaluetypeproviders)
+
+#include "tst_qqmlvaluetypeproviders.moc"