Fix a case of connect()ing to signals declared in a base class

Fix connection to pointer to member signal that belongs to the base
class, but whose type is a pointer to a member of the derived class.

The current code only use the QMetaObject of the type coming from the
function type to look up the signal id. But if the signal was casted
to a pointer to member function of a derived type, then we also need to
look in the base classes

Change-Id: Ib98fc38f63942946acb34d9f83c100991d58e4e5
Reviewed-by: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Olivier Goffart 2013-05-07 18:56:50 +02:00 committed by The Qt Project
parent baa2822077
commit 9cc106d9d7
2 changed files with 32 additions and 3 deletions

View File

@ -4288,9 +4288,13 @@ QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signa
}
int signal_index = -1;
void *args[] = { &signal_index, signal };
senderMetaObject->static_metacall(QMetaObject::IndexOfMethod, 0, args);
if (signal_index < 0 || signal_index >= QMetaObjectPrivate::get(senderMetaObject)->signalCount) {
qWarning("QObject::connect: signal not found in %s", senderMetaObject->className());
for (; senderMetaObject && signal_index < 0; senderMetaObject = senderMetaObject->superClass()) {
senderMetaObject->static_metacall(QMetaObject::IndexOfMethod, 0, args);
if (signal_index >= 0 && signal_index < QMetaObjectPrivate::get(senderMetaObject)->signalCount)
break;
}
if (!senderMetaObject) {
qWarning("QObject::connect: signal not found in %s", sender->metaObject()->className());
slotObj->destroyIfLastRef();
return QMetaObject::Connection(0);
}

View File

@ -145,6 +145,7 @@ private slots:
void connectFunctorArgDifference();
void connectFunctorOverloads();
void disconnectDoesNotLeakFunctor();
void connectBase();
};
struct QObjectCreatedOnShutdown
@ -5811,5 +5812,29 @@ void tst_QObject::disconnectDoesNotLeakFunctor()
QCOMPARE(countedStructObjectsCount, 0);
}
class SubSender : public SenderObject {
Q_OBJECT
};
void tst_QObject::connectBase()
{
SubSender sub;
ReceiverObject r1;
r1.reset();
QVERIFY( connect( &sub, &SubSender::signal1 , &r1, &ReceiverObject::slot1 ) );
QVERIFY( connect( &sub, static_cast<void (SenderObject::*)()>(&SubSender::signal2) , &r1, &ReceiverObject::slot2 ) );
QVERIFY( connect( &sub, static_cast<void (SubSender::*)()>(&SubSender::signal3) , &r1, &ReceiverObject::slot3 ) );
sub.emitSignal1();
sub.emitSignal2();
sub.emitSignal3();
QCOMPARE( r1.count_slot1, 1 );
QCOMPARE( r1.count_slot2, 1 );
QCOMPARE( r1.count_slot3, 1 );
}
QTEST_MAIN(tst_QObject)
#include "tst_qobject.moc"