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);
//! [48]
//! [49]
if (isSignalConnected(QMethaMethod::fromSignal(&MyObject::valueChanged))) {
QByteArray data;
data = get_the_value(); // expensive operation
emit valueChanged(data);
}
//! [49]
//! [meta data]
//: This is a comment for the translator.
//= qtn_foo_bar

View File

@ -2157,13 +2157,12 @@ int QObject::senderSignalIndex() const
\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.
\sa isSignalConnected()
*/
int QObject::receivers(const char *signal) const
@ -2209,6 +2208,60 @@ int QObject::receivers(const char *signal) const
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

View File

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

View File

@ -3774,6 +3774,7 @@ public:
void tst_QObject::isSignalConnected()
{
ManySignals o;
const QMetaObject *meta = o.metaObject();
o.rec = 0;
#ifdef QT_BUILD_INTERNAL
QObjectPrivate *priv = QObjectPrivate::get(&o);
@ -3784,6 +3785,13 @@ void tst_QObject::isSignalConnected()
QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig29()")));
QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig60()")));
#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(sig34()), &o, SIGNAL(sig03()));
@ -3802,6 +3810,18 @@ void tst_QObject::isSignalConnected()
QVERIFY(priv->isSignalConnected(priv->signalIndex("sig69()")));
QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig18()")));
#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(sig29()), &o, SIGNAL(sig62()));
@ -3815,6 +3835,11 @@ void tst_QObject::isSignalConnected()
QVERIFY(priv->isSignalConnected(priv->signalIndex("sig69()")));
QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig27()")));
#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);
emit o.sig01();
@ -3845,6 +3870,12 @@ void tst_QObject::isSignalConnected()
QCOMPARE(o.rec, 2);
emit o.sig36();
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()