Make sure QML type "real" always maps to C++ type "double"
authorKent Hansen <kent.hansen@nokia.com>
Mon, 5 Mar 2012 10:54:01 +0000 (11:54 +0100)
committerQt by Nokia <qt-info@nokia.com>
Wed, 7 Mar 2012 11:10:27 +0000 (12:10 +0100)
The type "real" was documented to be a single-precision float, but
that's incorrect. It's always been double.

However, signal parameters of type "real" would be mapped to the C++
type "qreal", which can be either float or double depending on the
platform.

Since JavaScript floating point numbers have double precision, QML
should use the same, to avoid potential loss of precision.

With this change, "real" behaves the same as the QML "double" type
(which already guaranteed double precision). Even though it's
redundant, "double" is kept to preserve compatibility.

Added tests for the "double" type to the QML meta-object autotest,
and a test for the "real" type that ensures there's no loss of
precision.

Change-Id: I1a77f1fd45082ff670684a935e17d1a46ea75d84
Reviewed-by: Aaron Kennedy <aaron.kennedy@nokia.com>
doc/src/qml/basictypes.qdoc
src/qml/qml/qqmlscript.cpp
tests/auto/qml/qqmlecmascript/data/realTypePrecision.qml [new file with mode: 0644]
tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
tests/auto/qml/qqmlmetaobject/data/property.double.qml [new file with mode: 0644]
tests/auto/qml/qqmlmetaobject/data/property.real.qml
tests/auto/qml/qqmlmetaobject/data/signal.6.qml [new file with mode: 0644]
tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp

index 0f66a96..317dd54 100644 (file)
@@ -88,7 +88,7 @@
     Item { width: 100.45; height: 150.82 }
     \endqml
 
-    \bold{Note:} In QML all reals are stored in single precision, \l
+    \bold{Note:} In QML all reals are stored in double precision, \l
     {http://en.wikipedia.org/wiki/IEEE_754} {IEEE floating point}
     format.
 
index d1c2faa..db59a72 100644 (file)
@@ -924,7 +924,7 @@ bool ProcessAST::visit(AST::UiPublicMember *node)
         { "int", strlen("int"), Object::DynamicProperty::Int, "int", strlen("int") },
         { "bool", strlen("bool"), Object::DynamicProperty::Bool, "bool", strlen("bool") },
         { "double", strlen("double"), Object::DynamicProperty::Real, "double", strlen("double") },
-        { "real", strlen("real"), Object::DynamicProperty::Real, "qreal", strlen("qreal") },
+        { "real", strlen("real"), Object::DynamicProperty::Real, "double", strlen("double") },
         { "string", strlen("string"), Object::DynamicProperty::String, "QString", strlen("QString") },
         { "url", strlen("url"), Object::DynamicProperty::Url, "QUrl", strlen("QUrl") },
         { "color", strlen("color"), Object::DynamicProperty::Color, "QColor", strlen("QColor") },
diff --git a/tests/auto/qml/qqmlecmascript/data/realTypePrecision.qml b/tests/auto/qml/qqmlecmascript/data/realTypePrecision.qml
new file mode 100644 (file)
index 0000000..5244788
--- /dev/null
@@ -0,0 +1,22 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+QtObject {
+    property real test: 1234567890
+    property real test2
+    property real test3
+    property real test4: test3
+    property real test5: func()
+    property real test6: test2 + test3
+
+    signal sig(real arg)
+
+    Component.onCompleted: {
+        test2 = 1234567890;
+        sig(1234567890)
+    }
+
+    onSig: { test3 = arg; }
+
+    function func() { return 1234567890; }
+}
index 676557a..0dc0e5a 100644 (file)
@@ -236,6 +236,7 @@ private slots:
     void revisionErrors();
     void revision();
     void invokableWithQObjectDerived();
+    void realTypePrecision();
 
     void automaticSemicolon();
     void unaryExpression();
@@ -6092,6 +6093,20 @@ void tst_qqmlecmascript::invokableWithQObjectDerived()
     }
 }
 
