This commit also improves the related documentation a bit.
The test is copied from the test with the old syntax, but all the
connection statement are changed to use the new syntax
Change-Id: Ia5630ca4335b9f8ca6d724ae3c8750d6f0804d8e
Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com>
If you pass the Qt::UniqueConnection \a type, the connection will only
be made if it is not a duplicate. If there is already a duplicate
(exact same signal to the exact same slot on the same objects),
- the connection will fail and connect will return false.
+ the connection will fail and connect will return an invalid QMetaObject::Connection.
The optional \a type parameter describes the type of connection
to establish. In particular, it determines whether a particular
to verify the existence of \a signal (if it was not declared as a signal)
You can check if the QMetaObject::Connection is valid by casting it to a bool.
+ By default, a signal is emitted for every connection you make;
+ two signals are emitted for duplicate connections. You can break
+ all of these connections with a single disconnect() call.
+ If you pass the Qt::UniqueConnection \a type, the connection will only
+ be made if it is not a duplicate. If there is already a duplicate
+ (exact same signal to the exact same slot on the same objects),
+ the connection will fail and connect will return an invalid QMetaObject::Connection.
+
The optional \a type parameter describes the type of connection
to establish. In particular, it determines whether a particular
signal is delivered to a slot immediately or queued for delivery
The connection will automatically disconnect if the sender is destroyed.
*/
-QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signal, const QObject *receiver, QObject::QSlotObjectBase *slotObj,
- Qt::ConnectionType type, const int* types, const QMetaObject* senderMetaObject)
+
+/** \internal
+
+ Implementation of the template version of connect
+
+ \a sender is the sender object
+ \a signal is a pointer to a pointer to a member signal of the sender
+ \a receiver is the receiver object, may not be null, will be equal to sender when
+ connecting to a static function or a functor
+ \a slot a pointer only used when using Qt::UniqueConnection
+ \a type the Qt::ConnctionType passed as argument to connect
+ \a types an array of integer with the metatype id of the parametter of the signal
+ to be used with queued connection
+ must stay valid at least for the whole time of the connection, this function
+ do not take ownership. typically static data.
+ If null, then the types will be computed when the signal is emit in a queued
+ connection from the types from the signature.
+ \a senderMetaObject is the metaobject used to lookup the signal, the signal must be in
+ this metaobject
+ */
+QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signal,
+ const QObject *receiver, void **slot,
+ QObject::QSlotObjectBase *slotObj, Qt::ConnectionType type,
+ const int *types, const QMetaObject *senderMetaObject)
{
+ if (!sender || !signal || !slotObj || !senderMetaObject) {
+ qWarning("QObject::connect: invalid null parametter");
+ return QMetaObject::Connection();
+ }
int signal_index = -1;
void *args[] = { &signal_index, signal };
senderMetaObject->static_metacall(QMetaObject::IndexOfMethod, 0, args);
signalSlotLock(receiver));
if (type & Qt::UniqueConnection) {
- qWarning() << "QObject::connect: Qt::UniqueConnection not supported when connecting function pointers";
- type = static_cast<Qt::ConnectionType>(type & (Qt::UniqueConnection - 1));
+ QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists;
+ if (connectionLists && connectionLists->count() > signal_index) {
+ const QObjectPrivate::Connection *c2 =
+ (*connectionLists)[signal_index].first;
+
+ while (c2) {
+ if (c2->receiver == receiver && c2->isSlotObject && c2->slotObj->compare(slot))
+ return QMetaObject::Connection();
+ c2 = c2->nextConnectionList;
+ }
+ }
+ type = static_cast<Qt::ConnectionType>(type ^ Qt::UniqueConnection);
}
QScopedPointer<QObjectPrivate::Connection> c(new QObjectPrivate::Connection);
types = QtPrivate::ConnectionTypes<typename SignalType::Arguments>::types();
return connectImpl(sender, reinterpret_cast<void **>(&signal),
- receiver, new QSlotObject<Func2,
- typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value,
- typename SignalType::ReturnType>(slot),
+ receiver, reinterpret_cast<void **>(&slot),
+ new QSlotObject<Func2, typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value,
+ typename SignalType::ReturnType>(slot),
type, types, &SignalType::Object::staticMetaObject);
}
typedef typename QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::IncompatibleSignalSlotArguments EnsureCompatibleArguments;
typedef typename QtPrivate::QEnableIf<(int(SignalType::ArgumentCount) >= int(SlotType::ArgumentCount))>::Type EnsureArgumentsCount;
- return connectImpl(sender, reinterpret_cast<void **>(&signal), sender,
+ return connectImpl(sender, reinterpret_cast<void **>(&signal), sender, 0,
new QStaticSlotObject<Func2,
typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value,
typename SignalType::ReturnType>(slot),
{
typedef QtPrivate::FunctionPointer<Func1> SignalType;
- return connectImpl(sender, reinterpret_cast<void **>(&signal),
- sender, new QFunctorSlotObject<Func2, SignalType::ArgumentCount, typename SignalType::Arguments, typename SignalType::ReturnType>(slot),
+ return connectImpl(sender, reinterpret_cast<void **>(&signal), sender, 0,
+ new QFunctorSlotObject<Func2, SignalType::ArgumentCount, typename SignalType::Arguments, typename SignalType::ReturnType>(slot),
Qt::DirectConnection, 0, &SignalType::Object::staticMetaObject);
}
}
};
- static QMetaObject::Connection connectImpl(const QObject *sender, void **signal, const QObject *receiver, QSlotObjectBase *slot,
- Qt::ConnectionType type, const int *types, const QMetaObject *senderMetaObject);
+ static QMetaObject::Connection connectImpl(const QObject *sender, void **signal,
+ const QObject *receiver, void **slotPtr,
+ 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);
void connectToSender();
void qobjectConstCast();
void uniqConnection();
+ void uniqConnectionPtr();
void interfaceIid();
void deleteQObjectWhenDeletingEvent();
void overloads();
delete r2;
}
+void tst_QObject::uniqConnectionPtr()
+{
+ SenderObject *s = new SenderObject;
+ ReceiverObject *r1 = new ReceiverObject;
+ ReceiverObject *r2 = new ReceiverObject;
+ r1->reset();
+ r2->reset();
+ ReceiverObject::sequence = 0;
+
+ QVERIFY( connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 , Qt::UniqueConnection) );
+ QVERIFY( connect( s, &SenderObject::signal1, r2, &ReceiverObject::slot1 , Qt::UniqueConnection) );
+ QVERIFY( connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot3 , Qt::UniqueConnection) );
+ QVERIFY( connect( s, &SenderObject::signal3, r1, &ReceiverObject::slot3 , Qt::UniqueConnection) );
+
+ s->emitSignal1();
+ s->emitSignal2();
+ s->emitSignal3();
+ s->emitSignal4();
+
+ QCOMPARE( r1->count_slot1, 1 );
+ QCOMPARE( r1->count_slot2, 0 );
+ QCOMPARE( r1->count_slot3, 2 );
+ QCOMPARE( r1->count_slot4, 0 );
+ QCOMPARE( r2->count_slot1, 1 );
+ QCOMPARE( r2->count_slot2, 0 );
+ QCOMPARE( r2->count_slot3, 0 );
+ QCOMPARE( r2->count_slot4, 0 );
+ QCOMPARE( r1->sequence_slot1, 1 );
+ QCOMPARE( r2->sequence_slot1, 2 );
+ QCOMPARE( r1->sequence_slot3, 4 );
+
+ r1->reset();
+ r2->reset();
+ ReceiverObject::sequence = 0;
+
+ QVERIFY( connect( s, &SenderObject::signal4, r1, &ReceiverObject::slot4 , Qt::UniqueConnection) );
+ QVERIFY( connect( s, &SenderObject::signal4, r2, &ReceiverObject::slot4 , Qt::UniqueConnection) );
+ QVERIFY(!connect( s, &SenderObject::signal4, r2, &ReceiverObject::slot4 , Qt::UniqueConnection) );
+ QVERIFY( connect( s, &SenderObject::signal1, r2, &ReceiverObject::slot4 , Qt::UniqueConnection) );
+ QVERIFY(!connect( s, &SenderObject::signal4, r1, &ReceiverObject::slot4 , Qt::UniqueConnection) );
+
+ s->emitSignal4();
+ QCOMPARE( r1->count_slot4, 1 );
+ QCOMPARE( r2->count_slot4, 1 );
+ QCOMPARE( r1->sequence_slot4, 1 );
+ QCOMPARE( r2->sequence_slot4, 2 );
+
+ r1->reset();
+ r2->reset();
+ ReceiverObject::sequence = 0;
+
+ connect( s, &SenderObject::signal4, r1, &ReceiverObject::slot4 );
+
+ s->emitSignal4();
+ QCOMPARE( r1->count_slot4, 2 );
+ QCOMPARE( r2->count_slot4, 1 );
+ QCOMPARE( r1->sequence_slot4, 3 );
+ QCOMPARE( r2->sequence_slot4, 2 );
+
+ delete s;
+ delete r1;
+ delete r2;
+}
+
void tst_QObject::interfaceIid()
{
QCOMPARE(QByteArray(qobject_interface_iid<Foo::Bleh *>()),