Make comparison of singletons and qobjects work
authorAlbert Astals Cid <albert.astals@canonical.com>
Wed, 13 Nov 2013 12:31:46 +0000 (13:31 +0100)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Mon, 18 Nov 2013 14:53:57 +0000 (15:53 +0100)
Otherwise you can end up with some weird situation in which you have
two objects, you print them and then you print the comparison and get
a Foo(0x858480) b Foo(0x858480) a == b false

Task-number: QTBUG-34651

Change-Id: Id2444d919f039be085eb5ed9112345db691540a5
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
src/qml/jsruntime/qv4qobjectwrapper.cpp
src/qml/jsruntime/qv4qobjectwrapper_p.h
src/qml/qml/qqmltypewrapper.cpp
src/qml/qml/qqmltypewrapper_p.h
tests/auto/qml/qqmlecmascript/data/singletonTest2.qml [new file with mode: 0644]
tests/auto/qml/qqmlecmascript/testtypes.h
tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp

index ad3ebe5..f1b0e0b 100644 (file)
@@ -646,6 +646,15 @@ void QObjectWrapper::setProperty(ExecutionContext *ctx, int propertyIndex, const
     return setProperty(m_object, ctx, property, value);
 }
 
+bool QObjectWrapper::isEqualTo(Managed *a, Managed *b)
+{
+    QV4::QObjectWrapper *qobjectWrapper = a->as<QV4::QObjectWrapper>();
+    if (QV4::QmlTypeWrapper *qmlTypeWrapper = b->asObject()->as<QV4::QmlTypeWrapper>())
+        return qmlTypeWrapper->toVariant().value<QObject*>() == qobjectWrapper->object();
+
+    return false;
+}
+
 ReturnedValue QObjectWrapper::create(ExecutionEngine *engine, QQmlData *ddata, QObject *object)
 {
     QQmlEngine *qmlEngine = engine->v8Engine->engine();
index 3a420ab..a73c96d 100644 (file)
@@ -97,6 +97,9 @@ struct Q_QML_EXPORT QObjectWrapper : public QV4::Object
     ReturnedValue getProperty(ExecutionContext *ctx, int propertyIndex, bool captureRequired);
     void setProperty(ExecutionContext *ctx, int propertyIndex, const ValueRef value);
 
+protected:
+    static bool isEqualTo(Managed *that, Managed *o);
+
 private:
     ReturnedValue getProperty(ExecutionContext *ctx, QQmlPropertyData *property, bool captureRequired = true);
     static void setProperty(QObject *object, ExecutionContext *ctx, QQmlPropertyData *property, const ValueRef value);
index 3fd3975..258442b 100644 (file)
@@ -286,4 +286,15 @@ void QmlTypeWrapper::destroy(Managed *that)
     static_cast<QmlTypeWrapper *>(that)->~QmlTypeWrapper();
 }
 
+bool QmlTypeWrapper::isEqualTo(Managed *a, Managed *b)
+{
+    QV4::QmlTypeWrapper *qmlTypeWrapperA = a->asObject()->as<QV4::QmlTypeWrapper>();
+    if (QV4::QmlTypeWrapper *qmlTypeWrapperB = b->asObject()->as<QV4::QmlTypeWrapper>())
+        return qmlTypeWrapperA->toVariant() == qmlTypeWrapperB->toVariant();
+    else if (QV4::QObjectWrapper *qobjectWrapper = b->as<QV4::QObjectWrapper>())
+        return qmlTypeWrapperA->toVariant().value<QObject*>() == qobjectWrapper->object();
+
+    return false;
+}
+
 QT_END_NAMESPACE
index 89f31d6..ee462d6 100644 (file)
@@ -89,6 +89,9 @@ public:
     static PropertyAttributes query(const Managed *, StringRef name);
     static void destroy(Managed *that);
 
+protected:
+    static bool isEqualTo(Managed *that, Managed *o);
+
 private:
     QV8Engine *v8;
     TypeNameMode mode;
