1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qdeclarativeboundsignal_p.h"
44 #include <private/qmetaobjectbuilder_p.h>
45 #include "qdeclarativeengine_p.h"
46 #include "qdeclarativeexpression_p.h"
47 #include "qdeclarativecontext_p.h"
48 #include "qdeclarativemetatype_p.h"
49 #include "qdeclarative.h"
50 #include "qdeclarativecontext.h"
51 #include "qdeclarativeglobal_p.h"
52 #include <private/qdeclarativedebugtrace_p.h>
53 #include <private/qv8debugservice_p.h>
55 #include <QtCore/qstringbuilder.h>
56 #include <QtCore/qdebug.h>
60 class QDeclarativeBoundSignalParameters : public QObject
64 QDeclarativeBoundSignalParameters(const QMetaMethod &, QObject * = 0);
65 ~QDeclarativeBoundSignalParameters();
67 void setValues(void **);
71 friend class MetaObject;
72 int metaCall(QMetaObject::Call, int _id, void **);
73 struct MetaObject : public QAbstractDynamicMetaObject {
74 MetaObject(QDeclarativeBoundSignalParameters *b)
77 int metaCall(QMetaObject::Call c, int id, void **a) {
78 return parent->metaCall(c, id, a);
80 QDeclarativeBoundSignalParameters *parent;
85 QMetaObject *myMetaObject;
88 static int evaluateIdx = -1;
90 QDeclarativeAbstractBoundSignal::QDeclarativeAbstractBoundSignal(QObject *parent)
95 QDeclarativeAbstractBoundSignal::~QDeclarativeAbstractBoundSignal()
99 QDeclarativeBoundSignal::QDeclarativeBoundSignal(QObject *scope, const QMetaMethod &signal,
101 : m_expression(0), m_signal(signal), m_paramsValid(false), m_isEvaluating(false), m_params(0)
103 // This is thread safe. Although it may be updated by two threads, they
104 // will both set it to the same value - so the worst thing that can happen
105 // is that they both do the work to figure it out. Boo hoo.
106 if (evaluateIdx == -1) evaluateIdx = metaObject()->methodCount();
108 QDeclarative_setParent_noEvent(this, parent);
109 QDeclarativePropertyPrivate::connect(scope, m_signal.methodIndex(), this, evaluateIdx);
112 QDeclarativeBoundSignal::QDeclarativeBoundSignal(QDeclarativeContext *ctxt, const QString &val,
113 QObject *scope, const QMetaMethod &signal,
115 : m_expression(0), m_signal(signal), m_paramsValid(false), m_isEvaluating(false), m_params(0)
117 // This is thread safe. Although it may be updated by two threads, they
118 // will both set it to the same value - so the worst thing that can happen
119 // is that they both do the work to figure it out. Boo hoo.
120 if (evaluateIdx == -1) evaluateIdx = metaObject()->methodCount();
122 QDeclarative_setParent_noEvent(this, parent);
123 QDeclarativePropertyPrivate::connect(scope, m_signal.methodIndex(), this, evaluateIdx);
125 m_expression = new QDeclarativeExpression(ctxt, scope, val);
128 QDeclarativeBoundSignal::~QDeclarativeBoundSignal()
134 int QDeclarativeBoundSignal::index() const
136 return m_signal.methodIndex();
140 Returns the signal expression.
142 QDeclarativeExpression *QDeclarativeBoundSignal::expression() const
148 Sets the signal expression to \a e. Returns the current signal expression,
149 or null if there is no signal expression.
151 The QDeclarativeBoundSignal instance takes ownership of \a e. The caller is
152 assumes ownership of the returned QDeclarativeExpression.
154 QDeclarativeExpression *QDeclarativeBoundSignal::setExpression(QDeclarativeExpression *e)
156 QDeclarativeExpression *rv = m_expression;
158 if (m_expression) m_expression->setNotifyOnValueChanged(false);
162 QDeclarativeBoundSignal *QDeclarativeBoundSignal::cast(QObject *o)
164 QDeclarativeAbstractBoundSignal *s = qobject_cast<QDeclarativeAbstractBoundSignal*>(o);
165 return static_cast<QDeclarativeBoundSignal *>(s);
168 int QDeclarativeBoundSignal::qt_metacall(QMetaObject::Call c, int id, void **a)
170 if (c == QMetaObject::InvokeMetaMethod && id == evaluateIdx) {
173 if (QDeclarativeDebugService::isDebuggingEnabled()) {
174 QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::HandlingSignal);
175 QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::HandlingSignal, QLatin1String(m_signal.signature()) % QLatin1String(": ") % m_expression->expression());
176 QDeclarativeDebugTrace::rangeLocation(QDeclarativeDebugTrace::HandlingSignal, m_expression->sourceFile(), m_expression->lineNumber());
177 QV8DebugService::instance()->signalEmitted(QString::fromAscii(m_signal.signature()));
179 m_isEvaluating = true;
180 if (!m_paramsValid) {
181 if (!m_signal.parameterTypes().isEmpty())
182 m_params = new QDeclarativeBoundSignalParameters(m_signal, this);
183 m_paramsValid = true;
186 if (m_params) m_params->setValues(a);
187 if (m_expression && m_expression->engine()) {
188 QDeclarativeExpressionPrivate::get(m_expression)->value(m_params);
189 if (m_expression && m_expression->hasError())
190 QDeclarativeEnginePrivate::warning(m_expression->engine(), m_expression->error());
192 if (m_params) m_params->clearValues();
193 m_isEvaluating = false;
194 QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::HandlingSignal);
197 return QObject::qt_metacall(c, id, a);
201 QDeclarativeBoundSignalParameters::QDeclarativeBoundSignalParameters(const QMetaMethod &method,
203 : QObject(parent), types(0), values(0)
205 MetaObject *mo = new MetaObject(this);
208 QMetaObjectBuilder mob;
209 mob.setSuperClass(&QDeclarativeBoundSignalParameters::staticMetaObject);
210 mob.setClassName("QDeclarativeBoundSignalParameters");
212 QList<QByteArray> paramTypes = method.parameterTypes();
213 QList<QByteArray> paramNames = method.parameterNames();
214 types = new int[paramTypes.count()];
215 for (int ii = 0; ii < paramTypes.count(); ++ii) {
216 const QByteArray &type = paramTypes.at(ii);
217 const QByteArray &name = paramNames.at(ii);
219 if (name.isEmpty() || type.isEmpty()) {
224 QVariant::Type t = (QVariant::Type)QMetaType::type(type.constData());
225 if (QDeclarativeMetaType::isQObject(t)) {
226 types[ii] = QMetaType::QObjectStar;
227 QMetaPropertyBuilder prop = mob.addProperty(name, "QObject*");
228 prop.setWritable(false);
230 QByteArray propType = type;
231 if (t >= QVariant::UserType || t == QVariant::Invalid) {
234 int scopeIdx = propType.lastIndexOf("::");
235 if (scopeIdx != -1) {
236 scope = propType.left(scopeIdx);
237 name = propType.mid(scopeIdx + 2);
241 const QMetaObject *meta;
243 meta = &QObject::staticQtMetaObject;
245 meta = parent->parent()->metaObject(); //### assumes parent->parent()
246 for (int i = meta->enumeratorCount() - 1; i >= 0; --i) {
247 QMetaEnum m = meta->enumerator(i);
248 if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope))) {
256 QMetaPropertyBuilder prop = mob.addProperty(name, propType);
257 prop.setWritable(false);
260 myMetaObject = mob.toMetaObject();
261 *static_cast<QMetaObject *>(mo) = *myMetaObject;
263 d_ptr->metaObject = mo;
266 QDeclarativeBoundSignalParameters::~QDeclarativeBoundSignalParameters()
272 void QDeclarativeBoundSignalParameters::setValues(void **v)
277 void QDeclarativeBoundSignalParameters::clearValues()
282 int QDeclarativeBoundSignalParameters::metaCall(QMetaObject::Call c, int id, void **a)
287 if (c == QMetaObject::ReadProperty && id >= 1) {
288 int t = types[id - 1];
290 QMetaType::destruct(t, p);
291 QMetaType::construct(t, p, values[id]);
294 return qt_metacall(c, id, a);
300 #include <qdeclarativeboundsignal.moc>