From 8562344632efce66d58490344d557d5d217994d4 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 11 Jan 2010 16:28:49 +1000 Subject: QMetaObject::disconnectOne() Adds a disconnectOne() method that allows a single signal/slot connection to be disconnected, as required by QTBUG-6781. Reviewed-by: Warwick Allison --- src/corelib/kernel/qmetaobject_p.h | 6 ++++-- src/corelib/kernel/qobject.cpp | 24 +++++++++++++++++++----- src/corelib/kernel/qobjectdefs.h | 2 ++ 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h index b5a7530..4ab2d81 100644 --- a/src/corelib/kernel/qmetaobject_p.h +++ b/src/corelib/kernel/qmetaobject_p.h @@ -124,14 +124,16 @@ struct QMetaObjectPrivate #ifndef QT_NO_QOBJECT //defined in qobject.cpp + enum DisconnectType { DisconnectAll, DisconnectOne }; static bool connect(const QObject *sender, int signal_index, const QObject *receiver, int method_index, int type = 0, int *types = 0); static bool disconnect(const QObject *sender, int signal_index, - const QObject *receiver, int method_index); + const QObject *receiver, int method_index, + DisconnectType = DisconnectAll); static inline bool disconnectHelper(QObjectPrivate::Connection *c, const QObject *receiver, int method_index, - QMutex *senderMutex); + QMutex *senderMutex, DisconnectType); #endif }; diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 305ec4f..39b4860 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -2945,7 +2945,6 @@ bool QMetaObjectPrivate::connect(const QObject *sender, int signal_index, return true; } - /*!\internal */ bool QMetaObject::disconnect(const QObject *sender, int signal_index, @@ -2956,12 +2955,23 @@ bool QMetaObject::disconnect(const QObject *sender, int signal_index, receiver, method_index); } +/*!\internal + */ +bool QMetaObject::disconnectOne(const QObject *sender, int signal_index, + const QObject *receiver, int method_index) +{ + signal_index = methodIndexToSignalIndex(sender->metaObject(), signal_index); + return QMetaObjectPrivate::disconnect(sender, signal_index, + receiver, method_index, + QMetaObjectPrivate::DisconnectOne); +} + /*! \internal Helper function to remove the connection from the senders list and setting the receivers to 0 */ bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c, const QObject *receiver, int method_index, - QMutex *senderMutex) + QMutex *senderMutex, DisconnectType disconnectType) { bool success = false; while (c) { @@ -2987,6 +2997,9 @@ bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c, c->receiver = 0; success = true; + + if (disconnectType == DisconnectOne) + return success; } c = c->nextConnectionList; } @@ -2997,7 +3010,8 @@ bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c, Same as the QMetaObject::disconnect, but \a signal_index must be the result of QObjectPrivate::signalIndex */ bool QMetaObjectPrivate::disconnect(const QObject *sender, int signal_index, - const QObject *receiver, int method_index) + const QObject *receiver, int method_index, + DisconnectType disconnectType) { if (!sender) return false; @@ -3021,7 +3035,7 @@ bool QMetaObjectPrivate::disconnect(const QObject *sender, int signal_index, for (signal_index = -1; signal_index < connectionLists->count(); ++signal_index) { QObjectPrivate::Connection *c = (*connectionLists)[signal_index].first; - if (disconnectHelper(c, receiver, method_index, senderMutex)) { + if (disconnectHelper(c, receiver, method_index, senderMutex, disconnectType)) { success = true; connectionLists->dirty = true; } @@ -3029,7 +3043,7 @@ bool QMetaObjectPrivate::disconnect(const QObject *sender, int signal_index, } else if (signal_index < connectionLists->count()) { QObjectPrivate::Connection *c = (*connectionLists)[signal_index].first; - if (disconnectHelper(c, receiver, method_index, senderMutex)) { + if (disconnectHelper(c, receiver, method_index, senderMutex, disconnectType)) { success = true; connectionLists->dirty = true; } diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index 6a9cead..211c47b 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -334,6 +334,8 @@ struct Q_CORE_EXPORT QMetaObject // internal index-based disconnect static bool disconnect(const QObject *sender, int signal_index, const QObject *receiver, int method_index); + static bool disconnectOne(const QObject *sender, int signal_index, + const QObject *receiver, int method_index); // internal slot-name based connect static void connectSlotsByName(QObject *o); -- cgit v0.12 From 2ec9b259f63a7305cf221425049cd728adb84bf2 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 11 Jan 2010 16:32:58 +1000 Subject: Use QMetaObject::disconnectOne() in QML QTBUG-6781 --- src/declarative/qml/qmlbindingvme.cpp | 4 ++-- src/declarative/qml/qmlexpression.cpp | 18 +++++++++--------- .../declarative/qmlecmascript/tst_qmlecmascript.cpp | 9 ++++++++- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/declarative/qml/qmlbindingvme.cpp b/src/declarative/qml/qmlbindingvme.cpp index b4b8dc1..29391a6 100644 --- a/src/declarative/qml/qmlbindingvme.cpp +++ b/src/declarative/qml/qmlbindingvme.cpp @@ -383,8 +383,8 @@ inline void subscribe(QObject *o, int notifyIndex, QmlBindingVME::Config::Subscription *s = config->subscriptions + subIndex; if (o != s->source || notifyIndex != s->notifyIndex) { if (s->source) - QMetaObject::disconnect(s->source, s->notifyIndex, - config->target, config->targetSlot + subIndex); + QMetaObject::disconnectOne(s->source, s->notifyIndex, + config->target, config->targetSlot + subIndex); s->source = o; s->notifyIndex = notifyIndex; if (s->source && s->notifyIndex != -1) diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp index 1587d61..aefa0b1 100644 --- a/src/declarative/qml/qmlexpression.cpp +++ b/src/declarative/qml/qmlexpression.cpp @@ -641,9 +641,9 @@ void QmlExpressionPrivate::clearGuards() for (int ii = 0; ii < data->guardListLength; ++ii) { if (data->guardList[ii].data()) { - QMetaObject::disconnect(data->guardList[ii].data(), - data->guardList[ii].notifyIndex, - q, notifyIdx); + QMetaObject::disconnectOne(data->guardList[ii].data(), + data->guardList[ii].notifyIndex, + q, notifyIdx); } } @@ -684,9 +684,9 @@ void QmlExpressionPrivate::updateGuards(const QPODVectorguardList[ii].data() && !data->guardList[ii].isDuplicate) { // Cache miss - QMetaObject::disconnect(data->guardList[ii].data(), - data->guardList[ii].notifyIndex, - q, notifyIdx); + QMetaObject::disconnectOne(data->guardList[ii].data(), + data->guardList[ii].notifyIndex, + q, notifyIdx); } /* else { // Cache miss, but nothing to do @@ -732,9 +732,9 @@ void QmlExpressionPrivate::updateGuards(const QPODVectorguardListLength; ++ii) { if (data->guardList[ii].data() && !data->guardList[ii].isDuplicate) { - QMetaObject::disconnect(data->guardList[ii].data(), - data->guardList[ii].notifyIndex, - q, notifyIdx); + QMetaObject::disconnectOne(data->guardList[ii].data(), + data->guardList[ii].notifyIndex, + q, notifyIdx); } } diff --git a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp index a153296..3aa1aff 100644 --- a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp +++ b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp @@ -216,6 +216,13 @@ void tst_qmlecmascript::methods() QCOMPARE(object->property("test2").toInt(), 17); QCOMPARE(object->property("test3").toInt(), 16); } + + { + QmlComponent component(&engine, TEST_FILE("methods.5.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + QCOMPARE(object->property("test").toInt(), 9); + } } void tst_qmlecmascript::bindingLoop() @@ -1051,6 +1058,7 @@ void tst_qmlecmascript::compositePropertyType() delete object; } +// QTBUG-6781 void tst_qmlecmascript::bug1() { QmlComponent component(&engine, TEST_FILE("bug.1.qml")); @@ -1065,7 +1073,6 @@ void tst_qmlecmascript::bug1() object->setProperty("b", true); - QEXPECT_FAIL("", "QTBUG-6781", Continue); QCOMPARE(object->property("test").toInt(), 9); delete object; -- cgit v0.12