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
|
||||
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
|
||||
@ -4089,6 +4089,14 @@ void qDeleteInEventHandler(QObject *o)
|
||||
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
|
||||
@ -4136,9 +4144,35 @@ void qDeleteInEventHandler(QObject *o)
|
||||
|
||||
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);
|
||||
@ -4157,8 +4191,18 @@ QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signa
|
||||
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);
|
||||
|
@ -225,9 +225,9 @@ public:
|
||||
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);
|
||||
}
|
||||
|
||||
@ -243,7 +243,7 @@ public:
|
||||
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),
|
||||
@ -257,8 +257,8 @@ public:
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
@ -407,8 +407,10 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
|
@ -107,6 +107,7 @@ private slots:
|
||||
void connectToSender();
|
||||
void qobjectConstCast();
|
||||
void uniqConnection();
|
||||
void uniqConnectionPtr();
|
||||
void interfaceIid();
|
||||
void deleteQObjectWhenDeletingEvent();
|
||||
void overloads();
|
||||
@ -3269,6 +3270,70 @@ void tst_QObject::uniqConnection()
|
||||
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 *>()),
|
||||
|
Loading…
Reference in New Issue
Block a user