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 "private/qdeclarativeboundsignal_p.h"
44 #include "private/qmetaobjectbuilder_p.h"
45 #include "private/qdeclarativeengine_p.h"
46 #include "private/qdeclarativeexpression_p.h"
47 #include "private/qdeclarativecontext_p.h"
48 #include "private/qdeclarativemetatype_p.h"
49 #include "qdeclarative.h"
50 #include "qdeclarativecontext.h"
51 #include "private/qdeclarativeglobal_p.h"
52 #include "private/qdeclarativedebugtrace_p.h"
54 #include <QtCore/qstringbuilder.h>
55 #include <QtCore/qdebug.h>
59 class QDeclarativeBoundSignalParameters : public QObject
63 QDeclarativeBoundSignalParameters(const QMetaMethod &, QObject * = 0);
64 ~QDeclarativeBoundSignalParameters();
66 void setValues(void **);
70 friend class MetaObject;
71 int metaCall(QMetaObject::Call, int _id, void **);
72 struct MetaObject : public QAbstractDynamicMetaObject {
73 MetaObject(QDeclarativeBoundSignalParameters *b)
76 int metaCall(QMetaObject::Call c, int id, void **a) {
77 return parent->metaCall(c, id, a);
79 QDeclarativeBoundSignalParameters *parent;
84 QMetaObject *myMetaObject;
87 static int evaluateIdx = -1;
89 QDeclarativeAbstractBoundSignal::QDeclarativeAbstractBoundSignal(QObject *parent)
94 QDeclarativeAbstractBoundSignal::~QDeclarativeAbstractBoundSignal()
98 QDeclarativeBoundSignal::QDeclarativeBoundSignal(QObject *scope, const QMetaMethod &signal,
100 : m_expression(0), m_signal(signal), m_paramsValid(false), m_isEvaluating(false), m_params(0)
102 // This is thread safe. Although it may be updated by two threads, they
103 // will both set it to the same value - so the worst thing that can happen
104 // is that they both do the work to figure it out. Boo hoo.
105 if (evaluateIdx == -1) evaluateIdx = metaObject()->methodCount();
107 QDeclarative_setParent_noEvent(this, parent);
108 QDeclarativePropertyPrivate::connect(scope, m_signal.methodIndex(), this, evaluateIdx);
111 QDeclarativeBoundSignal::QDeclarativeBoundSignal(QDeclarativeContext *ctxt, const QString &val,
112 QObject *scope, const QMetaMethod &signal,
114 : m_expression(0), m_signal(signal), m_paramsValid(false), m_isEvaluating(false), m_params(0)
116 // This is thread safe. Although it may be updated by two threads, they
117 // will both set it to the same value - so the worst thing that can happen
118 // is that they both do the work to figure it out. Boo hoo.
119 if (evaluateIdx == -1) evaluateIdx = metaObject()->methodCount();
121 QDeclarative_setParent_noEvent(this, parent);
122 QDeclarativePropertyPrivate::connect(scope, m_signal.methodIndex(), this, evaluateIdx);
124 m_expression = new QDeclarativeExpression(ctxt, scope, val);
127 QDeclarativeBoundSignal::~QDeclarativeBoundSignal()
133 int QDeclarativeBoundSignal::index() const
135 return m_signal.methodIndex();
139 Returns the signal expression.
141 QDeclarativeExpression *QDeclarativeBoundSignal::expression() const
147 Sets the signal expression to \a e. Returns the current signal expression,
148 or null if there is no signal expression.
150 The QDeclarativeBoundSignal instance takes ownership of \a e. The caller is
151 assumes ownership of the returned QDeclarativeExpression.
153 QDeclarativeExpression *QDeclarativeBoundSignal::setExpression(QDeclarativeExpression *e)
155 QDeclarativeExpression *rv = m_expression;
157 if (m_expression) m_expression->setNotifyOnValueChanged(false);
161 QDeclarativeBoundSignal *QDeclarativeBoundSignal::cast(QObject *o)
163 QDeclarativeAbstractBoundSignal *s = qobject_cast<QDeclarativeAbstractBoundSignal*>(o);
164 return static_cast<QDeclarativeBoundSignal *>(s);
167 int QDeclarativeBoundSignal::qt_metacall(QMetaObject::Call c, int id, void **a)
169 if (c == QMetaObject::InvokeMetaMethod && id == evaluateIdx) {
172 if (QDeclarativeDebugService::isDebuggingEnabled()) {
173 QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::HandlingSignal);
174 QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::HandlingSignal, QLatin1String(m_signal.signature()) % QLatin1String(": ") % m_expression->expression());
175 QDeclarativeDebugTrace::rangeLocation(QDeclarativeDebugTrace::HandlingSignal, m_expression->sourceFile(), m_expression->lineNumber());
177 m_isEvaluating = true;
178 if (!m_paramsValid) {
179 if (!m_signal.parameterTypes().isEmpty())
180 m_params = new QDeclarativeBoundSignalParameters(m_signal, this);
181 m_paramsValid = true;
184 if (m_params) m_params->setValues(a);
185 if (m_expression && m_expression->engine()) {
186 QDeclarativeExpressionPrivate::get(m_expression)->value(m_params);
187 if (m_expression && m_expression->hasError())
188 QDeclarativeEnginePrivate::warning(m_expression->engine(), m_expression->error());
190 if (m_params) m_params->clearValues();
191 m_isEvaluating = false;
192 QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::HandlingSignal);
195 return QObject::qt_metacall(c, id, a);
199 QDeclarativeBoundSignalParameters::QDeclarativeBoundSignalParameters(const QMetaMethod &method,
201 : QObject(parent), types(0), values(0)
203 MetaObject *mo = new MetaObject(this);
206 QMetaObjectBuilder mob;
207 mob.setSuperClass(&QDeclarativeBoundSignalParameters::staticMetaObject);
208 mob.setClassName("QDeclarativeBoundSignalParameters");
210 QList<QByteArray> paramTypes = method.parameterTypes();
211 QList<QByteArray> paramNames = method.parameterNames();
212 types = new int[paramTypes.count()];
213 for (int ii = 0; ii < paramTypes.count(); ++ii) {
214 const QByteArray &type = paramTypes.at(ii);
215 const QByteArray &name = paramNames.at(ii);
217 if (name.isEmpty() || type.isEmpty()) {
222 QVariant::Type t = (QVariant::Type)QMetaType::type(type.constData());
223 if (QDeclarativeMetaType::isQObject(t)) {
224 types[ii] = QMetaType::QObjectStar;
225 QMetaPropertyBuilder prop = mob.addProperty(name, "QObject*");
226 prop.setWritable(false);
228 QByteArray propType = type;
229 if (t >= QVariant::UserType || t == QVariant::Invalid) {
232 int scopeIdx = propType.lastIndexOf("::");
233 if (scopeIdx != -1) {
234 scope = propType.left(scopeIdx);
235 name = propType.mid(scopeIdx + 2);
239 const QMetaObject *meta;
241 meta = &QObject::staticQtMetaObject;
243 meta = parent->parent()->metaObject(); //### assumes parent->parent()
244 for (int i = meta->enumeratorCount() - 1; i >= 0; --i) {
245 QMetaEnum m = meta->enumerator(i);
246 if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope))) {
253 if (QDeclarativeMetaType::canCopy(t)) {
255 QMetaPropertyBuilder prop = mob.addProperty(name, propType);
256 prop.setWritable(false);
258 types[ii] = 0x80000000 | t;
259 QMetaPropertyBuilder prop = mob.addProperty(name, "QVariant");
260 prop.setWritable(false);
264 myMetaObject = mob.toMetaObject();
265 *static_cast<QMetaObject *>(mo) = *myMetaObject;
267 d_ptr->metaObject = mo;
270 QDeclarativeBoundSignalParameters::~QDeclarativeBoundSignalParameters()
276 void QDeclarativeBoundSignalParameters::setValues(void **v)
281 void QDeclarativeBoundSignalParameters::clearValues()
286 int QDeclarativeBoundSignalParameters::metaCall(QMetaObject::Call c, int id, void **a)
291 if (c == QMetaObject::ReadProperty && id >= 1) {
292 if (types[id - 1] & 0x80000000) {
293 *((QVariant *)a[0]) = QVariant(types[id - 1] & 0x7FFFFFFF, values[id]);
295 QDeclarativeMetaType::copy(types[id - 1], a[0], values[id]);
299 return qt_metacall(c, id, a);
305 #include <qdeclarativeboundsignal.moc>