diff --git a/tests/auto/qml/qqmlecmascript/data/singletonTest2.qml b/tests/auto/qml/qqmlecmascript/data/singletonTest2.qml
new file mode 100644 (file)
index 0000000..ec45758
--- /dev/null
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Canonical Limited and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+**     of its contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import Test 1.0
+
+Item {
+    property bool myInheritedQmlObjectTest1: false
+    property bool myInheritedQmlObjectTest2: false
+    property bool myInheritedQmlObjectTest3: false
+    property bool myQmlObjectTest1: false
+    property bool myQmlObjectTest2: false
+    property bool myQmlObjectTest3: false
+    property bool qobjectTest1: false
+    property bool qobjectTest2: false
+    property bool qobjectTest3: false
+    property bool singletonEqualToItself: true
+
+    Component.onCompleted: {
+        MyInheritedQmlObjectSingleton.myInheritedQmlObjectProperty = MyInheritedQmlObjectSingleton;
+        myInheritedQmlObjectTest1 = MyInheritedQmlObjectSingleton.myInheritedQmlObjectProperty == MyInheritedQmlObjectSingleton;
+        myInheritedQmlObjectTest2 = MyInheritedQmlObjectSingleton.myInheritedQmlObjectProperty == MyInheritedQmlObjectSingleton.myInheritedQmlObjectProperty;
+        myInheritedQmlObjectTest3 = MyInheritedQmlObjectSingleton == MyInheritedQmlObjectSingleton.myInheritedQmlObjectProperty;
+
+        MyInheritedQmlObjectSingleton.myQmlObjectProperty = MyInheritedQmlObjectSingleton;
+        myQmlObjectTest1 = MyInheritedQmlObjectSingleton.myQmlObjectProperty == MyInheritedQmlObjectSingleton;
+        myQmlObjectTest2 = MyInheritedQmlObjectSingleton.myQmlObjectProperty == MyInheritedQmlObjectSingleton.myQmlObjectProperty;
+        myQmlObjectTest3 = MyInheritedQmlObjectSingleton == MyInheritedQmlObjectSingleton.myQmlObjectProperty;
+
+        MyInheritedQmlObjectSingleton.qobjectProperty = MyInheritedQmlObjectSingleton;
+        qobjectTest1 = MyInheritedQmlObjectSingleton.qobjectProperty == MyInheritedQmlObjectSingleton;
+        qobjectTest2 = MyInheritedQmlObjectSingleton.qobjectProperty == MyInheritedQmlObjectSingleton.qobjectProperty;
+        qobjectTest3 = MyInheritedQmlObjectSingleton == MyInheritedQmlObjectSingleton.qobjectProperty;
+
+        singletonEqualToItself = MyInheritedQmlObjectSingleton == MyInheritedQmlObjectSingleton;
+    }
+}
index 6dcef2d..556cc32 100644 (file)
@@ -294,10 +294,28 @@ QML_DECLARE_TYPEINFO(MyQmlObject, QML_HAS_ATTACHED_PROPERTIES)
 class MyInheritedQmlObject : public MyQmlObject
 {
     Q_OBJECT
+    Q_PROPERTY(MyInheritedQmlObject *myInheritedQmlObjectProperty READ myInheritedQmlObject WRITE setMyInheritedQmlObject)
+    Q_PROPERTY(MyQmlObject *myQmlObjectProperty READ myQmlObject WRITE setMyQmlObject)
+    Q_PROPERTY(QObject *qobjectProperty READ qobject WRITE setQObject)
 public:
+    MyInheritedQmlObject() : m_myInheritedQmlObject(0), m_myQmlObject(0), m_qobject(0) {}
+
+    MyInheritedQmlObject *myInheritedQmlObject() const { return m_myInheritedQmlObject; }
+    void setMyInheritedQmlObject(MyInheritedQmlObject * o) { m_myInheritedQmlObject = o; }
+
+    MyQmlObject *myQmlObject() const { return m_myQmlObject; }
+    void setMyQmlObject(MyQmlObject * o) { m_myQmlObject = o; }
+
+    QObject *qobject() const { return m_qobject; }
+    void setQObject(QObject * o) { m_qobject = o; }
+
     Q_INVOKABLE bool isItYouQObject(QObject *o);
     Q_INVOKABLE bool isItYouMyQmlObject(MyQmlObject *o);
     Q_INVOKABLE bool isItYouMyInheritedQmlObject(MyInheritedQmlObject *o);
+private:
+    MyInheritedQmlObject *m_myInheritedQmlObject;
+    MyQmlObject *m_myQmlObject;
+    QObject *m_qobject;
 };
 QML_DECLARE_TYPE(MyInheritedQmlObject)
 
index 7c1eb7d..6af8863 100644 (file)
@@ -313,6 +313,7 @@ private slots:
     void qtbug_33754();
     void qtbug_34493();
     void singletonFromQMLToCpp();
+    void singletonFromQMLAndBackAndCompare();
     void setPropertyOnInvalid();
     void miscTypeTest();
     void stackLimits();
@@ -7389,6 +7390,33 @@ void tst_qqmlecmascript::singletonFromQMLToCpp()
     QCOMPARE(obj->property("myInheritedQmlObjectTest"), QVariant(true));
 }
 
+// Check that a Singleton can be passed from QML to C++
+// as its type*, it's parent type* and as QObject*
+// and correctly compares to itself
+void tst_qqmlecmascript::singletonFromQMLAndBackAndCompare()
+{
+    QQmlComponent component(&engine, testFile("singletonTest2.qml"));
+    QScopedPointer<QObject> o(component.create());
+    if (component.errors().size())
+        qDebug() << component.errors();
+    QVERIFY(component.errors().isEmpty());
+    QVERIFY(o != 0);
+
+    QCOMPARE(o->property("myInheritedQmlObjectTest1"), QVariant(true));
+    QCOMPARE(o->property("myInheritedQmlObjectTest2"), QVariant(true));
+    QCOMPARE(o->property("myInheritedQmlObjectTest3"), QVariant(true));
+
+    QCOMPARE(o->property("myQmlObjectTest1"), QVariant(true));
+    QCOMPARE(o->property("myQmlObjectTest2"), QVariant(true));
+    QCOMPARE(o->property("myQmlObjectTest3"), QVariant(true));
+
+    QCOMPARE(o->property("qobjectTest1"), QVariant(true));
+    QCOMPARE(o->property("qobjectTest2"), QVariant(true));
+    QCOMPARE(o->property("qobjectTest3"), QVariant(true));
+
+    QCOMPARE(o->property("singletonEqualToItself"), QVariant(true));
+}
+
 void tst_qqmlecmascript::setPropertyOnInvalid()
 {
     {