});
//! [46]
+//! [47]
+disconnect(myObject, &MyObject::mySignal(), 0, 0);
+//! [47]
+//! [48]
+QObject::disconnect(lineEdit, &QLineEdit::textChanged,
+ label, &QLabel::setText);
+//! [48]
//! [meta data]
//: This is a comment for the translator.
const QMetaObject *rmeta = 0,
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, void **slot,
DisconnectType = DisconnectAll);
static inline bool disconnectHelper(QObjectPrivate::Connection *c,
- const QObject *receiver, int method_index,
- QMutex *senderMutex, DisconnectType);
+ const QObject *receiver, int method_index, void **slot,
+ QMutex *senderMutex, DisconnectType = DisconnectAll);
#endif
};
}
if (!method) {
- res |= QMetaObjectPrivate::disconnect(sender, signal_index, receiver, -1);
+ res |= QMetaObjectPrivate::disconnect(sender, signal_index, receiver, -1, 0);
} else {
const QMetaObject *rmeta = receiver->metaObject();
do {
rmeta = rmeta->superClass();
if (method_index < 0)
break;
- res |= QMetaObjectPrivate::disconnect(sender, signal_index, receiver, method_index);
+ res |= QMetaObjectPrivate::disconnect(sender, signal_index, receiver, method_index, 0);
method_found = true;
} while ((rmeta = rmeta->superClass()));
}
return false;
}
- if (!QMetaObjectPrivate::disconnect(sender, signal_index, receiver, method_index))
+ if (!QMetaObjectPrivate::disconnect(sender, signal_index, receiver, method_index, 0))
return false;
const_cast<QObject*>(sender)->disconnectNotify(method.mobj ? signalSignature.constData() : 0);
{
signal_index = methodIndexToSignalIndex(sender->metaObject(), signal_index);
return QMetaObjectPrivate::disconnect(sender, signal_index,
- receiver, method_index);
+ receiver, method_index, 0);
}
/*!\internal
{
signal_index = methodIndexToSignalIndex(sender->metaObject(), signal_index);
return QMetaObjectPrivate::disconnect(sender, signal_index,
- receiver, method_index,
+ receiver, method_index, 0,
QMetaObjectPrivate::DisconnectOne);
}
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,
+ const QObject *receiver, int method_index, void **slot,
QMutex *senderMutex, DisconnectType disconnectType)
{
bool success = false;
while (c) {
if (c->receiver
&& (receiver == 0 || (c->receiver == receiver
- && (method_index < 0 || c->method() == method_index)))) {
+ && (method_index < 0 || c->method() == method_index)
+ && (slot == 0 || (c->isSlotObject && c->slotObj->compare(slot)))))) {
bool needToUnlock = false;
QMutex *receiverMutex = 0;
if (!receiver) {
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, void **slot,
DisconnectType disconnectType)
{
if (!sender)
for (signal_index = -1; signal_index < connectionLists->count(); ++signal_index) {
QObjectPrivate::Connection *c =
(*connectionLists)[signal_index].first;
- if (disconnectHelper(c, receiver, method_index, senderMutex, disconnectType)) {
+ if (disconnectHelper(c, receiver, method_index, slot, senderMutex, disconnectType)) {
success = true;
connectionLists->dirty = true;
}
} else if (signal_index < connectionLists->count()) {
QObjectPrivate::Connection *c =
(*connectionLists)[signal_index].first;
- if (disconnectHelper(c, receiver, method_index, senderMutex, disconnectType)) {
+ if (disconnectHelper(c, receiver, method_index, slot, senderMutex, disconnectType)) {
success = true;
connectionLists->dirty = true;
}
return true;
}
+/*! \fn bool QObject::disconnect(const QObject *sender, (T::*signal)(...), const Qbject *receiver, (T::*method)(...))
+ \threadsafe
+ \overload
+
+ Disconnects \a signal in object \a sender from \a method in object
+ \a receiver. Returns true if the connection is successfully broken;
+ otherwise returns false.
+
+ A signal-slot connection is removed when either of the objects
+ involved are destroyed.
+
+ disconnect() is typically used in three ways, as the following
+ examples demonstrate.
+ \list 1
+ \i Disconnect everything connected to an object's signals:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 26
+
+ \i Disconnect everything connected to a specific signal:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 47
+
+ \i Disconnect a specific receiver:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 30
+
+ \i Disconnect a connection from one specific signal to a specific slot:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 48
+
+
+ \endlist
+
+ 0 may be used as a wildcard, meaning "any signal", "any receiving
+ object", or "any slot in the receiving object", respectively.
+
+ The \a sender may never be 0. (You cannot disconnect signals from
+ more than one object in a single call.)
+
+ If \a signal is 0, it disconnects \a receiver and \a method from
+ any signal. If not, only the specified signal is disconnected.
+
+ If \a receiver is 0, it disconnects anything connected to \a
+ signal. If not, slots in objects other than \a receiver are not
+ disconnected.
+
+ If \a method is 0, it disconnects anything that is connected to \a
+ receiver. If not, only slots named \a method will be disconnected,
+ and all other slots are left alone. The \a method must be 0 if \a
+ receiver is left out, so you cannot disconnect a
+ specifically-named slot on all objects.
+
+ \note It is not possible to use this overload to diconnect signals
+ connected to functors or lambda expressions. That is because it is not
+ possible to compare them. Instead, use the olverload that take a
+ QMetaObject::Connection
+
+ \sa connect()
+*/
+bool QObject::disconnectImpl(const QObject *sender, void **signal, const QObject *receiver, void **slot, const QMetaObject *senderMetaObject)
+{
+ if (sender == 0 || (receiver == 0 && slot != 0)) {
+ qWarning("Object::disconnect: Unexpected null parameter");
+ return false;
+ }
+
+ int signal_index = -1;
+ if (signal) {
+ void *args[] = { &signal_index, signal };
+ senderMetaObject->static_metacall(QMetaObject::IndexOfMethod, 0, args);
+ if (signal_index < 0 || signal_index >= QMetaObjectPrivate::get(senderMetaObject)->signalCount) {
+ qWarning("QObject::disconnect: signal not found in %s", senderMetaObject->className());
+ return false;
+ }
+ int signalOffset, methodOffset;
+ computeOffsets(senderMetaObject, &signalOffset, &methodOffset);
+ signal_index += signalOffset;
+ }
+
+ return QMetaObjectPrivate::disconnect(sender, signal_index, receiver, -1, slot);
+}
+
/*! \class QMetaObject::Connection
Represents a handle to a signal-slot connection.
It can be used to disconnect that connection, or check if
{
}
+bool QObject::QSlotObjectBase::compare(void** )
+{
+ return false;
+}
+
+
QT_END_NAMESPACE
#include "moc_qobject.cpp"
{ return disconnect(this, 0, receiver, member); }
static bool disconnect(const QMetaObject::Connection &);
+ template <typename Func1, typename Func2>
+ static inline bool disconnect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
+ const typename QtPrivate::FunctionPointer<Func2>::Object *receiver, Func2 slot)
+ {
+ typedef QtPrivate::FunctionPointer<Func1> SignalType;
+ typedef QtPrivate::FunctionPointer<Func2> SlotType;
+ reinterpret_cast<typename SignalType::Object *>(0)->qt_check_for_QOBJECT_macro(*reinterpret_cast<typename SignalType::Object *>(0));
+
+ //compilation error if the arguments does not match.
+ typedef typename QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::IncompatibleSignalSlotArguments EnsureCompatibleArguments;
+ return disconnectImpl(sender, reinterpret_cast<void **>(&signal), receiver, reinterpret_cast<void **>(&slot),
+ &SignalType::Object::staticMetaObject);
+ }
+ template <typename Func1>
+ static inline bool disconnect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
+ const QObject *receiver, void **zero)
+ {
+ // This is the overload for when one wish to disconnect a signal from any slot. (slot=0)
+ // Since the function template parametter cannot be deduced from '0', we use a
+ // dummy void ** parametter that must be equal to 0
+ Q_ASSERT(!zero);
+ typedef QtPrivate::FunctionPointer<Func1> SignalType;
+ return disconnectImpl(sender, reinterpret_cast<void **>(&signal), receiver, zero,
+ &SignalType::Object::staticMetaObject);
+ }
+
+
void dumpObjectTree();
void dumpObjectInfo();
QSlotObjectBase() : ref(1) {}
virtual ~QSlotObjectBase();
virtual void call(QObject *receiver, void **a) = 0;
+ virtual bool compare(void **);
};
// implementation of QSlotObjectBase for which the slot is a pointer to member function of a QObject
// Args and R are the List of arguments and the returntype of the signal to which the slot is connected.
virtual void call(QObject *receiver, void **a) {
FuncType::template call<Args, R>(function, static_cast<typename FuncType::Object *>(receiver), a);
}
+ virtual bool compare(void **f) {
+ return *reinterpret_cast<Func *>(f) == function;
+ }
};
// implementation of QSlotObjectBase for which the slot is a static function
// Args and R are the List of arguments and the returntype of the signal to which the slot is connected.
static QMetaObject::Connection connectImpl(const QObject *sender, void **signal, const QObject *receiver, QSlotObjectBase *slot,
Qt::ConnectionType type, const int *types, const QMetaObject *senderMetaObject);
+
+ static bool disconnectImpl(const QObject *sender, void **signal, const QObject *receiver, void **slot,
+ const QMetaObject *senderMetaObject);
+
};
inline QMetaObject::Connection QObject::connect(const QObject *asender, const char *asignal,
void autoConnectionBehavior();
void baseDestroyed();
void pointerConnect();
+ void pointerDisconnect();
void emitInDefinedOrderPointer();
void customTypesPointer();
void connectCxx0x();
delete r2;
}
+void tst_QObject::pointerDisconnect()
+{
+ SenderObject *s = new SenderObject;
+ ReceiverObject *r1 = new ReceiverObject;
+ ReceiverObject *r2 = new ReceiverObject;
+
+ connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 );
+
+ connect( s, &SenderObject::signal2, r1, &ReceiverObject::slot2 );
+ connect( s, &SenderObject::signal3, r1, &ReceiverObject::slot3 );
+ connect( s, &SenderObject::signal4, r1, &ReceiverObject::slot4 );
+
+ s->emitSignal1();
+ s->emitSignal2();
+ s->emitSignal3();
+ s->emitSignal4();
+
+ QCOMPARE( r1->called(1), TRUE );
+ QCOMPARE( r1->called(2), TRUE );
+ QCOMPARE( r1->called(3), TRUE );
+ QCOMPARE( r1->called(4), TRUE );
+ r1->reset();
+
+ // usual disconnect with all parameters given
+ bool ret = QObject::disconnect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 );
+
+ s->emitSignal1();
+
+ QCOMPARE( r1->called(1), FALSE );
+ r1->reset();
+
+ QCOMPARE( ret, TRUE );
+ ret = QObject::disconnect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 );
+ QCOMPARE( ret, FALSE );
+
+ // disconnect all signals from s from all slots from r1
+ QObject::disconnect( s, 0, r1, 0 );
+
+ s->emitSignal2();
+ s->emitSignal3();
+ s->emitSignal4();
+
+ QCOMPARE( r1->called(2), FALSE );
+ QCOMPARE( r1->called(3), FALSE );
+ QCOMPARE( r1->called(4), FALSE );
+ r1->reset();
+
+ connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 );
+ connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot2 );
+ connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot3 );
+ connect( s, &SenderObject::signal2, r1, &ReceiverObject::slot4 );
+
+ // disconnect s's signal1() from all slots of r1
+ QObject::disconnect( s, &SenderObject::signal1, r1, 0 );
+
+ s->emitSignal1();
+ s->emitSignal2();
+
+ QCOMPARE( r1->called(1), FALSE );
+ QCOMPARE( r1->called(2), FALSE );
+ QCOMPARE( r1->called(3), FALSE );
+ QCOMPARE( r1->called(4), TRUE );
+ r1->reset();
+ // make sure all is disconnected again
+ QObject::disconnect( s, 0, r1, 0 );
+
+ connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 );
+ connect( s, &SenderObject::signal1, r2, &ReceiverObject::slot1 );
+ connect( s, &SenderObject::signal2, r1, &ReceiverObject::slot2 );
+ connect( s, &SenderObject::signal2, r2, &ReceiverObject::slot2 );
+ connect( s, &SenderObject::signal3, r1, &ReceiverObject::slot3 );
+ connect( s, &SenderObject::signal3, r2, &ReceiverObject::slot3 );
+
+ // disconnect signal1() from all receivers
+ QObject::disconnect( s, &SenderObject::signal1, 0, 0 );
+ s->emitSignal1();
+ s->emitSignal2();
+ s->emitSignal3();
+
+ QCOMPARE( r1->called(1), FALSE );
+ QCOMPARE( r2->called(1), FALSE );
+ QCOMPARE( r1->called(2), TRUE );
+ QCOMPARE( r2->called(2), TRUE );
+ QCOMPARE( r1->called(2), TRUE );
+ QCOMPARE( r2->called(2), TRUE );
+
+ r1->reset();
+ r2->reset();
+
+ // disconnect all signals of s from all receivers
+ QObject::disconnect( s, 0, 0, 0 );
+
+ QCOMPARE( r1->called(2), FALSE );
+ QCOMPARE( r2->called(2), FALSE );
+ QCOMPARE( r1->called(2), FALSE );
+ QCOMPARE( r2->called(2), FALSE );
+
+ delete r2;
+ delete r1;
+ delete s;
+
+}
+
+
void tst_QObject::emitInDefinedOrderPointer()
{
SenderObject sender;