From 66399c6584a86180c1955e5d34617fa46b07f36e Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Mon, 2 Apr 2012 10:02:28 +1000 Subject: [PATCH] Also check notifier endpoints when checking whether a signal is connected. This is required for the QQmlBoundSignal optimizations. Change-Id: I63540b96cd7d4523ec49973a2540054c83d82b12 Reviewed-by: Chris Adams --- src/particles/qquickcustomaffector.cpp | 4 ++-- src/particles/qquickparticleaffector.cpp | 4 ++-- src/particles/qquickparticleemitter.cpp | 4 ++-- src/particles/qquicktrailemitter.cpp | 4 ++-- src/qml/qml/qqmldata_p.h | 1 + src/qml/qml/qqmlengine.cpp | 17 ++++++++++++++++- src/qml/qml/qqmlglobal_p.h | 15 +++++++++++++++ src/quick/items/context2d/qquickcanvasitem.cpp | 7 ++++++- src/quick/items/context2d/qquickcanvasitem_p.h | 1 + src/quick/items/qquickitem.cpp | 10 +++++++--- src/quick/items/qquickitem_p.h | 4 ++-- src/quick/items/qquickmousearea.cpp | 14 ++++++-------- src/quick/items/qquicktext.cpp | 8 ++++---- src/quick/items/qquickvisualdatamodel.cpp | 8 ++++++-- 14 files changed, 72 insertions(+), 29 deletions(-) diff --git a/src/particles/qquickcustomaffector.cpp b/src/particles/qquickcustomaffector.cpp index acec981..788e244 100644 --- a/src/particles/qquickcustomaffector.cpp +++ b/src/particles/qquickcustomaffector.cpp @@ -42,6 +42,7 @@ #include "qquickcustomaffector_p.h" #include #include +#include #include #include QT_BEGIN_NAMESPACE @@ -102,8 +103,7 @@ QQuickCustomAffector::QQuickCustomAffector(QQuickItem *parent) : bool QQuickCustomAffector::isAffectConnected() { - static int idx = QObjectPrivate::get(this)->signalIndex("affectParticles(QQmlV8Handle,qreal)"); - return QObjectPrivate::get(this)->isSignalConnected(idx); + IS_SIGNAL_CONNECTED(this, "affectParticles(QQmlV8Handle,qreal)"); } void QQuickCustomAffector::affectSystem(qreal dt) diff --git a/src/particles/qquickparticleaffector.cpp b/src/particles/qquickparticleaffector.cpp index 0005af8..e2be877 100644 --- a/src/particles/qquickparticleaffector.cpp +++ b/src/particles/qquickparticleaffector.cpp @@ -41,6 +41,7 @@ #include "qquickparticleaffector_p.h" #include +#include QT_BEGIN_NAMESPACE /*! @@ -146,8 +147,7 @@ QQuickParticleAffector::QQuickParticleAffector(QQuickItem *parent) : bool QQuickParticleAffector::isAffectedConnected() { - static int idx = QObjectPrivate::get(this)->signalIndex("affected(qreal,qreal)"); - return QObjectPrivate::get(this)->isSignalConnected(idx); + IS_SIGNAL_CONNECTED(this, "affected(qreal,qreal)"); } diff --git a/src/particles/qquickparticleemitter.cpp b/src/particles/qquickparticleemitter.cpp index 035d66c..8181e8b 100644 --- a/src/particles/qquickparticleemitter.cpp +++ b/src/particles/qquickparticleemitter.cpp @@ -41,6 +41,7 @@ #include "qquickparticleemitter_p.h" #include +#include QT_BEGIN_NAMESPACE @@ -253,8 +254,7 @@ QQuickParticleEmitter::~QQuickParticleEmitter() bool QQuickParticleEmitter::isEmitConnected() { - static int idx = QObjectPrivate::get(this)->signalIndex("emitParticles(QQmlV8Handle)"); - return QObjectPrivate::get(this)->isSignalConnected(idx); + IS_SIGNAL_CONNECTED(this, "emitParticles(QQmlV8Handle)"); } void QQuickParticleEmitter::componentComplete() diff --git a/src/particles/qquicktrailemitter.cpp b/src/particles/qquicktrailemitter.cpp index 32f8763..3ea68ce 100644 --- a/src/particles/qquicktrailemitter.cpp +++ b/src/particles/qquicktrailemitter.cpp @@ -41,6 +41,7 @@ #include "qquicktrailemitter_p.h" #include +#include #include QT_BEGIN_NAMESPACE @@ -126,8 +127,7 @@ QQuickTrailEmitter::QQuickTrailEmitter(QQuickItem *parent) : bool QQuickTrailEmitter::isEmitFollowConnected() { - static int idx = QObjectPrivate::get(this)->signalIndex("emitFollowParticles(QQmlV8Handle,QQmlV8Handle)"); - return QObjectPrivate::get(this)->isSignalConnected(idx); + IS_SIGNAL_CONNECTED(this, "emitFollowParticles(QQmlV8Handle,QQmlV8Handle)"); } void QQuickTrailEmitter::recalcParticlesPerSecond(){ diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h index b8eee47..1a188f9 100644 --- a/src/qml/qml/qqmldata_p.h +++ b/src/qml/qml/qqmldata_p.h @@ -133,6 +133,7 @@ public: inline QQmlNotifierEndpoint *notify(int index); void addNotify(int index, QQmlNotifierEndpoint *); int endpointCount(int index); + bool signalHasEndpoint(int index); // The context that created the C++ object QQmlContextData *context; diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 7317689..c1ce012 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -77,13 +77,13 @@ #include #include #include -#include #include #include #include #include #include +#include #include @@ -1155,6 +1155,21 @@ void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint) } } +bool QQml_isSignalConnected(QObject *obj, int signal_index, int index) +{ + QQmlData *data = QQmlData::get(obj); + return QObjectPrivate::get(obj)->isSignalConnected(signal_index) || (data && data->signalHasEndpoint(index)); +} + +/* + index MUST be the index returned by QMetaMethod::index() + This is different than the index returned by QObjectPrivate::signalIndex() +*/ +bool QQmlData::signalHasEndpoint(int index) +{ + return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64))); +} + QQmlNotifier *QQmlData::objectNameNotifier() const { if (!extendedData) extendedData = new QQmlDataExtended; diff --git a/src/qml/qml/qqmlglobal_p.h b/src/qml/qml/qqmlglobal_p.h index 2356b2d..04711ae 100644 --- a/src/qml/qml/qqmlglobal_p.h +++ b/src/qml/qml/qqmlglobal_p.h @@ -89,6 +89,21 @@ QT_BEGIN_NAMESPACE QMetaObject::connect(sender, signalIdx, receiver, methodIdx, Qt::DirectConnection); \ } +bool Q_QML_EXPORT QQml_isSignalConnected(QObject*, int, int); + +#define IS_SIGNAL_CONNECTED(Sender, Signal) \ +do { \ + QObject *sender = (Sender); \ + const char *signal = (Signal); \ + static int signalIdx = -1; \ + static int methodIdx = -1; \ + if (signalIdx < 0) { \ + signalIdx = QObjectPrivate::get(sender)->signalIndex(signal); \ + methodIdx = sender->metaObject()->indexOfSignal(signal); \ + } \ + return QQml_isSignalConnected(sender, signalIdx, methodIdx); \ +} while (0) + struct QQmlGraphics_DerivedObject : public QObject { void setParent_noEvent(QObject *parent) { diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp index 4f849c7..6c8c8f3 100644 --- a/src/quick/items/context2d/qquickcanvasitem.cpp +++ b/src/quick/items/context2d/qquickcanvasitem.cpp @@ -446,6 +446,11 @@ QQuickCanvasContext* QQuickCanvasItem::rawContext() const return d_func()->context; } +bool QQuickCanvasItem::isPaintConnected() +{ + IS_SIGNAL_CONNECTED(this, "paint(QRect)"); +} + void QQuickCanvasItem::sceneGraphInitialized() { Q_D(QQuickCanvasItem); @@ -456,7 +461,7 @@ void QQuickCanvasItem::sceneGraphInitialized() if (!d->contextType.isNull()) QMetaObject::invokeMethod(this, "delayedCreate", Qt::QueuedConnection); - else if (receivers(SIGNAL(paint(QRect))) > 0) + else if (isPaintConnected()) QMetaObject::invokeMethod(this, "requestPaint", Qt::QueuedConnection); } diff --git a/src/quick/items/context2d/qquickcanvasitem_p.h b/src/quick/items/context2d/qquickcanvasitem_p.h index 9a57733..5238fbc 100644 --- a/src/quick/items/context2d/qquickcanvasitem_p.h +++ b/src/quick/items/context2d/qquickcanvasitem_p.h @@ -158,6 +158,7 @@ private: bool createContext(const QString &contextType); void initializeContext(QQuickCanvasContext *context, const QVariantMap &args = QVariantMap()); QRect tiledRect(const QRectF &window, const QSize &tileSize); + bool isPaintConnected(); }; QT_END_NAMESPACE diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index cf06dc2..5259b62 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -907,9 +907,13 @@ const QQuickKeysAttached::SigMap QQuickKeysAttached::sigMap[] = { { 0, 0 } }; -bool QQuickKeysAttachedPrivate::isConnected(const char *signalName) +bool QQuickKeysAttached::isConnected(const char *signalName) { - return isSignalConnected(signalIndex(signalName)); + Q_D(QQuickKeysAttached); + //### doing two string-based lookups isn't ideal + int signal_index = d->signalIndex(signalName); + int index = metaObject()->indexOfSignal(signalName); + return QQml_isSignalConnected(this, signal_index, index); } /*! @@ -1369,7 +1373,7 @@ void QQuickKeysAttached::keyPressed(QKeyEvent *event, bool post) QByteArray keySignal = keyToSignal(event->key()); if (!keySignal.isEmpty()) { keySignal += "(QQuickKeyEvent*)"; - if (d->isConnected(keySignal)) { + if (isConnected(keySignal)) { // If we specifically handle a key then default to accepted ke.setAccepted(true); int idx = QQuickKeysAttached::staticMetaObject.indexOfSignal(keySignal); diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index 89c09ed..ed762d0 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -710,8 +710,6 @@ public: , inIM(false), enabled(true), imeItem(0), item(0) {} - bool isConnected(const char *signalName); - //loop detection bool inPress:1; bool inRelease:1; @@ -827,6 +825,8 @@ private: return keySignal; } + bool isConnected(const char *signalName); + struct SigMap { int key; const char *sig; diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp index 956ca09..9185556 100644 --- a/src/quick/items/qquickmousearea.cpp +++ b/src/quick/items/qquickmousearea.cpp @@ -45,6 +45,8 @@ #include "qquickevents_p_p.h" #include "qquickdrag_p.h" +#include + #include #include #include @@ -218,29 +220,25 @@ void QQuickMouseAreaPrivate::saveEvent(QMouseEvent *event) bool QQuickMouseAreaPrivate::isPressAndHoldConnected() { Q_Q(QQuickMouseArea); - static int idx = QObjectPrivate::get(q)->signalIndex("pressAndHold(QQuickMouseEvent*)"); - return QObjectPrivate::get(q)->isSignalConnected(idx); + IS_SIGNAL_CONNECTED(q, "pressAndHold(QQuickMouseEvent*)"); } bool QQuickMouseAreaPrivate::isDoubleClickConnected() { Q_Q(QQuickMouseArea); - static int idx = QObjectPrivate::get(q)->signalIndex("doubleClicked(QQuickMouseEvent*)"); - return QObjectPrivate::get(q)->isSignalConnected(idx); + IS_SIGNAL_CONNECTED(q, "doubleClicked(QQuickMouseEvent*)"); } bool QQuickMouseAreaPrivate::isClickConnected() { Q_Q(QQuickMouseArea); - static int idx = QObjectPrivate::get(q)->signalIndex("clicked(QQuickMouseEvent*)"); - return QObjectPrivate::get(q)->isSignalConnected(idx); + IS_SIGNAL_CONNECTED(q, "clicked(QQuickMouseEvent*)"); } bool QQuickMouseAreaPrivate::isWheelConnected() { Q_Q(QQuickMouseArea); - static int idx = QObjectPrivate::get(q)->signalIndex("wheel(QQuickWheelEvent*)"); - return QObjectPrivate::get(q)->isSignalConnected(idx); + IS_SIGNAL_CONNECTED(q, "wheel(QQuickWheelEvent*)"); } void QQuickMouseAreaPrivate::propagate(QQuickMouseEvent* event, PropagateType t) diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp index cfedfbd..2407ade 100644 --- a/src/quick/items/qquicktext.cpp +++ b/src/quick/items/qquicktext.cpp @@ -594,8 +594,8 @@ void QQuickText::doLayout() bool QQuickTextPrivate::isLineLaidOutConnected() { - static int idx = this->signalIndex("lineLaidOut(QQuickTextLine*)"); - return this->isSignalConnected(idx); + Q_Q(QQuickText); + IS_SIGNAL_CONNECTED(q, "lineLaidOut(QQuickTextLine*)"); } void QQuickTextPrivate::setupCustomLineGeometry(QTextLine &line, qreal &height, int lineOffset) @@ -2406,8 +2406,8 @@ QString QQuickTextPrivate::anchorAt(const QPointF &mousePos) bool QQuickTextPrivate::isLinkActivatedConnected() { - static int idx = this->signalIndex("linkActivated(QString)"); - return this->isSignalConnected(idx); + Q_Q(QQuickText); + IS_SIGNAL_CONNECTED(q, "linkActivated(QString)"); } /*! \internal */ diff --git a/src/quick/items/qquickvisualdatamodel.cpp b/src/quick/items/qquickvisualdatamodel.cpp index cea8396..5046b1a 100644 --- a/src/quick/items/qquickvisualdatamodel.cpp +++ b/src/quick/items/qquickvisualdatamodel.cpp @@ -1748,11 +1748,15 @@ void QQuickVisualDataGroupPrivate::setModel(QQuickVisualDataModel *m, Compositor group = g; } +static bool isChangedConnected(QObject *obj) +{ + IS_SIGNAL_CONNECTED(obj, "changed(QQmlV8Handle,QQmlV8Handle)"); +} + void QQuickVisualDataGroupPrivate::emitChanges(QV8Engine *engine) { Q_Q(QQuickVisualDataGroup); - static int idx = signalIndex("changed(QQmlV8Handle,QQmlV8Handle)"); - if (isSignalConnected(idx) && !changeSet.isEmpty()) { + if (isChangedConnected(q) && !changeSet.isEmpty()) { v8::HandleScope handleScope; v8::Context::Scope contextScope(engine->context()); v8::Local removed = QQuickVisualDataModelPrivate::buildChangeList(changeSet.removes()); -- 1.7.2.5