summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/declarative/qml/qmlboundsignal.cpp129
-rw-r--r--src/declarative/qml/qmlboundsignal_p.h55
-rw-r--r--src/declarative/qml/qmlenginedebug.cpp6
-rw-r--r--src/declarative/qml/qmlmetaproperty.cpp66
-rw-r--r--src/declarative/qml/qmlmetaproperty.h4
-rw-r--r--src/declarative/qml/qmlvme.cpp6
-rw-r--r--src/declarative/util/qmlconnection.cpp7
7 files changed, 200 insertions, 73 deletions
diff --git a/src/declarative/qml/qmlboundsignal.cpp b/src/declarative/qml/qmlboundsignal.cpp
index c43097e..08c3387 100644
--- a/src/declarative/qml/qmlboundsignal.cpp
+++ b/src/declarative/qml/qmlboundsignal.cpp
@@ -52,40 +52,135 @@
QT_BEGIN_NAMESPACE
-int QmlBoundSignal::evaluateIdx = -1;
-QmlBoundSignal::QmlBoundSignal(QmlContext *ctxt, const QString &val, QObject *me, int idx, QObject *parent)
-: QmlExpression(ctxt, val, me), _idx(idx)
+class QmlBoundSignalParameters : public QObject
+{
+Q_OBJECT
+public:
+ QmlBoundSignalParameters(const QMetaMethod &, QObject * = 0);
+ ~QmlBoundSignalParameters();
+
+ void setValues(void **);
+ void clearValues();
+
+private:
+ friend class MetaObject;
+ int metaCall(QMetaObject::Call, int _id, void **);
+ struct MetaObject : public QAbstractDynamicMetaObject {
+ MetaObject(QmlBoundSignalParameters *b)
+ : parent(b) {}
+
+ int metaCall(QMetaObject::Call c, int id, void **a) {
+ return parent->metaCall(c, id, a);
+ }
+ QmlBoundSignalParameters *parent;
+ };
+
+ int *types;
+ void **values;
+ QMetaObject *myMetaObject;
+};
+
+static int evaluateIdx = -1;
+
+QmlAbstractBoundSignal::QmlAbstractBoundSignal(QObject *parent)
+: QObject(parent)
+{
+}
+
+QmlAbstractBoundSignal::~QmlAbstractBoundSignal()
+{
+}
+
+QmlBoundSignal::QmlBoundSignal(QObject *scope, const QMetaMethod &signal,
+ QObject *parent)
+: m_expression(0), m_idx(signal.methodIndex()), m_params(0)
{
// A cached evaluation of the QmlExpression::value() slot index.
//
// This is thread safe. Although it may be updated by two threads, they
// will both set it to the same value - so the worst thing that can happen
// is that they both do the work to figure it out. Boo hoo.
- if (evaluateIdx == -1)
- evaluateIdx = QmlExpression::staticMetaObject.indexOfMethod("value()");
+ if (evaluateIdx == -1) evaluateIdx = metaObject()->methodCount();
- setTrackChange(false);
QFx_setParent_noEvent(this, parent);
- QMetaObject::connect(me, _idx, this, evaluateIdx);
+ QMetaObject::connect(scope, m_idx, this, evaluateIdx);
+
+ if (!signal.parameterTypes().isEmpty())
+ m_params = new QmlBoundSignalParameters(signal, this);
}
-QmlBoundSignalProxy::QmlBoundSignalProxy(QmlContext *ctxt, const QString &val, QObject *me, int idx, QObject *parent)
-: QmlBoundSignal(ctxt, val, me, idx, parent)
+QmlBoundSignal::QmlBoundSignal(QmlContext *ctxt, const QString &val,
+ QObject *scope, const QMetaMethod &signal,
+ QObject *parent)
+: m_expression(0), m_idx(signal.methodIndex()), m_params(0)
{
- QMetaMethod signal = me->metaObject()->method(idx);
+ // A cached evaluation of the QmlExpression::value() slot index.
+ //
+ // This is thread safe. Although it may be updated by two threads, they
+ // will both set it to the same value - so the worst thing that can happen
+ // is that they both do the work to figure it out. Boo hoo.
+ if (evaluateIdx == -1) evaluateIdx = metaObject()->methodCount();
- params = new QmlBoundSignalParameters(signal, this);
+ QFx_setParent_noEvent(this, parent);
+ QMetaObject::connect(scope, m_idx, this, evaluateIdx);
+
+ m_expression = new QmlExpression(ctxt, val, scope);
+ m_expression->setTrackChange(false);
+
+ if (!signal.parameterTypes().isEmpty())
+ m_params = new QmlBoundSignalParameters(signal, this);
+}
+
+QmlBoundSignal::~QmlBoundSignal()
+{
+ delete m_expression;
+ m_expression = 0;
+}
+
+int QmlBoundSignal::index() const
+{
+ return m_idx;
}
-int QmlBoundSignalProxy::qt_metacall(QMetaObject::Call c, int id, void **a)
+/*!
+ Returns the signal expression.
+*/
+QmlExpression *QmlBoundSignal::expression() const
+{
+ return m_expression;
+}
+
+/*!
+ Sets the signal expression to \a e. Returns the current signal expression,
+ or null if there is no signal expression.
+
+ The QmlBoundSignal instance takes ownership of \a e. The caller is
+ assumes ownership of the returned QmlExpression.
+*/
+QmlExpression *QmlBoundSignal::setExpression(QmlExpression *e)
+{
+ QmlExpression *rv = m_expression;
+ m_expression = e;
+ if (m_expression) m_expression->setTrackChange(false);
+ return rv;
+}
+
+QmlBoundSignal *QmlBoundSignal::cast(QObject *o)
+{
+ QmlAbstractBoundSignal *s = qobject_cast<QmlAbstractBoundSignal*>(o);
+ return static_cast<QmlBoundSignal *>(s);
+}
+
+int QmlBoundSignal::qt_metacall(QMetaObject::Call c, int id, void **a)
{
if (c == QMetaObject::InvokeMetaMethod && id == evaluateIdx) {
- params->setValues(a);
- QmlExpressionPrivate::get(this)->value(params);
- params->clearValues();
+ if (m_params) m_params->setValues(a);
+ if (m_expression)
+ QmlExpressionPrivate::get(m_expression)->value(m_params);
+ if (m_params) m_params->clearValues();
return -1;
} else {
- return QmlBoundSignal::qt_metacall(c, id, a);
+ return QObject::qt_metacall(c, id, a);
}
}
@@ -157,3 +252,5 @@ int QmlBoundSignalParameters::metaCall(QMetaObject::Call c, int id, void **a)
}
QT_END_NAMESPACE
+
+#include "qmlboundsignal.moc"
diff --git a/src/declarative/qml/qmlboundsignal_p.h b/src/declarative/qml/qmlboundsignal_p.h
index de8f91d..51c7155 100644
--- a/src/declarative/qml/qmlboundsignal_p.h
+++ b/src/declarative/qml/qmlboundsignal_p.h
@@ -58,56 +58,37 @@
QT_BEGIN_NAMESPACE
-class QmlBoundSignal : public QmlExpression
+class QmlAbstractBoundSignal : public QObject
{
-Q_OBJECT
+ Q_OBJECT
public:
- QmlBoundSignal(QmlContext *, const QString &, QObject *me, int idx, QObject *parent);
-
- int index() const { return _idx; }
-protected:
- static int evaluateIdx;
-private:
- int _idx;
+ QmlAbstractBoundSignal(QObject *parent = 0);
+ virtual ~QmlAbstractBoundSignal() = 0;
};
-class QmlBoundSignalParameters : public QObject
+class QmlBoundSignalParameters;
+class QmlBoundSignal : public QmlAbstractBoundSignal
{
-Q_OBJECT
public:
- QmlBoundSignalParameters(const QMetaMethod &, QObject * = 0);
- ~QmlBoundSignalParameters();
-
- void setValues(void **);
- void clearValues();
-
-private:
- friend class MetaObject;
- int metaCall(QMetaObject::Call, int _id, void **);
- struct MetaObject : public QAbstractDynamicMetaObject {
- MetaObject(QmlBoundSignalParameters *b)
- : parent(b) {}
+ QmlBoundSignal(QObject *scope, const QMetaMethod &signal, QObject *parent);
+ QmlBoundSignal(QmlContext *ctxt, const QString &val, QObject *scope,
+ const QMetaMethod &signal, QObject *parent);
+ virtual ~QmlBoundSignal();
- int metaCall(QMetaObject::Call c, int id, void **a) {
- return parent->metaCall(c, id, a);
- }
- QmlBoundSignalParameters *parent;
- };
+ int index() const;
- int *types;
- void **values;
- QMetaObject *myMetaObject;
-};
+ QmlExpression *expression() const;
+ QmlExpression *setExpression(QmlExpression *);
-class QmlBoundSignalProxy : public QmlBoundSignal
-{
-public:
- QmlBoundSignalProxy(QmlContext *, const QString &, QObject *me, int idx, QObject *parent);
+ static QmlBoundSignal *cast(QObject *);
protected:
virtual int qt_metacall(QMetaObject::Call c, int id, void **a);
+
private:
- QmlBoundSignalParameters *params;
+ QmlExpression *m_expression;
+ int m_idx;
+ QmlBoundSignalParameters *m_params;
};
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlenginedebug.cpp b/src/declarative/qml/qmlenginedebug.cpp
index 7f9e530..a53ab2a 100644
--- a/src/declarative/qml/qmlenginedebug.cpp
+++ b/src/declarative/qml/qmlenginedebug.cpp
@@ -104,11 +104,7 @@ QmlEngineDebugServer::propertyData(QObject *obj, int propIdx)
if (prop.type() < QVariant::UserType) {
rv.type = QmlObjectProperty::Basic;
- if (qobject_cast<QmlBoundSignalParameters*>(obj) && prop.name() != QByteArray("objectName"))
- // these "properties" only have meaning during signal emission
- rv.value = tr("(signal parameter)");
- else
- rv.value = prop.read(obj);
+ rv.value = prop.read(obj);
} else if (QmlMetaType::isObject(prop.userType())) {
rv.type = QmlObjectProperty::Object;
} else if (QmlMetaType::isList(prop.userType()) ||
diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp
index 792b098..8f76240 100644
--- a/src/declarative/qml/qmlmetaproperty.cpp
+++ b/src/declarative/qml/qmlmetaproperty.cpp
@@ -547,6 +547,9 @@ QmlAbstractBinding *QmlMetaProperty::binding() const
\a newBinding will be enabled, and the returned binding (if any) will be
disabled.
+
+ Ownership of \a newBinding transfers to QML. Ownership of the return value
+ is assumed by the caller.
*/
QmlAbstractBinding *
QmlMetaProperty::setBinding(QmlAbstractBinding *newBinding) const
@@ -577,6 +580,59 @@ QmlMetaProperty::setBinding(QmlAbstractBinding *newBinding) const
return 0;
}
+/*!
+ Returns the expression associated with this signal property, or 0 if no
+ signal expression exists.
+*/
+QmlExpression *QmlMetaProperty::signalExpression() const
+{
+ if (!(type() & SignalProperty))
+ return 0;
+
+ const QObjectList &children = d->object->children();
+
+ for (int ii = 0; ii < children.count(); ++ii) {
+ QObject *child = children.at(ii);
+
+ QmlBoundSignal *signal = QmlBoundSignal::cast(child);
+ if (signal && signal->index() == coreIndex())
+ return signal->expression();
+ }
+
+ return 0;
+}
+
+/*!
+ Set the signal expression associated with this signal property to \a expr.
+ Returns the existing signal expression (if any), otherwise 0.
+
+ Ownership of \a expr transfers to QML. Ownership of the return value is
+ assumed by the caller.
+*/
+QmlExpression *QmlMetaProperty::setSignalExpression(QmlExpression *expr) const
+{
+ if (!(type() & SignalProperty))
+ return 0;
+
+ const QObjectList &children = d->object->children();
+
+ for (int ii = 0; ii < children.count(); ++ii) {
+ QObject *child = children.at(ii);
+
+ QmlBoundSignal *signal = QmlBoundSignal::cast(child);
+ if (signal && signal->index() == coreIndex())
+ return signal->setExpression(expr);
+ }
+
+ if (expr) {
+ QmlBoundSignal *signal = new QmlBoundSignal(d->object, d->signal,
+ d->object);
+ return signal->setExpression(expr);
+ } else {
+ return 0;
+ }
+}
+
void QmlMetaPropertyPrivate::findSignalInt(QObject *obj, const QString &name)
{
const QMetaObject *mo = obj->metaObject();
@@ -617,9 +673,9 @@ QVariant QmlMetaProperty::read() const
const QObjectList &children = object()->children();
for (int ii = 0; ii < children.count(); ++ii) {
- QmlBoundSignal *sig = qobject_cast<QmlBoundSignal *>(children.at(ii));
+ QmlBoundSignal *sig = QmlBoundSignal::cast(children.at(ii));
if (sig && sig->index() == d->coreIdx)
- return sig->expression();
+ return sig->expression()->expression();
}
} else if (type() & Property) {
if (type() & Attached) {
@@ -653,13 +709,13 @@ void QmlMetaPropertyPrivate::writeSignalProperty(const QVariant &value)
const QObjectList &children = object->children();
for (int ii = 0; ii < children.count(); ++ii) {
- QmlBoundSignal *sig = qobject_cast<QmlBoundSignal *>(children.at(ii));
+ QmlBoundSignal *sig = QmlBoundSignal::cast(children.at(ii));
if (sig && sig->index() == coreIdx) {
if (expr.isEmpty()) {
sig->disconnect();
sig->deleteLater();
} else {
- sig->setExpression(expr);
+ sig->expression()->setExpression(expr);
}
return;
}
@@ -667,7 +723,7 @@ void QmlMetaPropertyPrivate::writeSignalProperty(const QVariant &value)
if (!expr.isEmpty()) {
// XXX scope
- (void *)new QmlBoundSignal(qmlContext(object), expr, object, coreIdx, object);
+ (void *)new QmlBoundSignal(qmlContext(object), expr, object, signal, object);
}
}
diff --git a/src/declarative/qml/qmlmetaproperty.h b/src/declarative/qml/qmlmetaproperty.h
index 7b9ff47..62e93c4 100644
--- a/src/declarative/qml/qmlmetaproperty.h
+++ b/src/declarative/qml/qmlmetaproperty.h
@@ -53,6 +53,7 @@ QT_MODULE(Declarative)
class QObject;
class QmlAbstractBinding;
+class QmlExpression;
class QStringList;
class QVariant;
struct QMetaObject;
@@ -125,6 +126,9 @@ public:
QmlAbstractBinding *binding() const;
QmlAbstractBinding *setBinding(QmlAbstractBinding *) const;
+ QmlExpression *signalExpression() const;
+ QmlExpression *setSignalExpression(QmlExpression *) const;
+
static QmlMetaProperty createProperty(QObject *, const QString &);
int coreIndex() const;
diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp
index ca88455..d377cc3 100644
--- a/src/declarative/qml/qmlvme.cpp
+++ b/src/declarative/qml/qmlvme.cpp
@@ -537,11 +537,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QmlCompiledData
QMetaMethod signal =
target->metaObject()->method(instr.storeSignal.signalIndex);
- if (signal.parameterTypes().isEmpty()) {
- (void *)new QmlBoundSignal(ctxt, primitives.at(instr.storeSignal.value), target, instr.storeSignal.signalIndex, target);
- } else {
- (void *)new QmlBoundSignalProxy(ctxt, primitives.at(instr.storeSignal.value), target, instr.storeSignal.signalIndex, target);
- }
+ (void *)new QmlBoundSignal(ctxt, primitives.at(instr.storeSignal.value), target, signal, target);
}
break;
diff --git a/src/declarative/util/qmlconnection.cpp b/src/declarative/util/qmlconnection.cpp
index 6dca2d1..c77d0f6 100644
--- a/src/declarative/util/qmlconnection.cpp
+++ b/src/declarative/util/qmlconnection.cpp
@@ -187,10 +187,7 @@ void QmlConnection::connectIfValid()
return;
}
- if (sigparams.isEmpty())
- d->boundsignal = new QmlBoundSignal(qmlContext(this), d->script, sender, sigIdx, this);
- else
- d->boundsignal = new QmlBoundSignalProxy(new QmlContext(qmlContext(this),this), d->script, sender, sigIdx, this);
+ d->boundsignal = new QmlBoundSignal(qmlContext(this), d->script, sender, mo->method(sigIdx), this);
}
}
@@ -238,7 +235,7 @@ void QmlConnection::setScript(const QString& script)
} else {
// must exist - update
d->script = script;
- d->boundsignal->setExpression(script);
+ d->boundsignal->expression()->setExpression(script);
}
} else {
d->script = script;