source: trunk/src/declarative/util/qdeclarativeopenmetaobject.cpp@ 1008

Last change on this file since 1008 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: 10.9 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/qdeclarativeopenmetaobject_p.h"
43#include "private/qdeclarativepropertycache_p.h"
44#include "private/qdeclarativedata_p.h"
45#include <qmetaobjectbuilder_p.h>
46#include <qdebug.h>
47
48QT_BEGIN_NAMESPACE
49
50
51class QDeclarativeOpenMetaObjectTypePrivate
52{
53public:
54 QDeclarativeOpenMetaObjectTypePrivate() : mem(0), cache(0), engine(0) {}
55
56 void init(const QMetaObject *metaObj);
57
58 int propertyOffset;
59 int signalOffset;
60 QHash<QByteArray, int> names;
61 QMetaObjectBuilder mob;
62 QMetaObject *mem;
63 QDeclarativePropertyCache *cache;
64 QDeclarativeEngine *engine;
65 QSet<QDeclarativeOpenMetaObject*> referers;
66};
67
68QDeclarativeOpenMetaObjectType::QDeclarativeOpenMetaObjectType(const QMetaObject *base, QDeclarativeEngine *engine)
69 : d(new QDeclarativeOpenMetaObjectTypePrivate)
70{
71 d->engine = engine;
72 d->init(base);
73}
74
75QDeclarativeOpenMetaObjectType::~QDeclarativeOpenMetaObjectType()
76{
77 if (d->mem)
78 qFree(d->mem);
79 if (d->cache)
80 d->cache->release();
81 delete d;
82}
83
84
85int QDeclarativeOpenMetaObjectType::propertyOffset() const
86{
87 return d->propertyOffset;
88}
89
90int QDeclarativeOpenMetaObjectType::signalOffset() const
91{
92 return d->signalOffset;
93}
94
95int QDeclarativeOpenMetaObjectType::createProperty(const QByteArray &name)
96{
97 int id = d->mob.propertyCount();
98 d->mob.addSignal("__" + QByteArray::number(id) + "()");
99 QMetaPropertyBuilder build = d->mob.addProperty(name, "QVariant", id);
100 build.setDynamic(true);
101 propertyCreated(id, build);
102 qFree(d->mem);
103 d->mem = d->mob.toMetaObject();
104 d->names.insert(name, id);
105 QSet<QDeclarativeOpenMetaObject*>::iterator it = d->referers.begin();
106 while (it != d->referers.end()) {
107 QDeclarativeOpenMetaObject *omo = *it;
108 *static_cast<QMetaObject *>(omo) = *d->mem;
109 if (d->cache)
110 d->cache->update(d->engine, omo);
111 ++it;
112 }
113
114 return d->propertyOffset + id;
115}
116
117void QDeclarativeOpenMetaObjectType::propertyCreated(int id, QMetaPropertyBuilder &builder)
118{
119 if (d->referers.count())
120 (*d->referers.begin())->propertyCreated(id, builder);
121}
122
123void QDeclarativeOpenMetaObjectTypePrivate::init(const QMetaObject *metaObj)
124{
125 if (!mem) {
126 mob.setSuperClass(metaObj);
127 mob.setClassName(metaObj->className());
128 mob.setFlags(QMetaObjectBuilder::DynamicMetaObject);
129
130 mem = mob.toMetaObject();
131
132 propertyOffset = mem->propertyOffset();
133 signalOffset = mem->methodOffset();
134 }
135}
136
137//----------------------------------------------------------------------------
138
139class QDeclarativeOpenMetaObjectPrivate
140{
141public:
142 QDeclarativeOpenMetaObjectPrivate(QDeclarativeOpenMetaObject *_q)
143 : q(_q), parent(0), type(0), cacheProperties(false) {}
144
145 inline QVariant &getData(int idx) {
146 while (data.count() <= idx)
147 data << QPair<QVariant, bool>(QVariant(), false);
148 QPair<QVariant, bool> &prop = data[idx];
149 if (!prop.second) {
150 prop.first = q->initialValue(idx);
151 prop.second = true;
152 }
153 return prop.first;
154 }
155
156 inline void writeData(int idx, const QVariant &value) {
157 while (data.count() <= idx)
158 data << QPair<QVariant, bool>(QVariant(), false);
159 QPair<QVariant, bool> &prop = data[idx];
160 prop.first = value;
161 prop.second = true;
162 }
163
164 inline bool hasData(int idx) const {
165 if (idx >= data.count())
166 return false;
167 return data[idx].second;
168 }
169
170 bool autoCreate;
171 QDeclarativeOpenMetaObject *q;
172 QAbstractDynamicMetaObject *parent;
173 QList<QPair<QVariant, bool> > data;
174 QObject *object;
175 QDeclarativeOpenMetaObjectType *type;
176 bool cacheProperties;
177};
178
179QDeclarativeOpenMetaObject::QDeclarativeOpenMetaObject(QObject *obj, bool automatic)
180: d(new QDeclarativeOpenMetaObjectPrivate(this))
181{
182 d->autoCreate = automatic;
183 d->object = obj;
184
185 d->type = new QDeclarativeOpenMetaObjectType(obj->metaObject(), 0);
186 d->type->d->referers.insert(this);
187
188 QObjectPrivate *op = QObjectPrivate::get(obj);
189 d->parent = static_cast<QAbstractDynamicMetaObject *>(op->metaObject);
190 *static_cast<QMetaObject *>(this) = *d->type->d->mem;
191 op->metaObject = this;
192}
193
194QDeclarativeOpenMetaObject::QDeclarativeOpenMetaObject(QObject *obj, QDeclarativeOpenMetaObjectType *type, bool automatic)
195: d(new QDeclarativeOpenMetaObjectPrivate(this))
196{
197 d->autoCreate = automatic;
198 d->object = obj;
199
200 d->type = type;
201 d->type->addref();
202 d->type->d->referers.insert(this);
203
204 QObjectPrivate *op = QObjectPrivate::get(obj);
205 d->parent = static_cast<QAbstractDynamicMetaObject *>(op->metaObject);
206 *static_cast<QMetaObject *>(this) = *d->type->d->mem;
207 op->metaObject = this;
208}
209
210QDeclarativeOpenMetaObject::~QDeclarativeOpenMetaObject()
211{
212 if (d->parent)
213 delete d->parent;
214 d->type->d->referers.remove(this);
215 d->type->release();
216 delete d;
217}
218
219QDeclarativeOpenMetaObjectType *QDeclarativeOpenMetaObject::type() const
220{
221 return d->type;
222}
223
224int QDeclarativeOpenMetaObject::metaCall(QMetaObject::Call c, int id, void **a)
225{
226 if (( c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty)
227 && id >= d->type->d->propertyOffset) {
228 int propId = id - d->type->d->propertyOffset;
229 if (c == QMetaObject::ReadProperty) {
230 propertyRead(propId);
231 *reinterpret_cast<QVariant *>(a[0]) = d->getData(propId);
232 } else if (c == QMetaObject::WriteProperty) {
233 if (propId <= d->data.count() || d->data[propId].first != *reinterpret_cast<QVariant *>(a[0])) {
234 propertyWrite(propId);
235 d->writeData(propId, *reinterpret_cast<QVariant *>(a[0]));
236 propertyWritten(propId);
237 activate(d->object, d->type->d->signalOffset + propId, 0);
238 }
239 }
240 return -1;
241 } else {
242 if (d->parent)
243 return d->parent->metaCall(c, id, a);
244 else
245 return d->object->qt_metacall(c, id, a);
246 }
247}
248
249QAbstractDynamicMetaObject *QDeclarativeOpenMetaObject::parent() const
250{
251 return d->parent;
252}
253
254QVariant QDeclarativeOpenMetaObject::value(int id) const
255{
256 return d->getData(id);
257}
258
259void QDeclarativeOpenMetaObject::setValue(int id, const QVariant &value)
260{
261 d->writeData(id, value);
262 activate(d->object, id + d->type->d->signalOffset, 0);
263}
264
265QVariant QDeclarativeOpenMetaObject::value(const QByteArray &name) const
266{
267 QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.find(name);
268 if (iter == d->type->d->names.end())
269 return QVariant();
270
271 return d->getData(*iter);
272}
273
274QVariant &QDeclarativeOpenMetaObject::operator[](const QByteArray &name)
275{
276 QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.find(name);
277 Q_ASSERT(iter != d->type->d->names.end());
278
279 return d->getData(*iter);
280}
281
282QVariant &QDeclarativeOpenMetaObject::operator[](int id)
283{
284 return d->getData(id);
285}
286
287void QDeclarativeOpenMetaObject::setValue(const QByteArray &name, const QVariant &val)
288{
289 QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.find(name);
290
291 int id = -1;
292 if (iter == d->type->d->names.end()) {
293 id = d->type->createProperty(name.constData()) - d->type->d->propertyOffset;
294 } else {
295 id = *iter;
296 }
297
298 QVariant &dataVal = d->getData(id);
299 if (dataVal == val)
300 return;
301
302 dataVal = val;
303 activate(d->object, id + d->type->d->signalOffset, 0);
304}
305
306// returns true if this value has been initialized by a call to either value() or setValue()
307bool QDeclarativeOpenMetaObject::hasValue(int id) const
308{
309 return d->hasData(id);
310}
311
312void QDeclarativeOpenMetaObject::setCached(bool c)
313{
314 if (c == d->cacheProperties || !d->type->d->engine)
315 return;
316
317 d->cacheProperties = c;
318
319 QDeclarativeData *qmldata = QDeclarativeData::get(d->object, true);
320 if (d->cacheProperties) {
321 if (!d->type->d->cache)
322 d->type->d->cache = new QDeclarativePropertyCache(d->type->d->engine, this);
323 qmldata->propertyCache = d->type->d->cache;
324 d->type->d->cache->addref();
325 } else {
326 if (d->type->d->cache)
327 d->type->d->cache->release();
328 qmldata->propertyCache = 0;
329 }
330}
331
332
333int QDeclarativeOpenMetaObject::createProperty(const char *name, const char *)
334{
335 if (d->autoCreate)
336 return d->type->createProperty(name);
337 else
338 return -1;
339}
340
341void QDeclarativeOpenMetaObject::propertyRead(int)
342{
343}
344
345void QDeclarativeOpenMetaObject::propertyWrite(int)
346{
347}
348
349void QDeclarativeOpenMetaObject::propertyWritten(int)
350{
351}
352
353void QDeclarativeOpenMetaObject::propertyCreated(int, QMetaPropertyBuilder &)
354{
355}
356
357QVariant QDeclarativeOpenMetaObject::initialValue(int)
358{
359 return QVariant();
360}
361
362int QDeclarativeOpenMetaObject::count() const
363{
364 return d->type->d->names.count();
365}
366
367QByteArray QDeclarativeOpenMetaObject::name(int idx) const
368{
369 Q_ASSERT(idx >= 0 && idx < d->type->d->names.count());
370
371 return d->type->d->mob.property(idx).name();
372}
373
374QObject *QDeclarativeOpenMetaObject::object() const
375{
376 return d->object;
377}
378
379QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.