From b5eb3d69b40c4b750a1bbece7be2acbe7cf918e3 Mon Sep 17 00:00:00 2001 From: Matthew Vogt Date: Thu, 5 Jul 2012 16:09:27 +1000 Subject: [PATCH] Allow color to be explicitly compared to a string Add the Qt.colorEqual() function which compares any combination of two supplied color and string arguments, by converting the string arguments to colors as necessary. Task-number: QTBUG-18754 Change-Id: I75baef9a2edd30a5f8b9cb5e151e4adba6f6a371 Reviewed-by: Michael Brasser --- src/qml/doc/src/typesystem/basictypes.qdoc | 5 ++ src/qml/qml/v8/qqmlbuiltinfunctions.cpp | 39 +++++++++++++ src/qml/qml/v8/qqmlbuiltinfunctions_p.h | 1 + src/qml/qml/v8/qv8engine.cpp | 2 +- tests/auto/qml/qqmlqt/data/colorEqual.qml | 81 +++++++++++++++++++++++++++ tests/auto/qml/qqmlqt/tst_qqmlqt.cpp | 84 ++++++++++++++++++++++++++++ 6 files changed, 211 insertions(+), 1 deletions(-) create mode 100644 tests/auto/qml/qqmlqt/data/colorEqual.qml diff --git a/src/qml/doc/src/typesystem/basictypes.qdoc b/src/qml/doc/src/typesystem/basictypes.qdoc index 94ff682..0f30a8a 100644 --- a/src/qml/doc/src/typesystem/basictypes.qdoc +++ b/src/qml/doc/src/typesystem/basictypes.qdoc @@ -293,6 +293,7 @@ property is only invoked when the property is reassigned to a different object v \qmlbasictype color \ingroup qmlbasictypes \brief an ARGB color value. + \target qmlbasictypecolor The \c color type refers to an ARGB color value. It can be specified in a number of ways: @@ -326,6 +327,10 @@ property is only invoked when the property is reassigned to a different object v } \endqml + To test color values for equality, use the \l{QML:Qt::colorEqual()}{Qt.colorEqual()} + function. This allows colors to be accurately compared whether they are in property + form or in any of the acceptable string specification forms. + When integrating with C++, note that any QColor value \l{qtqml-cppintegration-data.html}{passed into QML from C++} is automatically converted into a \c color value, and vice-versa. diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index 5abc7cf..b99d350 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -445,6 +445,45 @@ v8::Handle hsla(const v8::Arguments &args) } /*! +\qmlmethod color Qt::colorEqual(color lhs, string rhs) + +Returns true if both \c lhs and \c rhs yield equal color values. Both arguments +may be either color values or string values. If a string value is supplied it +must be convertible to a color, as described for the \l{qmlbasictypecolor}{color} +basic type. +*/ +v8::Handle colorEqual(const v8::Arguments &args) +{ + if (args.Length() != 2) + V8THROW_ERROR("Qt.colorEqual(): Invalid arguments"); + + bool ok = false; + + QVariant lhs = V8ENGINE()->toVariant(args[0], -1); + if (lhs.userType() == QVariant::String) { + lhs = QQmlStringConverters::colorFromString(lhs.toString(), &ok); + if (!ok) { + V8THROW_ERROR("Qt.colorEqual(): Invalid color name"); + } + } else if (lhs.userType() != QVariant::Color) { + V8THROW_ERROR("Qt.colorEqual(): Invalid arguments"); + } + + QVariant rhs = V8ENGINE()->toVariant(args[1], -1); + if (rhs.userType() == QVariant::String) { + rhs = QQmlStringConverters::colorFromString(rhs.toString(), &ok); + if (!ok) { + V8THROW_ERROR("Qt.colorEqual(): Invalid color name"); + } + } else if (rhs.userType() != QVariant::Color) { + V8THROW_ERROR("Qt.colorEqual(): Invalid arguments"); + } + + bool equal = (lhs == rhs); + return V8ENGINE()->fromVariant(equal); +} + +/*! \qmlmethod rect Qt::rect(int x, int y, int width, int height) Returns a \c rect with the top-left corner at \c x, \c y and the specified \c width and \c height. diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h index 0f43298..c05f4ed 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h +++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h @@ -75,6 +75,7 @@ v8::Handle consoleException(const v8::Arguments &args); v8::Handle isQtObject(const v8::Arguments &args); v8::Handle rgba(const v8::Arguments &args); v8::Handle hsla(const v8::Arguments &args); +v8::Handle colorEqual(const v8::Arguments &args); v8::Handle font(const v8::Arguments &args); v8::Handle rect(const v8::Arguments &args); v8::Handle point(const v8::Arguments &args); diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp index be3c7de..7eabd96 100644 --- a/src/qml/qml/v8/qv8engine.cpp +++ b/src/qml/qml/v8/qv8engine.cpp @@ -605,8 +605,8 @@ void QV8Engine::initializeGlobal(v8::Handle global) qt->Set(v8::String::New("isQtObject"), V8FUNCTION(isQtObject, this)); qt->Set(v8::String::New("rgba"), V8FUNCTION(rgba, this)); qt->Set(v8::String::New("hsla"), V8FUNCTION(hsla, this)); + qt->Set(v8::String::New("colorEqual"), V8FUNCTION(colorEqual, 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)); diff --git a/tests/auto/qml/qqmlqt/data/colorEqual.qml b/tests/auto/qml/qqmlqt/data/colorEqual.qml new file mode 100644 index 0000000..c84a5b9 --- /dev/null +++ b/tests/auto/qml/qqmlqt/data/colorEqual.qml @@ -0,0 +1,81 @@ +import QtQuick 2.0 + +QtObject { + property color color1 + + property bool test1a: Qt.colorEqual(color1) + property bool test1b: Qt.colorEqual('red') + + property bool test1c: Qt.colorEqual(color1, '') + property bool test1d: Qt.colorEqual('', color1) + + property bool test1e: Qt.colorEqual(color1, 7) + property bool test1f: Qt.colorEqual(7, color1) + + property var other: ({ name: 'value' }) + + property bool test1g: Qt.colorEqual(color1, other) + property bool test1h: Qt.colorEqual(other, color1) + + property color color2: 'red' + + property bool test2a: Qt.colorEqual(color2, 'red') + property bool test2b: Qt.colorEqual('red', color2) + property bool test2c: Qt.colorEqual(color2, '#f00') + property bool test2d: Qt.colorEqual('#f00', color2) + property bool test2e: Qt.colorEqual(color2, '#ff0000') + property bool test2f: Qt.colorEqual('#ff0000', color2) + property bool test2g: Qt.colorEqual(color2, '#ffff0000') + property bool test2h: Qt.colorEqual('#ffff0000', color2) + property bool test2i: Qt.colorEqual(color2, '#80ff0000') + property bool test2j: Qt.colorEqual('#80ff0000', color2) + property bool test2k: Qt.colorEqual(color2, 'blue') + property bool test2l: Qt.colorEqual('blue', color2) + property bool test2m: Qt.colorEqual(color2, 'darklightmediumgreen') + property bool test2n: Qt.colorEqual('darklightmediumgreen', color2) + + property color color3: '#f00' + + property bool test3a: Qt.colorEqual(color3, '#f00') + property bool test3b: Qt.colorEqual('#f00', color3) + property bool test3c: Qt.colorEqual(color3, '#ff0000') + property bool test3d: Qt.colorEqual('#ff0000', color3) + property bool test3e: Qt.colorEqual(color3, '#ffff0000') + property bool test3f: Qt.colorEqual('#ffff0000', color3) + property bool test3g: Qt.colorEqual(color3, '#80ff0000') + property bool test3h: Qt.colorEqual('#80ff0000', color3) + property bool test3i: Qt.colorEqual(color3, 'red') + property bool test3j: Qt.colorEqual('red', color3) + property bool test3k: Qt.colorEqual(color3, 'red') + property bool test3l: Qt.colorEqual('red', color3) + property bool test3m: Qt.colorEqual(color3, color2) + property bool test3n: Qt.colorEqual(color2, color3) + + property color color4: '#80ff0000' + + property bool test4a: Qt.colorEqual(color4, '#80ff0000') + property bool test4b: Qt.colorEqual('#80ff0000', color4) + property bool test4c: Qt.colorEqual(color4, '#00ff0000') + property bool test4d: Qt.colorEqual('#00ff0000', color4) + property bool test4e: Qt.colorEqual(color4, '#ffff0000') + property bool test4f: Qt.colorEqual('#ffff0000', color4) + property bool test4g: Qt.colorEqual(color4, 'red') + property bool test4h: Qt.colorEqual('red', color4) + // Note: these fail due to the mismatching precision of their alpha values: + property bool test4i: Qt.colorEqual(color4, Qt.rgba(1, 0, 0, 0.5)) + property bool test4j: Qt.colorEqual(Qt.rgba(1, 0, 0, 0.5), color4) + + property color color5: 'mediumturquoise' + + property bool test5a: Qt.colorEqual(color5, 'medium' + 'turquoise') + property bool test5b: Qt.colorEqual('medium' + 'turquoise', color5) + property bool test5c: Qt.colorEqual(color5, color5) + property bool test5d: Qt.colorEqual(color5, color3) + property bool test5e: Qt.colorEqual(color3, color5) + + property bool test6a: Qt.colorEqual('red', 'red') + property bool test6b: Qt.colorEqual('red', '#f00') + property bool test6c: Qt.colorEqual('#f00', 'red') + property bool test6d: Qt.colorEqual('red', 'blue') + property bool test6e: Qt.colorEqual('blue', 'red') +} diff --git a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp index 6fd6fc8..3497fd7 100644 --- a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp +++ b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp @@ -69,6 +69,7 @@ private slots: void enums(); void rgba(); void hsla(); + void colorEqual(); void rect(); void point(); void size(); @@ -162,6 +163,89 @@ void tst_qqmlqt::hsla() delete object; } +void tst_qqmlqt::colorEqual() +{ + QQmlComponent component(&engine, testFileUrl("colorEqual.qml")); + + QTest::ignoreMessage(QtWarningMsg, qPrintable(component.url().toString() + ":6: Error: Qt.colorEqual(): Invalid arguments")); + QTest::ignoreMessage(QtWarningMsg, qPrintable(component.url().toString() + ":7: Error: Qt.colorEqual(): Invalid arguments")); + QTest::ignoreMessage(QtWarningMsg, qPrintable(component.url().toString() + ":9: Error: Qt.colorEqual(): Invalid color name")); + QTest::ignoreMessage(QtWarningMsg, qPrintable(component.url().toString() + ":10: Error: Qt.colorEqual(): Invalid color name")); + QTest::ignoreMessage(QtWarningMsg, qPrintable(component.url().toString() + ":12: Error: Qt.colorEqual(): Invalid arguments")); + QTest::ignoreMessage(QtWarningMsg, qPrintable(component.url().toString() + ":13: Error: Qt.colorEqual(): Invalid arguments")); + QTest::ignoreMessage(QtWarningMsg, qPrintable(component.url().toString() + ":17: Error: Qt.colorEqual(): Invalid arguments")); + QTest::ignoreMessage(QtWarningMsg, qPrintable(component.url().toString() + ":18: Error: Qt.colorEqual(): Invalid arguments")); + QTest::ignoreMessage(QtWarningMsg, qPrintable(component.url().toString() + ":34: Error: Qt.colorEqual(): Invalid color name")); + QTest::ignoreMessage(QtWarningMsg, qPrintable(component.url().toString() + ":35: Error: Qt.colorEqual(): Invalid color name")); + + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test1a").toBool(), false); + QCOMPARE(object->property("test1b").toBool(), false); + QCOMPARE(object->property("test1c").toBool(), false); + QCOMPARE(object->property("test1d").toBool(), false); + QCOMPARE(object->property("test1e").toBool(), false); + QCOMPARE(object->property("test1f").toBool(), false); + QCOMPARE(object->property("test1g").toBool(), false); + QCOMPARE(object->property("test1h").toBool(), false); + + QCOMPARE(object->property("test2a").toBool(), true); + QCOMPARE(object->property("test2b").toBool(), true); + QCOMPARE(object->property("test2c").toBool(), true); + QCOMPARE(object->property("test2d").toBool(), true); + QCOMPARE(object->property("test2e").toBool(), true); + QCOMPARE(object->property("test2f").toBool(), true); + QCOMPARE(object->property("test2g").toBool(), true); + QCOMPARE(object->property("test2h").toBool(), true); + QCOMPARE(object->property("test2i").toBool(), false); + QCOMPARE(object->property("test2j").toBool(), false); + QCOMPARE(object->property("test2k").toBool(), false); + QCOMPARE(object->property("test2l").toBool(), false); + QCOMPARE(object->property("test2m").toBool(), false); + QCOMPARE(object->property("test2n").toBool(), false); + + QCOMPARE(object->property("test3a").toBool(), true); + QCOMPARE(object->property("test3b").toBool(), true); + QCOMPARE(object->property("test3c").toBool(), true); + QCOMPARE(object->property("test3d").toBool(), true); + QCOMPARE(object->property("test3e").toBool(), true); + QCOMPARE(object->property("test3f").toBool(), true); + QCOMPARE(object->property("test3g").toBool(), false); + QCOMPARE(object->property("test3h").toBool(), false); + QCOMPARE(object->property("test3i").toBool(), true); + QCOMPARE(object->property("test3j").toBool(), true); + QCOMPARE(object->property("test3k").toBool(), true); + QCOMPARE(object->property("test3l").toBool(), true); + QCOMPARE(object->property("test3m").toBool(), true); + QCOMPARE(object->property("test3n").toBool(), true); + + QCOMPARE(object->property("test4a").toBool(), true); + QCOMPARE(object->property("test4b").toBool(), true); + QCOMPARE(object->property("test4c").toBool(), false); + QCOMPARE(object->property("test4d").toBool(), false); + QCOMPARE(object->property("test4e").toBool(), false); + QCOMPARE(object->property("test4f").toBool(), false); + QCOMPARE(object->property("test4g").toBool(), false); + QCOMPARE(object->property("test4h").toBool(), false); + QCOMPARE(object->property("test4i").toBool(), false); + QCOMPARE(object->property("test4j").toBool(), false); + + QCOMPARE(object->property("test5a").toBool(), true); + QCOMPARE(object->property("test5b").toBool(), true); + QCOMPARE(object->property("test5c").toBool(), true); + QCOMPARE(object->property("test5d").toBool(), false); + QCOMPARE(object->property("test5e").toBool(), false); + + QCOMPARE(object->property("test6a").toBool(), true); + QCOMPARE(object->property("test6b").toBool(), true); + QCOMPARE(object->property("test6c").toBool(), true); + QCOMPARE(object->property("test6d").toBool(), false); + QCOMPARE(object->property("test6e").toBool(), false); + + delete object; +} + void tst_qqmlqt::rect() { QQmlComponent component(&engine, testFileUrl("rect.qml")); -- 1.7.2.5