Allow color to be explicitly compared to a string
authorMatthew Vogt <matthew.vogt@nokia.com>
Thu, 5 Jul 2012 06:09:27 +0000 (16:09 +1000)
committerQt by Nokia <qt-info@nokia.com>
Wed, 11 Jul 2012 15:37:55 +0000 (17:37 +0200)
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 <michael.brasser@nokia.com>
src/qml/doc/src/typesystem/basictypes.qdoc
src/qml/qml/v8/qqmlbuiltinfunctions.cpp
src/qml/qml/v8/qqmlbuiltinfunctions_p.h
src/qml/qml/v8/qv8engine.cpp
tests/auto/qml/qqmlqt/data/colorEqual.qml [new file with mode: 0644]
tests/auto/qml/qqmlqt/tst_qqmlqt.cpp

index 94ff682..0f30a8a 100644 (file)
@@ -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.
index 5abc7cf..b99d350 100644 (file)
@@ -445,6 +445,45 @@ v8::Handle<v8::Value> 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<v8::Value> 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.
index 0f43298..c05f4ed 100644 (file)
@@ -75,6 +75,7 @@ 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> colorEqual(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);
index be3c7de..7eabd96 100644 (file)
@@ -605,8 +605,8 @@ 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("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 (file)
index 0000000..c84a5b9
--- /dev/null
@@ -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')
+}
index 6fd6fc8..3497fd7 100644 (file)
@@ -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"));