Qt 4.8
qdeclarativepropertycache.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "private/qdeclarativepropertycache_p.h"
43 
44 #include "private/qdeclarativeengine_p.h"
45 #include "private/qdeclarativebinding_p.h"
46 #include <QtCore/qdebug.h>
47 
49 
51 
53 {
54  int propType = p.userType();
55 
56  Flags flags;
57 
58  if (p.isConstant())
59  flags |= Data::IsConstant;
60  if (p.isWritable())
61  flags |= Data::IsWritable;
62  if (p.isResettable())
63  flags |= Data::IsResettable;
64 
65  if (propType == qMetaTypeId<QDeclarativeBinding *>()) {
66  flags |= Data::IsQmlBinding;
67  } else if (propType == qMetaTypeId<QScriptValue>()) {
68  flags |= Data::IsQScriptValue;
69  } else if (p.isEnumType()) {
70  flags |= Data::IsEnumType;
71  } else {
75  flags |= Data::IsQObjectDerived;
76  else if (cat == QDeclarativeMetaType::List)
77  flags |= Data::IsQList;
78  }
79 
80  return flags;
81 }
82 
84 {
85  propType = p.userType();
87  propType = qMetaTypeId<QVariant>();
90  flags = flagsForProperty(p, engine);
91  revision = p.revision();
92 }
93 
95 {
96  coreIndex = m.methodIndex();
97  relatedIndex = -1;
102 
103  const char *returnType = m.typeName();
104  if (returnType)
105  propType = QMetaType::type(returnType);
106 
107  QList<QByteArray> params = m.parameterTypes();
108  if (!params.isEmpty())
110  revision = m.revision();
111 }
112 
113 
119 {
120  Q_ASSERT(engine);
121 }
122 
128 {
129  Q_ASSERT(engine);
130  Q_ASSERT(metaObject);
131 
132  update(engine, metaObject);
133 }
134 
136 {
137  clear();
138 }
139 
141 {
142  for (int ii = 0; ii < indexCache.count(); ++ii) {
143  if (indexCache.at(ii)) indexCache.at(ii)->release();
144  }
145 
146  for (int ii = 0; ii < methodIndexCache.count(); ++ii) {
147  RData *data = methodIndexCache.at(ii);
148  if (data) data->release();
149  }
150 
152  iter != stringCache.end(); ++iter) {
153  RData *data = (*iter);
154  data->release();
155  }
156 
157  for (IdentifierCache::ConstIterator iter = identifierCache.begin();
158  iter != identifierCache.end(); ++iter) {
159  RData *data = (*iter);
160  data->release();
161  }
162 
163  indexCache.clear();
165  stringCache.clear();
166  identifierCache.clear();
167 }
168 
170  const QString &property)
171 {
172  Q_ASSERT(metaObject);
173 
175  {
176  const QMetaObject *cmo = metaObject;
177  while (cmo) {
178  int idx = metaObject->indexOfProperty(property.toUtf8());
179  if (idx != -1) {
180  QMetaProperty p = metaObject->property(idx);
181  if (p.isScriptable()) {
182  rv.load(metaObject->property(idx));
183  return rv;
184  } else {
185  while (cmo && cmo->propertyOffset() >= idx)
186  cmo = cmo->superClass();
187  }
188  } else {
189  cmo = 0;
190  }
191  }
192  }
193 
194  int methodCount = metaObject->methodCount();
195  for (int ii = methodCount - 1; ii >= 3; --ii) { // >=3 to block the destroyed signal and deleteLater() slot
196  QMetaMethod m = metaObject->method(ii);
197  if (m.access() == QMetaMethod::Private)
198  continue;
200 
201  int parenIdx = methodName.indexOf(QLatin1Char('('));
202  Q_ASSERT(parenIdx != -1);
203  QStringRef methodNameRef = methodName.leftRef(parenIdx);
204 
205  if (methodNameRef == property) {
206  rv.load(m);
207  return rv;
208  }
209  }
210 
211  return rv;
212 }
213 
215 {
217  cache->indexCache = indexCache;
219  cache->stringCache = stringCache;
222 
223  for (int ii = 0; ii < indexCache.count(); ++ii) {
224  if (indexCache.at(ii)) indexCache.at(ii)->addref();
225  }
226  for (int ii = 0; ii < methodIndexCache.count(); ++ii) {
227  if (methodIndexCache.at(ii)) methodIndexCache.at(ii)->addref();
228  }
229  for (StringCache::ConstIterator iter = stringCache.begin(); iter != stringCache.end(); ++iter)
230  (*iter)->addref();
231  for (IdentifierCache::ConstIterator iter = identifierCache.begin(); iter != identifierCache.end(); ++iter)
232  (*iter)->addref();
233 
234  return cache;
235 }
236 
238  Data::Flag propertyFlags, Data::Flag methodFlags, Data::Flag signalFlags)
239 {
240  append(engine, metaObject, -1, propertyFlags, methodFlags, signalFlags);
241 }
242 
244  int revision,
245  Data::Flag propertyFlags, Data::Flag methodFlags, Data::Flag signalFlags)
246 {
247  Q_UNUSED(revision);
248 
250 
252  int methodCount = metaObject->methodCount();
253  // 3 to block the destroyed signal and the deleteLater() slot
254  int methodOffset = qMax(3, metaObject->methodOffset());
255 
256  methodIndexCache.resize(methodCount);
257  for (int ii = methodOffset; ii < methodCount; ++ii) {
258  QMetaMethod m = metaObject->method(ii);
259  if (m.access() == QMetaMethod::Private)
260  continue;
262 
263  int parenIdx = methodName.indexOf(QLatin1Char('('));
264  Q_ASSERT(parenIdx != -1);
265  methodName = methodName.left(parenIdx);
266 
267  RData *data = new RData;
268  data->identifier = enginePriv->objectClass->createPersistentIdentifier(methodName);
269  methodIndexCache[ii] = data;
270 
271  data->load(m);
273  data->flags |= methodFlags;
274  else if (m.methodType() == QMetaMethod::Signal)
275  data->flags |= signalFlags;
276 
278 
279  if (stringCache.contains(methodName)) {
280  RData *old = stringCache[methodName];
281  // We only overload methods in the same class, exactly like C++
282  if (old->flags & Data::IsFunction && old->coreIndex >= methodOffset)
283  data->relatedIndex = old->coreIndex;
284  data->overrideIndexIsProperty = !bool(old->flags & Data::IsFunction);
285  data->overrideIndex = old->coreIndex;
286  stringCache[methodName]->release();
287  identifierCache[data->identifier.identifier]->release();
288  }
289 
290  stringCache.insert(methodName, data);
291  identifierCache.insert(data->identifier.identifier, data);
292  data->addref();
293  data->addref();
294  }
295 
296  int propCount = metaObject->propertyCount();
297  int propOffset = metaObject->propertyOffset();
298 
299  indexCache.resize(propCount);
300  for (int ii = propOffset; ii < propCount; ++ii) {
301  QMetaProperty p = metaObject->property(ii);
302  if (!p.isScriptable())
303  continue;
304 
305  QString propName = QString::fromUtf8(p.name());
306 
307  RData *data = new RData;
308  data->identifier = enginePriv->objectClass->createPersistentIdentifier(propName);
309  indexCache[ii] = data;
310 
311  data->load(p, engine);
312  data->flags |= propertyFlags;
313 
314  data->metaObjectOffset = allowedRevisionCache.count() - 1;
315 
316  if (stringCache.contains(propName)) {
317  RData *old = stringCache[propName];
318  data->overrideIndexIsProperty = !bool(old->flags & Data::IsFunction);
319  data->overrideIndex = old->coreIndex;
320  stringCache[propName]->release();
321  identifierCache[data->identifier.identifier]->release();
322  }
323 
324  stringCache.insert(propName, data);
325  identifierCache.insert(data->identifier.identifier, data);
326  data->addref();
327  data->addref();
328  }
329 }
330 
332 {
333  if (!metaObject)
334  return;
335 
336  updateRecur(engine, metaObject->superClass());
337 
338  append(engine, metaObject);
339 }
340 
342 {
343  Q_ASSERT(engine);
344  Q_ASSERT(metaObject);
345 
346  clear();
347 
348  // Optimization to prevent unnecessary reallocation of lists
349  indexCache.reserve(metaObject->propertyCount());
350  methodIndexCache.reserve(metaObject->methodCount());
351 
352  updateRecur(engine,metaObject);
353 }
354 
357 {
358  if (index < 0 || index >= indexCache.count())
359  return 0;
360 
361  return indexCache.at(index);
362 }
363 
366 {
367  if (index < 0 || index >= methodIndexCache.count())
368  return 0;
369 
370  return methodIndexCache.at(index);
371 }
372 
375 {
376  return stringCache.value(str);
377 }
378 
380 {
381  if (!object)
382  return QString();
383 
384  return name(object->metaObject());
385 }
386 
388 {
389  if (!metaObject || coreIndex == -1)
390  return QString();
391 
392  if (flags & IsFunction) {
393  QMetaMethod m = metaObject->method(coreIndex);
394 
396  int parenIdx = name.indexOf(QLatin1Char('('));
397  if (parenIdx != -1)
398  name = name.left(parenIdx);
399  return name;
400  } else {
401  QMetaProperty p = metaObject->property(coreIndex);
402  return QString::fromUtf8(p.name());
403  }
404 }
405 
407 {
408  return stringCache.keys();
409 }
410 
413 {
415 
417 
418  QDeclarativePropertyCache *cache = 0;
420  if (ddata && ddata->propertyCache && ddata->propertyCache->qmlEngine() == engine)
421  cache = ddata->propertyCache;
422  if (!cache) {
423  cache = enginePrivate->cache(obj);
424  if (cache && ddata && !ddata->propertyCache) { cache->addref(); ddata->propertyCache = cache; }
425  }
426 
427  if (cache) {
428  rv = cache->property(name);
429  } else {
430  local = QDeclarativePropertyCache::create(obj->metaObject(), enginePrivate->objectClass->toString(name));
431  if (local.isValid())
432  rv = &local;
433  }
434 
435  return rv;
436 }
437 
439  const QString &name, Data &local)
440 {
442 
443  if (!engine) {
445  if (local.isValid())
446  rv = &local;
447  } else {
449 
450  QDeclarativePropertyCache *cache = 0;
452  if (ddata && ddata->propertyCache && ddata->propertyCache->qmlEngine() == engine)
453  cache = ddata->propertyCache;
454  if (!cache) {
455  cache = enginePrivate->cache(obj);
456  if (cache && ddata && !ddata->propertyCache) { cache->addref(); ddata->propertyCache = cache; }
457  }
458 
459  if (cache) {
460  rv = cache->property(name);
461  } else {
463  if (local.isValid())
464  rv = &local;
465  }
466  }
467 
468  return rv;
469 }
470 
The QMetaObject class contains meta-information about Qt objects.
Definition: qobjectdefs.h:304
QDeclarativePropertyCache * propertyCache
static QDeclarativeData * get(const QObject *object, bool create=false)
The QHash::const_iterator class provides an STL-style const iterator for QHash and QMultiHash...
Definition: qhash.h:395
bool isScriptable(const QObject *obj=0) const
Returns true if the property is scriptable for the given object; otherwise returns false...
bool isWritable() const
Returns true if this property is writable; otherwise returns false.
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
void clear()
Removes all items from the hash.
Definition: qhash.h:574
int methodIndex() const
Returns this method&#39;s index.
void updateRecur(QDeclarativeEngine *, const QMetaObject *)
int notifySignalIndex() const
Returns the index of the property change notifying signal if one was specified, otherwise returns -1...
int count(const T &t) const
Returns the number of occurrences of value in the vector.
Definition: qvector.h:742
QByteArray toUtf8() const Q_REQUIRED_RESULT
Returns a UTF-8 representation of the string as a QByteArray.
Definition: qstring.cpp:4074
QDeclarativePropertyCache * cache(QObject *obj)
Returns a QDeclarativePropertyCache for obj if one is available.
void update(QDeclarativeEngine *, const QMetaObject *)
int propertyCount() const
Returns the number of properties in this class, including the number of properties provided by each b...
The QString class provides a Unicode character string.
Definition: qstring.h:83
const char * typeName() const
Returns the return type of this method, or an empty string if the return type is void.
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
static QDeclarativeEnginePrivate * get(QDeclarativeEngine *e)
int indexOfProperty(const char *name) const
Finds property name and returns its index; otherwise returns -1.
bool contains(const Key &key) const
Returns true if the hash contains an item with the key; otherwise returns false.
Definition: qhash.h:872
int propertyIndex() const
Returns this property&#39;s index.
PersistentIdentifier createPersistentIdentifier(const QString &)
const T value(const Key &key) const
Returns the value associated with the key.
Definition: qhash.h:606
static TypeCategory typeCategory(int)
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
void resize(int size)
Sets the size of the vector to size.
Definition: qvector.h:342
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition: qhash.h:753
QStringRef leftRef(int n) const Q_REQUIRED_RESULT
Returns a substring reference to the n leftmost characters of the string.
Definition: qstring.cpp:9045
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
bool isEnumType() const
Returns true if the property&#39;s type is an enumeration value; otherwise returns false.
int methodOffset() const
Returns the method offset for this class; i.e.
int userType() const
Returns this property&#39;s user type.
QString left(int n) const Q_REQUIRED_RESULT
Returns a substring that contains the n leftmost characters of the string.
Definition: qstring.cpp:3664
void clear()
Removes all the elements from the vector and releases the memory used by the vector.
Definition: qvector.h:347
static Data create(const QMetaObject *, const QString &)
const char * name
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
QDeclarativeMetaType::TypeCategory typeCategory(int) const
Data * property(const QScriptDeclarativeClass::Identifier &id) const
static QString fromUtf8(const char *, int size=-1)
Returns a QString initialized with the first size bytes of the UTF-8 string str.
Definition: qstring.cpp:4302
void append(const T &t)
Inserts value at the end of the vector.
Definition: qvector.h:573
static const char * data(const QByteArray &arr)
int indexOf(QChar c, int from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:2838
Type
This enum type defines the types of variable that a QVariant can contain.
Definition: qvariant.h:95
void load(const QMetaProperty &, QDeclarativeEngine *engine=0)
QDeclarativeEngine * qmlEngine() const
static int type(const char *typeName)
Returns a handle to the type called typeName, or 0 if there is no such type.
Definition: qmetatype.cpp:607
const QMetaObject * superClass() const
Returns the meta-object of the superclass, or 0 if there is no such object.
Definition: qobjectdefs.h:494
The QStringRef class provides a thin wrapper around QString substrings.
Definition: qstring.h:1099
#define Q_DECLARE_METATYPE(TYPE)
This macro makes the type Type known to QMetaType as long as it provides a public default constructor...
Definition: qmetatype.h:265
const T & at(int i) const
Returns the item at index position i in the vector.
Definition: qvector.h:350
QDeclarativeObjectScriptClass * objectClass
bool isResettable() const
Returns true if this property can be reset to a default value; otherwise returns false.
MethodType methodType() const
Returns the type of this method (signal, slot, or method).
QList< QByteArray > parameterTypes() const
Returns a list of parameter types.
void append(QDeclarativeEngine *, const QMetaObject *, Data::Flag propertyFlags=Data::NoFlags, Data::Flag methodFlags=Data::NoFlags, Data::Flag signalFlags=Data::NoFlags)
iterator end()
Returns an STL-style iterator pointing to the imaginary item after the last item in the hash...
Definition: qhash.h:467
const char * name() const
Returns this property&#39;s name.
The QDeclarativeEngine class provides an environment for instantiating QML components.
static QByteArray methodName(const char *signature, int nameLength)
Makes a deep copy of the first nameLength characters of the given method signature and returns the co...
if(void) toggleToolbarShown
iterator begin()
Returns an STL-style iterator pointing to the first item in the hash.
Definition: qhash.h:464
QDeclarativePropertyCache(QDeclarativeEngine *)
Creates a new empty QDeclarativePropertyCache.
quint16 index
The QDeclarativeCleanup provides a callback when a QDeclarativeEngine is deleted. ...
int revision() const
Returns the method revision if one was specified by Q_REVISION, otherwise returns 0...
QMetaMethod method(int index) const
Returns the meta-data for the method with the given index.
The QMetaProperty class provides meta-data about a property.
Definition: qmetaobject.h:176
QScriptDeclarativeClass::PersistentIdentifier identifier
void reserve(int size)
Attempts to allocate memory for at least size elements.
Definition: qvector.h:339
int propertyOffset() const
Returns the property offset for this class; i.e.
const char * signature() const
Returns the signature of this method (e.g., setValue(double)).
int revision() const
Returns the property revision if one was specified by REVISION, otherwise returns 0...
Access access() const
Returns the access specification of this method (private, protected, or public).
Flags
The QScriptValue class acts as a container for the Qt Script data types.
Definition: qscriptvalue.h:57
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
QString toString(const Identifier &)
int methodCount() const
Returns the number of methods known to the meta-object system in this class, including the number of ...
QDeclarativePropertyCache * copy() const
QList< Key > keys() const
Returns a list containing all the keys in the hash, in an arbitrary order.
Definition: qhash.h:648
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
The QMetaMethod class provides meta-data about a member function.
Definition: qmetaobject.h:56
bool isConstant() const
virtual const QMetaObject * metaObject() const
Returns a pointer to the meta-object of this object.
QMetaProperty property(int index) const
Returns the meta-data for the property with the given index.
static Flags flagsForProperty(const QMetaProperty &, QDeclarativeEngine *engine=0)