QSignalSpy: Added template function pointer constructor
Added the function pointer constructor to QSignalSpy to take advantage of the new connect syntax. Change-Id: I94218a096c677cdba73e1b2cfa8b9c09bc28145f Reviewed-by: Olivier Goffart <ogoffart@woboq.com> Reviewed-by: Jason McDonald <macadder1@gmail.com>
This commit is contained in:
parent
eb88aaa3a2
commit
6fc7d76e73
@ -83,3 +83,8 @@ QSignalSpy spy(myPushButton, SIGNAL(clicked(bool)));
|
||||
//! [5]
|
||||
QVERIFY(spy.wait(1000));
|
||||
//! [5]
|
||||
|
||||
//! [6]
|
||||
QSignalSpy spy(myPushButton, &QPushButton::clicked);
|
||||
//! [6]
|
||||
|
||||
|
@ -98,6 +98,48 @@ public:
|
||||
initArgs(mo->method(sigIndex), obj);
|
||||
}
|
||||
|
||||
#ifdef Q_QDOC
|
||||
QSignalSpy(const QObject *object, PointerToMemberFunction signal);
|
||||
#else
|
||||
template <typename Func>
|
||||
QSignalSpy(const typename QtPrivate::FunctionPointer<Func>::Object *obj, Func signal0)
|
||||
: m_waiting(false)
|
||||
{
|
||||
#ifdef Q_CC_BOR
|
||||
const int memberOffset = QObject::staticMetaObject.methodCount();
|
||||
#else
|
||||
static const int memberOffset = QObject::staticMetaObject.methodCount();
|
||||
#endif
|
||||
if (!obj) {
|
||||
qWarning("QSignalSpy: Cannot spy on a null object");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!signal0) {
|
||||
qWarning("QSignalSpy: Null signal name is not valid");
|
||||
return;
|
||||
}
|
||||
|
||||
const QMetaObject * const mo = obj->metaObject();
|
||||
const QMetaMethod signalMetaMethod = QMetaMethod::fromSignal(signal0);
|
||||
const int sigIndex = signalMetaMethod.methodIndex();
|
||||
if (!signalMetaMethod.isValid() ||
|
||||
signalMetaMethod.methodType() != QMetaMethod::Signal) {
|
||||
qWarning("QSignalSpy: Not a valid signal: '%s'",
|
||||
signalMetaMethod.methodSignature().constData());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!QMetaObject::connect(obj, sigIndex, this, memberOffset,
|
||||
Qt::DirectConnection, 0)) {
|
||||
qWarning("QSignalSpy: QMetaObject::connect returned false. Unable to connect.");
|
||||
return;
|
||||
}
|
||||
sig = signalMetaMethod.methodSignature();
|
||||
initArgs(mo->method(sigIndex), obj);
|
||||
}
|
||||
#endif // Q_QDOC
|
||||
|
||||
inline bool isValid() const { return !sig.isEmpty(); }
|
||||
inline QByteArray signal() const { return sig; }
|
||||
|
||||
|
@ -72,6 +72,20 @@
|
||||
\snippet code/doc_src_qsignalspy.cpp 4
|
||||
*/
|
||||
|
||||
/*! \fn QSignalSpy::QSignalSpy(const QObject *object, PointerToMemberFunction signal)
|
||||
\since 5.4
|
||||
|
||||
Constructs a new QSignalSpy that listens for emissions of the \a signal
|
||||
from the QObject \a object. If QSignalSpy is not able to listen for a
|
||||
valid signal (for example, because \a object is null or \a signal does
|
||||
not denote a valid signal of \a object), an explanatory warning message
|
||||
will be output using qWarning() and subsequent calls to \c isValid() will
|
||||
return false.
|
||||
|
||||
Example:
|
||||
\snippet code/doc_src_qsignalspy.cpp 6
|
||||
*/
|
||||
|
||||
/*! \fn QSignalSpy::isValid() const
|
||||
|
||||
Returns \c true if the signal spy listens to a valid signal, otherwise false.
|
||||
|
@ -65,6 +65,19 @@ private slots:
|
||||
void wait_signalEmittedLater();
|
||||
void wait_signalEmittedTooLate();
|
||||
void wait_signalEmittedMultipleTimes();
|
||||
|
||||
void spyFunctionPointerWithoutArgs();
|
||||
void spyFunctionPointerWithBasicArgs();
|
||||
void spyFunctionPointerWithPointers();
|
||||
void spyFunctionPointerWithQtClasses();
|
||||
void spyFunctionPointerWithBasicQtClasses();
|
||||
void spyFunctionPointerWithQtTypedefs();
|
||||
|
||||
void waitFunctionPointer_signalEmitted();
|
||||
void waitFunctionPointer_timeout();
|
||||
void waitFunctionPointer_signalEmittedLater();
|
||||
void waitFunctionPointer_signalEmittedTooLate();
|
||||
void waitFunctionPointer_signalEmittedMultipleTimes();
|
||||
};
|
||||
|
||||
class QtTestObject: public QObject
|
||||
@ -278,5 +291,160 @@ void tst_QSignalSpy::wait_signalEmittedMultipleTimes()
|
||||
QCOMPARE(spy.count(), 3);
|
||||
}
|
||||
|
||||
void tst_QSignalSpy::spyFunctionPointerWithoutArgs()
|
||||
{
|
||||
QtTestObject obj;
|
||||
|
||||
QSignalSpy spy(&obj, &QtTestObject::sig0);
|
||||
QCOMPARE(spy.count(), 0);
|
||||
|
||||
emit obj.sig0();
|
||||
QCOMPARE(spy.count(), 1);
|
||||
emit obj.sig0();
|
||||
QCOMPARE(spy.count(), 2);
|
||||
|
||||
QList<QVariant> args = spy.takeFirst();
|
||||
QCOMPARE(args.count(), 0);
|
||||
}
|
||||
|
||||
void tst_QSignalSpy::spyFunctionPointerWithBasicArgs()
|
||||
{
|
||||
QtTestObject obj;
|
||||
QSignalSpy spy(&obj, &QtTestObject::sig1);
|
||||
|
||||
emit obj.sig1(1, 2);
|
||||
QCOMPARE(spy.count(), 1);
|
||||
|
||||
QList<QVariant> args = spy.takeFirst();
|
||||
QCOMPARE(args.count(), 2);
|
||||
QCOMPARE(args.at(0).toInt(), 1);
|
||||
QCOMPARE(args.at(1).toInt(), 2);
|
||||
|
||||
QSignalSpy spyl(&obj, &QtTestObject::sigLong);
|
||||
|
||||
emit obj.sigLong(1l, 2l);
|
||||
args = spyl.takeFirst();
|
||||
QCOMPARE(args.count(), 2);
|
||||
QCOMPARE(qvariant_cast<long>(args.at(0)), 1l);
|
||||
QCOMPARE(qvariant_cast<long>(args.at(1)), 2l);
|
||||
}
|
||||
|
||||
|
||||
void tst_QSignalSpy::spyFunctionPointerWithPointers()
|
||||
{
|
||||
qRegisterMetaType<int *>("int*");
|
||||
|
||||
QtTestObject obj;
|
||||
QSignalSpy spy(&obj, &QtTestObject::sig2);
|
||||
|
||||
int i1 = 1;
|
||||
int i2 = 2;
|
||||
|
||||
emit obj.sig2(&i1, &i2);
|
||||
QCOMPARE(spy.count(), 1);
|
||||
|
||||
QList<QVariant> args = spy.takeFirst();
|
||||
QCOMPARE(args.count(), 2);
|
||||
QCOMPARE(*static_cast<int * const *>(args.at(0).constData()), &i1);
|
||||
QCOMPARE(*static_cast<int * const *>(args.at(1).constData()), &i2);
|
||||
}
|
||||
|
||||
void tst_QSignalSpy::spyFunctionPointerWithBasicQtClasses()
|
||||
{
|
||||
QtTestObject2 obj;
|
||||
|
||||
QSignalSpy spy(&obj, &QtTestObject2::sig);
|
||||
emit obj.sig(QString("bubu"));
|
||||
QCOMPARE(spy.count(), 1);
|
||||
QCOMPARE(spy.at(0).count(), 1);
|
||||
QCOMPARE(spy.at(0).at(0).toString(), QString("bubu"));
|
||||
|
||||
QSignalSpy spy2(&obj, &QtTestObject2::sig5);
|
||||
QVariant val(45);
|
||||
emit obj.sig5(val);
|
||||
QCOMPARE(spy2.count(), 1);
|
||||
QCOMPARE(spy2.at(0).count(), 1);
|
||||
QCOMPARE(spy2.at(0).at(0), val);
|
||||
QCOMPARE(qvariant_cast<QVariant>(spy2.at(0).at(0)), val);
|
||||
}
|
||||
|
||||
void tst_QSignalSpy::spyFunctionPointerWithQtClasses()
|
||||
{
|
||||
QtTestObject2 obj;
|
||||
|
||||
QSignalSpy spy(&obj, &QtTestObject2::sig2);
|
||||
QDateTime dt = QDateTime::currentDateTime();
|
||||
emit obj.sig2(dt);
|
||||
QCOMPARE(spy.count(), 1);
|
||||
QCOMPARE(spy.at(0).count(), 1);
|
||||
QCOMPARE(spy.at(0).at(0).typeName(), "QDateTime");
|
||||
QCOMPARE(*static_cast<const QDateTime *>(spy.at(0).at(0).constData()), dt);
|
||||
QCOMPARE(spy.at(0).at(0).toDateTime(), dt);
|
||||
|
||||
QSignalSpy spy2(&obj, &QtTestObject2::sig3);
|
||||
emit obj.sig3(this);
|
||||
QCOMPARE(*static_cast<QObject * const *>(spy2.value(0).value(0).constData()),
|
||||
(QObject *)this);
|
||||
QCOMPARE(qvariant_cast<QObject *>(spy2.value(0).value(0)), (QObject*)this);
|
||||
|
||||
QSignalSpy spy3(&obj, &QtTestObject2::sig4);
|
||||
emit obj.sig4(QChar('A'));
|
||||
QCOMPARE(qvariant_cast<QChar>(spy3.value(0).value(0)), QChar('A'));
|
||||
}
|
||||
|
||||
void tst_QSignalSpy::spyFunctionPointerWithQtTypedefs()
|
||||
{
|
||||
QtTestObject3 obj;
|
||||
|
||||
QSignalSpy spy2(&obj, &QtTestObject3::sig2);
|
||||
emit obj.sig2(42, 43);
|
||||
QCOMPARE(spy2.value(0).value(0).toInt(), 42);
|
||||
QCOMPARE(spy2.value(0).value(1).toInt(), 43);
|
||||
}
|
||||
|
||||
void tst_QSignalSpy::waitFunctionPointer_signalEmitted()
|
||||
{
|
||||
QTimer::singleShot(0, this, SIGNAL(sigFoo()));
|
||||
QSignalSpy spy(this, &tst_QSignalSpy::sigFoo);
|
||||
QVERIFY(spy.wait(1));
|
||||
}
|
||||
|
||||
void tst_QSignalSpy::waitFunctionPointer_timeout()
|
||||
{
|
||||
QSignalSpy spy(this, &tst_QSignalSpy::sigFoo);
|
||||
QVERIFY(!spy.wait(1));
|
||||
}
|
||||
|
||||
void tst_QSignalSpy::waitFunctionPointer_signalEmittedLater()
|
||||
{
|
||||
QTimer::singleShot(500, this, SIGNAL(sigFoo()));
|
||||
QSignalSpy spy(this, &tst_QSignalSpy::sigFoo);
|
||||
QVERIFY(spy.wait(1000));
|
||||
}
|
||||
|
||||
void tst_QSignalSpy::waitFunctionPointer_signalEmittedTooLate()
|
||||
{
|
||||
QTimer::singleShot(500, this, SIGNAL(sigFoo()));
|
||||
QSignalSpy spy(this, &tst_QSignalSpy::sigFoo);
|
||||
QVERIFY(!spy.wait(200));
|
||||
QTest::qWait(400);
|
||||
QCOMPARE(spy.count(), 1);
|
||||
}
|
||||
|
||||
void tst_QSignalSpy::waitFunctionPointer_signalEmittedMultipleTimes()
|
||||
{
|
||||
QTimer::singleShot(100, this, SIGNAL(sigFoo()));
|
||||
QTimer::singleShot(800, this, SIGNAL(sigFoo()));
|
||||
QSignalSpy spy(this, &tst_QSignalSpy::sigFoo);
|
||||
QVERIFY(spy.wait());
|
||||
QCOMPARE(spy.count(), 1); // we don't wait for the second signal...
|
||||
QVERIFY(spy.wait());
|
||||
QCOMPARE(spy.count(), 2);
|
||||
QVERIFY(!spy.wait(1));
|
||||
QTimer::singleShot(10, this, SIGNAL(sigFoo()));
|
||||
QVERIFY(spy.wait());
|
||||
QCOMPARE(spy.count(), 3);
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QSignalSpy)
|
||||
#include "tst_qsignalspy.moc"
|
||||
|
Loading…
Reference in New Issue
Block a user