Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Make sure QML type "real" always maps to C++ type "double"
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>
  • Loading branch information
Kent Hansen authored and Qt by Nokia committed Mar 7, 2012
1 parent 3f3850e commit aed15e7
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 7 deletions.
2 changes: 1 addition & 1 deletion doc/src/qml/basictypes.qdoc
Expand Up @@ -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.

Expand Down
2 changes: 1 addition & 1 deletion src/qml/qml/qqmlscript.cpp
Expand Up @@ -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") },
Expand Down
22 changes: 22 additions & 0 deletions tests/auto/qml/qqmlecmascript/data/realTypePrecision.qml
@@ -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; }
}
15 changes: 15 additions & 0 deletions tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
Expand Up @@ -236,6 +236,7 @@ private slots:
void revisionErrors();
void revision();
void invokableWithQObjectDerived();
void realTypePrecision();

void automaticSemicolon();
void unaryExpression();
Expand Down Expand Up @@ -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"
5 changes: 5 additions & 0 deletions tests/auto/qml/qqmlmetaobject/data/property.double.qml
@@ -0,0 +1,5 @@
import QtQuick 2.0

QtObject {
property double test: 1234567890
}
2 changes: 1 addition & 1 deletion tests/auto/qml/qqmlmetaobject/data/property.real.qml
@@ -1,5 +1,5 @@
import QtQuick 2.0

QtObject {
property real test: 21
property real test: 1234567890
}
5 changes: 5 additions & 0 deletions tests/auto/qml/qqmlmetaobject/data/signal.6.qml
@@ -0,0 +1,5 @@
import QtQuick 2.0

QtObject {
signal testSignal(double foo)
}
20 changes: 16 additions & 4 deletions tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp
Expand Up @@ -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
Expand Down Expand Up @@ -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)"
Expand All @@ -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()
Expand Down

0 comments on commit aed15e7

Please sign in to comment.