+void tst_qqmlecmascript::realTypePrecision()
+{
+    // Properties and signal parameters of type real should have double precision.
+    QQmlComponent component(&engine, testFileUrl("realTypePrecision.qml"));
+    QScopedPointer<QObject> object(component.create());
+    QVERIFY(object != 0);
+    QCOMPARE(object->property("test").toDouble(), 1234567890.);
+    QCOMPARE(object->property("test2").toDouble(), 1234567890.);
+    QCOMPARE(object->property("test3").toDouble(), 1234567890.);
+    QCOMPARE(object->property("test4").toDouble(), 1234567890.);
+    QCOMPARE(object->property("test5").toDouble(), 1234567890.);
+    QCOMPARE(object->property("test6").toDouble(), 1234567890.*2);
+}
+
 QTEST_MAIN(tst_qqmlecmascript)
 
 #include "tst_qqmlecmascript.moc"
diff --git a/tests/auto/qml/qqmlmetaobject/data/property.double.qml b/tests/auto/qml/qqmlmetaobject/data/property.double.qml
new file mode 100644 (file)
index 0000000..65da188
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+QtObject {
+    property double test: 1234567890
+}
index de2baf5..2268aac 100644 (file)
@@ -1,5 +1,5 @@
 import QtQuick 2.0
 
 QtObject {
-    property real test: 21
+    property real test: 1234567890
 }
diff --git a/tests/auto/qml/qqmlmetaobject/data/signal.6.qml b/tests/auto/qml/qqmlmetaobject/data/signal.6.qml
new file mode 100644 (file)
index 0000000..a4ec6c0
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+QtObject {
+    signal testSignal(double foo)
+}
index 6cadc35..f2c50dd 100644 (file)
@@ -92,12 +92,18 @@ void tst_QQmlMetaObject::property_data()
             << QByteArray("bool") << int(QMetaType::Bool)
             << true // default
             << QVariant(true) << true << QVariant(false);
+    QTest::newRow("double") << "property.double.qml"
+             << QByteArray("double") << int(QMetaType::Double)
+             << false // default
+             << QVariant(double(1234567890.))
+             << true // writable
+             << QVariant(double(1.23456789));
     QTest::newRow("real") << "property.real.qml"
             << QByteArray("double") << int(QMetaType::Double)
             << false // default
-            << QVariant(double(21))
+            << QVariant(double(1234567890.))
             << true // writable
-            << QVariant(double(37));
+            << QVariant(double(1.23456789));
     QTest::newRow("string") << "property.string.qml"
             << QByteArray("QString") << int(QMetaType::QString)
             << true // default
@@ -306,10 +312,10 @@ void tst_QQmlMetaObject::method_data()
             << (QList<QByteArray>() << "QString")
             << (QList<QByteArray>() << "foo");
     QTest::newRow("testSignal(int foo, bool bar, real baz)") << "signal.3.qml"
-            << "testSignal(int,bool,qreal)"
+            << "testSignal(int,bool,double)"
             << QMetaMethod::Signal
             << ""
-            << (QList<QByteArray>() << "int" << "bool" << "qreal")
+            << (QList<QByteArray>() << "int" << "bool" << "double")
             << (QList<QByteArray>() << "foo" << "bar" << "baz");
     QTest::newRow("testSignal(variant foo, var bar)") << "signal.4.qml"
             << "testSignal(QVariant,QVariant)"
@@ -323,6 +329,12 @@ void tst_QQmlMetaObject::method_data()
             << ""
             << (QList<QByteArray>() << "QColor" << "QDateTime" << "QUrl")
             << (QList<QByteArray>() << "foo" << "bar" << "baz");
+    QTest::newRow("testSignal(double foo)") << "signal.6.qml"
+            << "testSignal(double)"
+            << QMetaMethod::Signal
+            << ""
+            << (QList<QByteArray>() << "double")
+            << (QList<QByteArray>() << "foo");
 }
 
 void tst_QQmlMetaObject::method()