Introduce QObject::isSignalConnected(QMetaMethod)

This is much more performant than calling QObject::receivers(const char*)

Can be used instead of connectNotify in some cases.

Change-Id: I19e0933f678f171f515d9a0f69f0ad4fb7d894b4
Reviewed-by: Kent Hansen <kent.hansen@nokia.com>
This commit is contained in:
Olivier Goffart 2012-04-24 15:01:47 +02:00 committed by Qt by Nokia
parent ade8888603
commit bcd477e0bc
4 changed files with 96 additions and 3 deletions

View File

@ -479,6 +479,14 @@ QObject::disconnect(lineEdit, &QLineEdit::textChanged,
label, &QLabel::setText); label, &QLabel::setText);
//! [48] //! [48]
//! [49]
if (isSignalConnected(QMethaMethod::fromSignal(&MyObject::valueChanged))) {
QByteArray data;
data = get_the_value(); // expensive operation
emit valueChanged(data);
}
//! [49]
//! [meta data] //! [meta data]
//: This is a comment for the translator. //: This is a comment for the translator.
//= qtn_foo_bar //= qtn_foo_bar

View File

@ -2157,13 +2157,12 @@ int QObject::senderSignalIndex() const
\snippet code/src_corelib_kernel_qobject.cpp 21 \snippet code/src_corelib_kernel_qobject.cpp 21
As the code snippet above illustrates, you can use this function
to avoid emitting a signal that nobody listens to.
\warning This function violates the object-oriented principle of \warning This function violates the object-oriented principle of
modularity. However, it might be useful when you need to perform modularity. However, it might be useful when you need to perform
expensive initialization only if something is connected to a expensive initialization only if something is connected to a
signal. signal.
\sa isSignalConnected()
*/ */
int QObject::receivers(const char *signal) const int QObject::receivers(const char *signal) const
@ -2209,6 +2208,60 @@ int QObject::receivers(const char *signal) const
return receivers; return receivers;
} }
/*!
\since 5.0
Returns true if the \a signal is connected to at least one receiver,
otherwise returns false.
\a signal must be a signal member of this object, otherwise the behaviour
is undefined.
\snippet code/src_corelib_kernel_qobject.cpp 21
As the code snippet above illustrates, you can use this function
to avoid emitting a signal that nobody listens to.
\warning This function violates the object-oriented principle of
modularity. However, it might be useful when you need to perform
expensive initialization only if something is connected to a
signal.
*/
bool QObject::isSignalConnected(const QMetaMethod &signal) const
{
Q_D(const QObject);
if (!signal.mobj)
return false;
Q_ASSERT_X(signal.mobj->cast(this) && signal.methodType() == QMetaMethod::Signal,
"QObject::isSignalConnected" , "the parametter must be a signal member of the object");
uint signalIndex = (signal.handle - QMetaObjectPrivate::get(signal.mobj)->methodData)/5;
if (signal.mobj->d.data[signal.handle + 4] & MethodCloned)
signalIndex = QMetaObjectPrivate::originalClone(signal.mobj, signalIndex);
int signalOffset;
int methodOffset;
computeOffsets(signal.mobj, &signalOffset, &methodOffset);
signalIndex += signalOffset;
if (signalIndex < sizeof(d->connectedSignals) * 8)
return d->isSignalConnected(signalIndex);
QMutexLocker locker(signalSlotLock(this));
if (d->connectionLists) {
if (signalIndex < uint(d->connectionLists->count())) {
const QObjectPrivate::Connection *c =
d->connectionLists->at(signalIndex).first;
while (c) {
if (c->receiver)
return true;
c = c->nextConnectionList;
}
}
}
return false;
}
/*! /*!
\internal \internal

View File

@ -365,6 +365,7 @@ protected:
QObject *sender() const; QObject *sender() const;
int senderSignalIndex() const; int senderSignalIndex() const;
int receivers(const char* signal) const; int receivers(const char* signal) const;
bool isSignalConnected(const QMetaMethod &signal) const;
virtual void timerEvent(QTimerEvent *); virtual void timerEvent(QTimerEvent *);
virtual void childEvent(QChildEvent *); virtual void childEvent(QChildEvent *);

View File

@ -3774,6 +3774,7 @@ public:
void tst_QObject::isSignalConnected() void tst_QObject::isSignalConnected()
{ {
ManySignals o; ManySignals o;
const QMetaObject *meta = o.metaObject();
o.rec = 0; o.rec = 0;
#ifdef QT_BUILD_INTERNAL #ifdef QT_BUILD_INTERNAL
QObjectPrivate *priv = QObjectPrivate::get(&o); QObjectPrivate *priv = QObjectPrivate::get(&o);
@ -3784,6 +3785,13 @@ void tst_QObject::isSignalConnected()
QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig29()"))); QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig29()")));
QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig60()"))); QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig60()")));
#endif #endif
QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("destroyed()"))));
QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig00()"))));
QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig05()"))));
QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig15()"))));
QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig29()"))));
QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig60()"))));
QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig69()"))));
QObject::connect(&o, SIGNAL(sig00()), &o, SIGNAL(sig69())); QObject::connect(&o, SIGNAL(sig00()), &o, SIGNAL(sig69()));
QObject::connect(&o, SIGNAL(sig34()), &o, SIGNAL(sig03())); QObject::connect(&o, SIGNAL(sig34()), &o, SIGNAL(sig03()));
@ -3802,6 +3810,18 @@ void tst_QObject::isSignalConnected()
QVERIFY(priv->isSignalConnected(priv->signalIndex("sig69()"))); QVERIFY(priv->isSignalConnected(priv->signalIndex("sig69()")));
QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig18()"))); QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig18()")));
#endif #endif
QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("destroyed()"))));
QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("destroyed(QObject*)"))));
QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig05()"))));
QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig15()"))));
QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig29()"))));
QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig00()"))));
QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig03()"))));
QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig34()"))));
QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig69()"))));
QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig18()"))));
QObject::connect(&o, SIGNAL(sig18()), &o, SIGNAL(sig29())); QObject::connect(&o, SIGNAL(sig18()), &o, SIGNAL(sig29()));
QObject::connect(&o, SIGNAL(sig29()), &o, SIGNAL(sig62())); QObject::connect(&o, SIGNAL(sig29()), &o, SIGNAL(sig62()));
@ -3815,6 +3835,11 @@ void tst_QObject::isSignalConnected()
QVERIFY(priv->isSignalConnected(priv->signalIndex("sig69()"))); QVERIFY(priv->isSignalConnected(priv->signalIndex("sig69()")));
QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig27()"))); QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig27()")));
#endif #endif
QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig18()"))));
QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig62()"))));
QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig28()"))));
QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig69()"))));
QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig27()"))));
QCOMPARE(o.rec, 0); QCOMPARE(o.rec, 0);
emit o.sig01(); emit o.sig01();
@ -3845,6 +3870,12 @@ void tst_QObject::isSignalConnected()
QCOMPARE(o.rec, 2); QCOMPARE(o.rec, 2);
emit o.sig36(); emit o.sig36();
QCOMPARE(o.rec, 2); QCOMPARE(o.rec, 2);
QObject::connect(&o, &QObject::destroyed, qt_noop);
QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("destroyed()"))));
QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("destroyed(QObject*)"))));
QVERIFY(!o.isSignalConnected(QMetaMethod()));
} }
void tst_QObject::qMetaObjectConnect() void tst_QObject::qMetaObjectConnect()