source: trunk/src/declarative/qml/qdeclarativeboundsignal.cpp@ 1147

Last change on this file since 1147 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 8.7 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtDeclarative module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "private/qdeclarativeboundsignal_p.h"
43
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
53#include <QtCore/qdebug.h>
54
55QT_BEGIN_NAMESPACE
56
57class QDeclarativeBoundSignalParameters : public QObject
58{
59Q_OBJECT
60public:
61 QDeclarativeBoundSignalParameters(const QMetaMethod &, QObject * = 0);
62 ~QDeclarativeBoundSignalParameters();
63
64 void setValues(void **);
65 void clearValues();
66
67private:
68 friend class MetaObject;
69 int metaCall(QMetaObject::Call, int _id, void **);
70 struct MetaObject : public QAbstractDynamicMetaObject {
71 MetaObject(QDeclarativeBoundSignalParameters *b)
72 : parent(b) {}
73
74 int metaCall(QMetaObject::Call c, int id, void **a) {
75 return parent->metaCall(c, id, a);
76 }
77 QDeclarativeBoundSignalParameters *parent;
78 };
79
80 int *types;
81 void **values;
82 QMetaObject *myMetaObject;
83};
84
85static int evaluateIdx = -1;
86
87QDeclarativeAbstractBoundSignal::QDeclarativeAbstractBoundSignal(QObject *parent)
88: QObject(parent)
89{
90}
91
92QDeclarativeAbstractBoundSignal::~QDeclarativeAbstractBoundSignal()
93{
94}
95
96QDeclarativeBoundSignal::QDeclarativeBoundSignal(QObject *scope, const QMetaMethod &signal,
97 QObject *parent)
98: m_expression(0), m_signal(signal), m_paramsValid(false), m_isEvaluating(false), m_params(0)
99{
100 // This is thread safe. Although it may be updated by two threads, they
101 // will both set it to the same value - so the worst thing that can happen
102 // is that they both do the work to figure it out. Boo hoo.
103 if (evaluateIdx == -1) evaluateIdx = metaObject()->methodCount();
104
105 QDeclarative_setParent_noEvent(this, parent);
106 QDeclarativePropertyPrivate::connect(scope, m_signal.methodIndex(), this, evaluateIdx);
107}
108
109QDeclarativeBoundSignal::QDeclarativeBoundSignal(QDeclarativeContext *ctxt, const QString &val,
110 QObject *scope, const QMetaMethod &signal,
111 QObject *parent)
112: m_expression(0), m_signal(signal), m_paramsValid(false), m_isEvaluating(false), m_params(0)
113{
114 // This is thread safe. Although it may be updated by two threads, they
115 // will both set it to the same value - so the worst thing that can happen
116 // is that they both do the work to figure it out. Boo hoo.
117 if (evaluateIdx == -1) evaluateIdx = metaObject()->methodCount();
118
119 QDeclarative_setParent_noEvent(this, parent);
120 QDeclarativePropertyPrivate::connect(scope, m_signal.methodIndex(), this, evaluateIdx);
121
122 m_expression = new QDeclarativeExpression(ctxt, scope, val);
123}
124
125QDeclarativeBoundSignal::~QDeclarativeBoundSignal()
126{
127 delete m_expression;
128 m_expression = 0;
129}
130
131int QDeclarativeBoundSignal::index() const
132{
133 return m_signal.methodIndex();
134}
135
136/*!
137 Returns the signal expression.
138*/
139QDeclarativeExpression *QDeclarativeBoundSignal::expression() const
140{
141 return m_expression;
142}
143
144/*!
145 Sets the signal expression to \a e. Returns the current signal expression,
146 or null if there is no signal expression.
147
148 The QDeclarativeBoundSignal instance takes ownership of \a e. The caller is
149 assumes ownership of the returned QDeclarativeExpression.
150*/
151QDeclarativeExpression *QDeclarativeBoundSignal::setExpression(QDeclarativeExpression *e)
152{
153 QDeclarativeExpression *rv = m_expression;
154 m_expression = e;
155 if (m_expression) m_expression->setNotifyOnValueChanged(false);
156 return rv;
157}
158
159QDeclarativeBoundSignal *QDeclarativeBoundSignal::cast(QObject *o)
160{
161 QDeclarativeAbstractBoundSignal *s = qobject_cast<QDeclarativeAbstractBoundSignal*>(o);
162 return static_cast<QDeclarativeBoundSignal *>(s);
163}
164
165int QDeclarativeBoundSignal::qt_metacall(QMetaObject::Call c, int id, void **a)
166{
167 if (c == QMetaObject::InvokeMetaMethod && id == evaluateIdx) {
168 m_isEvaluating = true;
169 if (!m_paramsValid) {
170 if (!m_signal.parameterTypes().isEmpty())
171 m_params = new QDeclarativeBoundSignalParameters(m_signal, this);
172 m_paramsValid = true;
173 }
174
175 if (m_params) m_params->setValues(a);
176 if (m_expression && m_expression->engine()) {
177 QDeclarativeExpressionPrivate::get(m_expression)->value(m_params);
178 if (m_expression && m_expression->hasError())
179 QDeclarativeEnginePrivate::warning(m_expression->engine(), m_expression->error());
180 }
181 if (m_params) m_params->clearValues();
182 m_isEvaluating = false;
183 return -1;
184 } else {
185 return QObject::qt_metacall(c, id, a);
186 }
187}
188
189QDeclarativeBoundSignalParameters::QDeclarativeBoundSignalParameters(const QMetaMethod &method,
190 QObject *parent)
191: QObject(parent), types(0), values(0)
192{
193 MetaObject *mo = new MetaObject(this);
194
195 // ### Optimize!
196 // ### Ensure only supported types are allowed, otherwise it might crash
197 QMetaObjectBuilder mob;
198 mob.setSuperClass(&QDeclarativeBoundSignalParameters::staticMetaObject);
199 mob.setClassName("QDeclarativeBoundSignalParameters");
200
201 QList<QByteArray> paramTypes = method.parameterTypes();
202 QList<QByteArray> paramNames = method.parameterNames();
203 types = new int[paramTypes.count()];
204 for (int ii = 0; ii < paramTypes.count(); ++ii) {
205 const QByteArray &type = paramTypes.at(ii);
206 const QByteArray &name = paramNames.at(ii);
207
208 if (name.isEmpty() || type.isEmpty()) {
209 types[ii] = 0;
210 continue;
211 }
212
213 QVariant::Type t = (QVariant::Type)QMetaType::type(type.constData());
214 if (QDeclarativeMetaType::isQObject(t)) {
215 types[ii] = QMetaType::QObjectStar;
216 QMetaPropertyBuilder prop = mob.addProperty(name, "QObject*");
217 prop.setWritable(false);
218 } else {
219 types[ii] = t;
220 QMetaPropertyBuilder prop = mob.addProperty(name, type);
221 prop.setWritable(false);
222 }
223 }
224 myMetaObject = mob.toMetaObject();
225 *static_cast<QMetaObject *>(mo) = *myMetaObject;
226
227 d_ptr->metaObject = mo;
228}
229
230QDeclarativeBoundSignalParameters::~QDeclarativeBoundSignalParameters()
231{
232 delete [] types;
233 qFree(myMetaObject);
234}
235
236void QDeclarativeBoundSignalParameters::setValues(void **v)
237{
238 values = v;
239}
240
241void QDeclarativeBoundSignalParameters::clearValues()
242{
243 values = 0;
244}
245
246int QDeclarativeBoundSignalParameters::metaCall(QMetaObject::Call c, int id, void **a)
247{
248 if (!values)
249 return -1;
250
251 if (c == QMetaObject::ReadProperty && id >= 1) {
252 QDeclarativeMetaType::copy(types[id - 1], a[0], values[id]);
253 return -1;
254 } else {
255 return qt_metacall(c, id, a);
256 }
257}
258
259QT_END_NAMESPACE
260
261#include <qdeclarativeboundsignal.moc>
Note: See TracBrowser for help on using the repository browser.