Fix signal handlers for signals with default arguments.
authorMichael Brasser <michael.brasser@nokia.com>
Wed, 16 May 2012 02:31:59 +0000 (12:31 +1000)
committerQt by Nokia <qt-info@nokia.com>
Thu, 17 May 2012 06:58:45 +0000 (08:58 +0200)
For cloned signals, connect to the index of the original. This was a
regression caused by the switch to QQmlNotifierEndpoint for signal
handlers. This change also makes parameters with default arguments
available from QML, while previously they were unavailable.

Change-Id: I1feb3412c3e9b0f2a5d6644c404c56d53c5544ac
Reviewed-by: Martin Jones <martin.jones@nokia.com>
src/qml/qml/qqmlboundsignal.cpp
tests/auto/qml/qqmllanguage/data/signalWithDefaultArg.qml [new file with mode: 0644]
tests/auto/qml/qqmllanguage/testtypes.h
tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp

index b3d07c3..629c8a5 100644 (file)
@@ -228,6 +228,18 @@ QQmlBoundSignal::QQmlBoundSignal(QObject *scope, const QMetaMethod &signal,
     setIsEvaluating(false);
     addToObject(owner);
     callback = &subscriptionCallback;
+
+    /*
+        If this is a cloned method, connect to the 'original'. For example,
+        for the signal 'void aSignal(int parameter = 0)', if the method
+        index refers to 'aSignal()', get the index of 'aSignal(int)'.
+        This ensures that 'parameter' will be available from QML.
+    */
+    if (signal.attributes() & QMetaMethod::Cloned) {
+        do {
+            --m_index;
+        } while (scope->metaObject()->method(m_index).attributes() & QMetaMethod::Cloned);
+    }
     QQmlNotifierEndpoint::connect(scope, m_index, engine);
 }
 
diff --git a/tests/auto/qml/qqmllanguage/data/signalWithDefaultArg.qml b/tests/auto/qml/qqmllanguage/data/signalWithDefaultArg.qml
new file mode 100644 (file)
index 0000000..e9f86fe
--- /dev/null
@@ -0,0 +1,23 @@
+import Test 1.0
+import QtQuick 2.0
+
+MyQmlObject {
+    property real signalCount: 0
+    property real signalArg: 0
+
+    signal noArgSignal
+    signal argSignal(real arg)
+
+    function emitNoArgSignal() { noArgSignal(); }
+    function emitArgSignal() { argSignal(22); }
+
+    onSignalWithDefaultArg: {
+        signalArg = parameter
+        signalCount++
+    }
+
+    Component.onCompleted: {
+        noArgSignal.connect(signalWithDefaultArg)
+        argSignal.connect(signalWithDefaultArg)
+    }
+}
index 90dea4a..a359a34 100644 (file)
@@ -164,6 +164,7 @@ signals:
     void basicSignal();
     void basicParameterizedSignal(int parameter);
     void oddlyNamedNotifySignal();
+    void signalWithDefaultArg(int parameter = 5);
 
 private:
     friend class tst_qqmllanguage;
index e33f636..05029b9 100644 (file)
@@ -173,6 +173,7 @@ private slots:
 
     void propertyInit();
     void remoteLoadCrash();
+    void signalWithDefaultArg();
 
     // regression tests for crashes
     void crash1();
@@ -2313,6 +2314,37 @@ void tst_qqmllanguage::remoteLoadCrash()
     delete o;
 }
 
+void tst_qqmllanguage::signalWithDefaultArg()
+{
+    QQmlComponent component(&engine, TEST_FILE("signalWithDefaultArg.qml"));
+
+    MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+    QVERIFY(object != 0);
+
+    QCOMPARE(object->property("signalCount").toInt(), 0);
+    QCOMPARE(object->property("signalArg").toInt(), 0);
+
+    emit object->signalWithDefaultArg();
+    QCOMPARE(object-> property("signalCount").toInt(), 1);
+    QCOMPARE(object->property("signalArg").toInt(), 5);
+
+    emit object->signalWithDefaultArg(15);
+    QCOMPARE(object->property("signalCount").toInt(), 2);
+    QCOMPARE(object->property("signalArg").toInt(), 15);
+
+    const QMetaObject *metaObject = object->metaObject();
+
+    metaObject->invokeMethod(object, "emitNoArgSignal");
+    QCOMPARE(object->property("signalCount").toInt(), 3);
+    QCOMPARE(object->property("signalArg").toInt(), 5);
+
+    metaObject->invokeMethod(object, "emitArgSignal");
+    QCOMPARE(object->property("signalCount").toInt(), 4);
+    QCOMPARE(object->property("signalArg").toInt(), 22);
+
+    delete object;
+}
+
 // QTBUG-20639
 void tst_qqmllanguage::globalEnums()
 {