Support Qt::UniqueConnection in the new connection syntax
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>
This commit is contained in:
parent
8350d91245
commit
0dec6250f7
@ -2366,7 +2366,7 @@ static inline void check_and_warn_compat(const QMetaObject *sender, const QMetaM
|
|||||||
If you pass the Qt::UniqueConnection \a type, the connection will only
|
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
|
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),
|
(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
|
The optional \a type parameter describes the type of connection
|
||||||
to establish. In particular, it determines whether a particular
|
to establish. In particular, it determines whether a particular
|
||||||
@ -4089,6 +4089,14 @@ void qDeleteInEventHandler(QObject *o)
|
|||||||
to verify the existence of \a signal (if it was not declared as a signal)
|
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.
|
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
|
The optional \a type parameter describes the type of connection
|
||||||
to establish. In particular, it determines whether a particular
|
to establish. In particular, it determines whether a particular
|
||||||
signal is delivered to a slot immediately or queued for delivery
|
signal is delivered to a slot immediately or queued for delivery
|
||||||
@ -4136,9 +4144,35 @@ void qDeleteInEventHandler(QObject *o)
|
|||||||
|
|
||||||
The connection will automatically disconnect if the sender is destroyed.
|
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;
|
int signal_index = -1;
|
||||||
void *args[] = { &signal_index, signal };
|
void *args[] = { &signal_index, signal };
|
||||||
senderMetaObject->static_metacall(QMetaObject::IndexOfMethod, 0, args);
|
senderMetaObject->static_metacall(QMetaObject::IndexOfMethod, 0, args);
|
||||||
@ -4157,8 +4191,18 @@ QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signa
|
|||||||
signalSlotLock(receiver));
|
signalSlotLock(receiver));
|
||||||
|
|
||||||
if (type & Qt::UniqueConnection) {
|
if (type & Qt::UniqueConnection) {
|
||||||
qWarning() << "QObject::connect: Qt::UniqueConnection not supported when connecting function pointers";
|
QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists;
|
||||||
type = static_cast<Qt::ConnectionType>(type & (Qt::UniqueConnection - 1));
|
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);
|
QScopedPointer<QObjectPrivate::Connection> c(new QObjectPrivate::Connection);
|
||||||
|
@ -225,8 +225,8 @@ public:
|
|||||||
types = QtPrivate::ConnectionTypes<typename SignalType::Arguments>::types();
|
types = QtPrivate::ConnectionTypes<typename SignalType::Arguments>::types();
|
||||||
|
|
||||||
return connectImpl(sender, reinterpret_cast<void **>(&signal),
|
return connectImpl(sender, reinterpret_cast<void **>(&signal),
|
||||||
receiver, new QSlotObject<Func2,
|
receiver, reinterpret_cast<void **>(&slot),
|
||||||
typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value,
|
new QSlotObject<Func2, typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value,
|
||||||
typename SignalType::ReturnType>(slot),
|
typename SignalType::ReturnType>(slot),
|
||||||
type, types, &SignalType::Object::staticMetaObject);
|
type, types, &SignalType::Object::staticMetaObject);
|
||||||
}
|
}
|
||||||
@ -243,7 +243,7 @@ public:
|
|||||||
typedef typename QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::IncompatibleSignalSlotArguments EnsureCompatibleArguments;
|
typedef typename QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::IncompatibleSignalSlotArguments EnsureCompatibleArguments;
|
||||||
typedef typename QtPrivate::QEnableIf<(int(SignalType::ArgumentCount) >= int(SlotType::ArgumentCount))>::Type EnsureArgumentsCount;
|
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,
|
new QStaticSlotObject<Func2,
|
||||||
typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value,
|
typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value,
|
||||||
typename SignalType::ReturnType>(slot),
|
typename SignalType::ReturnType>(slot),
|
||||||
@ -257,8 +257,8 @@ public:
|
|||||||
{
|
{
|
||||||
typedef QtPrivate::FunctionPointer<Func1> SignalType;
|
typedef QtPrivate::FunctionPointer<Func1> SignalType;
|
||||||
|
|
||||||
return connectImpl(sender, reinterpret_cast<void **>(&signal),
|
return connectImpl(sender, reinterpret_cast<void **>(&signal), sender, 0,
|
||||||
sender, new QFunctorSlotObject<Func2, SignalType::ArgumentCount, typename SignalType::Arguments, typename SignalType::ReturnType>(slot),
|
new QFunctorSlotObject<Func2, SignalType::ArgumentCount, typename SignalType::Arguments, typename SignalType::ReturnType>(slot),
|
||||||
Qt::DirectConnection, 0, &SignalType::Object::staticMetaObject);
|
Qt::DirectConnection, 0, &SignalType::Object::staticMetaObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -407,8 +407,10 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static QMetaObject::Connection connectImpl(const QObject *sender, void **signal, const QObject *receiver, QSlotObjectBase *slot,
|
static QMetaObject::Connection connectImpl(const QObject *sender, void **signal,
|
||||||
Qt::ConnectionType type, const int *types, const QMetaObject *senderMetaObject);
|
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,
|
static bool disconnectImpl(const QObject *sender, void **signal, const QObject *receiver, void **slot,
|
||||||
const QMetaObject *senderMetaObject);
|
const QMetaObject *senderMetaObject);
|
||||||
|
@ -107,6 +107,7 @@ private slots:
|
|||||||
void connectToSender();
|
void connectToSender();
|
||||||
void qobjectConstCast();
|
void qobjectConstCast();
|
||||||
void uniqConnection();
|
void uniqConnection();
|
||||||
|
void uniqConnectionPtr();
|
||||||
void interfaceIid();
|
void interfaceIid();
|
||||||
void deleteQObjectWhenDeletingEvent();
|
void deleteQObjectWhenDeletingEvent();
|
||||||
void overloads();
|
void overloads();
|
||||||
@ -3269,6 +3270,70 @@ void tst_QObject::uniqConnection()
|
|||||||
delete r2;
|
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()
|
void tst_QObject::interfaceIid()
|
||||||
{
|
{
|
||||||
QCOMPARE(QByteArray(qobject_interface_iid<Foo::Bleh *>()),
|
QCOMPARE(QByteArray(qobject_interface_iid<Foo::Bleh *>()),
|
||||||
|
Loading…
Reference in New Issue
Block a user