Fix warnings in QtQml
[profile/ivi/qtdeclarative.git] / src / qml / qml / qqmlmetatype.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <QtQml/qqmlprivate.h>
43 #include "qqmlmetatype_p.h"
44
45 #include <private/qqmlproxymetaobject_p.h>
46 #include <private/qqmlcustomparser_p.h>
47 #include <private/qqmlguard_p.h>
48 #include <private/qhashedstring_p.h>
49
50 #include <QtCore/qdebug.h>
51 #include <QtCore/qstringlist.h>
52 #include <QtCore/qmetaobject.h>
53 #include <QtCore/qbitarray.h>
54 #include <QtCore/qreadwritelock.h>
55 #include <QtCore/private/qmetaobject_p.h>
56
57 #include <qmetatype.h>
58 #include <qobjectdefs.h>
59 #include <qbytearray.h>
60 #include <qreadwritelock.h>
61 #include <qstring.h>
62 #include <qstringlist.h>
63 #include <qvector.h>
64
65 #include <ctype.h>
66
67 QT_BEGIN_NAMESPACE
68
69 struct QQmlMetaTypeData
70 {
71     QQmlMetaTypeData();
72     ~QQmlMetaTypeData();
73     QList<QQmlType *> types;
74     typedef QHash<int, QQmlType *> Ids;
75     Ids idToType;
76     typedef QHash<QHashedStringRef,QQmlType *> Names;
77     Names nameToType;
78     typedef QHash<const QMetaObject *, QQmlType *> MetaObjects;
79     MetaObjects metaObjectToType;
80     typedef QHash<int, QQmlMetaType::StringConverter> StringConverters;
81     StringConverters stringConverters;
82
83     struct VersionedUri {
84         VersionedUri()
85         : majorVersion(0) {}
86         VersionedUri(const QHashedString &uri, int majorVersion)
87         : uri(uri), majorVersion(majorVersion) {}
88         bool operator==(const VersionedUri &other) const {
89             return other.majorVersion == majorVersion && other.uri == uri;
90         }
91         QHashedString uri;
92         int majorVersion;
93     };
94     typedef QHash<VersionedUri, QQmlTypeModule *> TypeModules;
95     TypeModules uriToModule;
96
97     struct SingletonTypeList {
98         SingletonTypeList() : sorted(true) {}
99         QList<QQmlMetaType::SingletonType> singletonTypes;
100         bool sorted;
101     };
102     typedef QStringHash<SingletonTypeList> SingletonTypes;
103     SingletonTypes singletonTypes;
104     int singletonTypeCount;
105
106     bool singletonTypeExists(const QString &uri, const QString &typeName, int major, int minor)
107     {
108         QQmlMetaTypeData::SingletonTypeList *apiList = singletonTypes.value(uri);
109         if (apiList) {
110             for (int i=0 ; i < apiList->singletonTypes.size() ; ++i) {
111                 const QQmlMetaType::SingletonType &import = apiList->singletonTypes.at(i);
112                 if (import.major == major && import.minor == minor && typeName == import.typeName)
113                     return true;
114             }
115         }
116
117         return false;
118     }
119
120     bool typeExists(const QString &uri, const QString &typeName, int major, int minor)
121     {
122         QQmlMetaTypeData::VersionedUri versionedUri(uri, major);
123         QQmlTypeModule *module = uriToModule.value(versionedUri);
124         return module && module->typeNoLock(typeName, minor) != 0;
125     }
126
127     QBitArray objects;
128     QBitArray interfaces;
129     QBitArray lists;
130
131     QList<QQmlPrivate::AutoParentFunction> parentFunctions;
132
133     QSet<QString> protectedNamespaces;
134
135     QString typeRegistrationNamespace;
136     QStringList typeRegistrationFailures;
137 };
138
139 class QQmlTypeModulePrivate
140 {
141 public:
142     QQmlTypeModulePrivate() 
143     : minMinorVersion(INT_MAX), maxMinorVersion(0) {}
144
145     QQmlMetaTypeData::VersionedUri uri;
146
147     int minMinorVersion;
148     int maxMinorVersion;
149
150     void add(QQmlType *);
151
152     QStringHash<QList<QQmlType *> > typeHash;
153     QList<QQmlType *> types;
154 };
155
156 Q_GLOBAL_STATIC(QQmlMetaTypeData, metaTypeData)
157 Q_GLOBAL_STATIC_WITH_ARGS(QReadWriteLock, metaTypeDataLock, (QReadWriteLock::Recursive))
158
159 static uint qHash(const QQmlMetaTypeData::VersionedUri &v)
160 {
161     return v.uri.hash() ^ qHash(v.majorVersion);
162 }
163
164 QQmlMetaTypeData::QQmlMetaTypeData()
165 : singletonTypeCount(0)
166 {
167 }
168
169 QQmlMetaTypeData::~QQmlMetaTypeData()
170 {
171     for (int i = 0; i < types.count(); ++i)
172         delete types.at(i);
173 }
174
175 class QQmlTypePrivate
176 {
177 public:
178     QQmlTypePrivate();
179
180     void init() const;
181     void initEnums() const;
182     void insertEnums(const QMetaObject *metaObject) const;
183
184     bool m_isInterface : 1;
185     const char *m_iid;
186     QHashedString m_module;
187     QString m_name;
188     QString m_elementName;
189     int m_version_maj;
190     int m_version_min;
191     int m_typeId; int m_listId; 
192     int m_revision;
193     mutable bool m_containsRevisionedAttributes;
194     mutable QQmlType *m_superType;
195
196     int m_allocationSize;
197     void (*m_newFunc)(void *);
198     QString m_noCreationReason;
199
200     const QMetaObject *m_baseMetaObject;
201     QQmlAttachedPropertiesFunc m_attachedPropertiesFunc;
202     const QMetaObject *m_attachedPropertiesType;
203     int m_attachedPropertiesId;
204     int m_parserStatusCast;
205     int m_propertyValueSourceCast;
206     int m_propertyValueInterceptorCast;
207     QObject *(*m_extFunc)(QObject *);
208     const QMetaObject *m_extMetaObject;
209     int m_index;
210     QQmlCustomParser *m_customParser;
211     mutable volatile bool m_isSetup:1;
212     mutable volatile bool m_isEnumSetup:1;
213     mutable bool m_haveSuperType:1;
214     mutable QList<QQmlProxyMetaObject::ProxyData> m_metaObjects;
215     mutable QStringHash<int> m_enums;
216
217     static QHash<const QMetaObject *, int> m_attachedPropertyIds;
218 };
219
220 // Avoid multiple fromUtf8(), copies and hashing of the module name.
221 // This is only called when metaTypeDataLock is locked.
222 static QHashedString moduleFromUtf8(const char *module)
223 {
224     if (!module)
225         return QHashedString();
226
227     static const char *lastModule = 0;
228     static QHashedString lastModuleStr;
229
230     // Separate plugins may have different strings at the same address
231     QHashedCStringRef currentModule(module, ::strlen(module));
232     if ((lastModule != module) || (lastModuleStr.hash() != currentModule.hash())) {
233         lastModuleStr = QString::fromUtf8(module);
234         lastModuleStr.hash();
235         lastModule = module;
236     }
237
238     return lastModuleStr;
239 }
240
241 QHash<const QMetaObject *, int> QQmlTypePrivate::m_attachedPropertyIds;
242
243 QQmlTypePrivate::QQmlTypePrivate()
244 : m_isInterface(false), m_iid(0), m_typeId(0), m_listId(0), m_revision(0), m_containsRevisionedAttributes(false),
245   m_superType(0), m_allocationSize(0), m_newFunc(0), m_baseMetaObject(0), m_attachedPropertiesFunc(0), 
246   m_attachedPropertiesType(0), m_parserStatusCast(-1), m_propertyValueSourceCast(-1), 
247   m_propertyValueInterceptorCast(-1), m_extFunc(0), m_extMetaObject(0), m_index(-1), m_customParser(0), 
248   m_isSetup(false), m_isEnumSetup(false), m_haveSuperType(false)
249 {
250 }
251
252
253 QQmlType::QQmlType(int index, const QQmlPrivate::RegisterInterface &interface)
254 : d(new QQmlTypePrivate)
255 {
256     d->m_isInterface = true;
257     d->m_iid = interface.iid;
258     d->m_typeId = interface.typeId;
259     d->m_listId = interface.listId;
260     d->m_newFunc = 0;
261     d->m_index = index;
262     d->m_isSetup = true;
263     d->m_version_maj = 0;
264     d->m_version_min = 0;
265 }
266
267 QQmlType::QQmlType(int index, const QString &elementName, const QQmlPrivate::RegisterType &type)
268 : d(new QQmlTypePrivate)
269 {
270     d->m_elementName = elementName;
271     d->m_module = moduleFromUtf8(type.uri);
272
273     d->m_version_maj = type.versionMajor;
274     d->m_version_min = type.versionMinor;
275     if (type.version >= 1) // revisions added in version 1
276         d->m_revision = type.revision;
277     d->m_typeId = type.typeId;
278     d->m_listId = type.listId;
279     d->m_allocationSize = type.objectSize;
280     d->m_newFunc = type.create;
281     d->m_noCreationReason = type.noCreationReason;
282     d->m_baseMetaObject = type.metaObject;
283     d->m_attachedPropertiesFunc = type.attachedPropertiesFunction;
284     d->m_attachedPropertiesType = type.attachedPropertiesMetaObject;
285     if (d->m_attachedPropertiesType) {
286         QHash<const QMetaObject *, int>::Iterator iter = d->m_attachedPropertyIds.find(d->m_baseMetaObject);
287         if (iter == d->m_attachedPropertyIds.end())
288             iter = d->m_attachedPropertyIds.insert(d->m_baseMetaObject, index);
289         d->m_attachedPropertiesId = *iter;
290     } else {
291         d->m_attachedPropertiesId = -1;
292     }
293     d->m_parserStatusCast = type.parserStatusCast;
294     d->m_propertyValueSourceCast = type.valueSourceCast;
295     d->m_propertyValueInterceptorCast = type.valueInterceptorCast;
296     d->m_extFunc = type.extensionObjectCreate;
297     d->m_index = index;
298     d->m_customParser = type.customParser;
299
300     if (type.extensionMetaObject)
301         d->m_extMetaObject = type.extensionMetaObject;
302 }
303
304 QQmlType::~QQmlType()
305 {
306     delete d->m_customParser;
307     delete d;
308 }
309
310 const QHashedString &QQmlType::module() const
311 {
312     return d->m_module;
313 }
314
315 int QQmlType::majorVersion() const
316 {
317     return d->m_version_maj;
318 }
319
320 int QQmlType::minorVersion() const
321 {
322     return d->m_version_min;
323 }
324
325 bool QQmlType::availableInVersion(int vmajor, int vminor) const
326 {
327     Q_ASSERT(vmajor >= 0 && vminor >= 0);
328     return vmajor == d->m_version_maj && vminor >= d->m_version_min;
329 }
330
331 bool QQmlType::availableInVersion(const QHashedStringRef &module, int vmajor, int vminor) const
332 {
333     Q_ASSERT(vmajor >= 0 && vminor >= 0);
334     return module == d->m_module && vmajor == d->m_version_maj && vminor >= d->m_version_min;
335 }
336
337 // returns the nearest _registered_ super class
338 QQmlType *QQmlType::superType() const
339 {
340     if (!d->m_haveSuperType) {
341         const QMetaObject *mo = d->m_baseMetaObject->superClass();
342         while (mo && !d->m_superType) {
343             d->m_superType = QQmlMetaType::qmlType(mo, d->m_module, d->m_version_maj, d->m_version_min);
344             mo = mo->superClass();
345         }
346         d->m_haveSuperType = true;
347     }
348
349     return d->m_superType;
350 }
351
352 static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo, 
353                   const QMetaObject *ignoreStart, const QMetaObject *ignoreEnd)
354 {
355     // Set classname
356     builder.setClassName(ignoreEnd->className());
357
358     // Clone Q_CLASSINFO
359     for (int ii = mo->classInfoOffset(); ii < mo->classInfoCount(); ++ii) {
360         QMetaClassInfo info = mo->classInfo(ii);
361
362         int otherIndex = ignoreEnd->indexOfClassInfo(info.name());
363         if (otherIndex >= ignoreStart->classInfoOffset() + ignoreStart->classInfoCount()) {
364             // Skip 
365         } else {
366             builder.addClassInfo(info.name(), info.value());
367         }
368     }
369
370     // Clone Q_PROPERTY
371     for (int ii = mo->propertyOffset(); ii < mo->propertyCount(); ++ii) {
372         QMetaProperty property = mo->property(ii);
373
374         int otherIndex = ignoreEnd->indexOfProperty(property.name());
375         if (otherIndex >= ignoreStart->propertyOffset() + ignoreStart->propertyCount()) {
376             builder.addProperty(QByteArray("__qml_ignore__") + property.name(), QByteArray("void"));
377             // Skip 
378         } else {
379             builder.addProperty(property);
380         }
381     }
382
383     // Clone Q_METHODS
384     for (int ii = mo->methodOffset(); ii < mo->methodCount(); ++ii) {
385         QMetaMethod method = mo->method(ii);
386
387         // More complex - need to search name
388         QByteArray name = method.name();
389
390
391         bool found = false;
392
393         for (int ii = ignoreStart->methodOffset() + ignoreStart->methodCount(); 
394              !found && ii < ignoreEnd->methodOffset() + ignoreEnd->methodCount();
395              ++ii) {
396
397             QMetaMethod other = ignoreEnd->method(ii);
398
399             found = name == other.name();
400         }
401
402         QMetaMethodBuilder m = builder.addMethod(method);
403         if (found) // SKIP
404             m.setAccess(QMetaMethod::Private);
405     }
406
407     // Clone Q_ENUMS
408     for (int ii = mo->enumeratorOffset(); ii < mo->enumeratorCount(); ++ii) {
409         QMetaEnum enumerator = mo->enumerator(ii);
410
411         int otherIndex = ignoreEnd->indexOfEnumerator(enumerator.name());
412         if (otherIndex >= ignoreStart->enumeratorOffset() + ignoreStart->enumeratorCount()) {
413             // Skip 
414         } else {
415             builder.addEnumerator(enumerator);
416         }
417     }
418 }
419
420 static bool isPropertyRevisioned(const QMetaObject *mo, int index)
421 {
422     int i = index;
423     i -= mo->propertyOffset();
424     if (i < 0 && mo->d.superdata)
425         return isPropertyRevisioned(mo->d.superdata, index);
426
427     const QMetaObjectPrivate *mop = reinterpret_cast<const QMetaObjectPrivate*>(mo->d.data);
428     if (i >= 0 && i < mop->propertyCount) {
429         int handle = mop->propertyData + 3*i;
430         int flags = mo->d.data[handle + 2];
431
432         return (flags & Revisioned);
433     }
434
435     return false;
436 }
437
438 void QQmlTypePrivate::init() const
439 {
440     if (m_isSetup) return;
441
442     QWriteLocker lock(metaTypeDataLock());
443     if (m_isSetup)
444         return;
445
446     // Setup extended meta object
447     // XXX - very inefficient
448     const QMetaObject *mo = m_baseMetaObject;
449     if (m_extFunc) {
450         QMetaObjectBuilder builder;
451         clone(builder, m_extMetaObject, m_extMetaObject, m_extMetaObject);
452         builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
453         QMetaObject *mmo = builder.toMetaObject();
454         mmo->d.superdata = mo;
455         QQmlProxyMetaObject::ProxyData data = { mmo, m_extFunc, 0, 0 };
456         m_metaObjects << data;
457     }
458
459     mo = mo->d.superdata;
460     while(mo) {
461         QQmlType *t = metaTypeData()->metaObjectToType.value(mo);
462         if (t) {
463             if (t->d->m_extFunc) {
464                 QMetaObjectBuilder builder;
465                 clone(builder, t->d->m_extMetaObject, t->d->m_baseMetaObject, m_baseMetaObject);
466                 builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
467                 QMetaObject *mmo = builder.toMetaObject();
468                 mmo->d.superdata = m_baseMetaObject;
469                 if (!m_metaObjects.isEmpty())
470                     m_metaObjects.last().metaObject->d.superdata = mmo;
471                 QQmlProxyMetaObject::ProxyData data = { mmo, t->d->m_extFunc, 0, 0 };
472                 m_metaObjects << data;
473             }
474         }
475         mo = mo->d.superdata;
476     }
477
478     for (int ii = 0; ii < m_metaObjects.count(); ++ii) {
479         m_metaObjects[ii].propertyOffset =
480             m_metaObjects.at(ii).metaObject->propertyOffset();
481         m_metaObjects[ii].methodOffset =
482             m_metaObjects.at(ii).metaObject->methodOffset();
483     }
484     
485     // Check for revisioned details
486     {
487         const QMetaObject *mo = 0;
488         if (m_metaObjects.isEmpty())
489             mo = m_baseMetaObject;
490         else
491             mo = m_metaObjects.first().metaObject;
492
493         for (int ii = 0; !m_containsRevisionedAttributes && ii < mo->propertyCount(); ++ii) {
494             if (isPropertyRevisioned(mo, ii))
495                 m_containsRevisionedAttributes = true;
496         }
497
498         for (int ii = 0; !m_containsRevisionedAttributes && ii < mo->methodCount(); ++ii) {
499             if (mo->method(ii).revision() != 0)
500                 m_containsRevisionedAttributes = true;
501         }
502     }
503
504     m_isSetup = true;
505     lock.unlock();
506 }
507
508 void QQmlTypePrivate::initEnums() const
509 {
510     if (m_isEnumSetup) return;
511
512     init();
513
514     QWriteLocker lock(metaTypeDataLock());
515     if (m_isEnumSetup) return;
516
517     insertEnums(m_baseMetaObject);
518
519     m_isEnumSetup = true;
520 }
521
522 void QQmlTypePrivate::insertEnums(const QMetaObject *metaObject) const
523 {
524     // Add any enum values defined by 'related' classes
525     if (metaObject->d.relatedMetaObjects) {
526         const QMetaObject **related = metaObject->d.relatedMetaObjects;
527         if (related) {
528             while (*related)
529                 insertEnums(*related++);
530         }
531     }
532
533     // Add any enum values defined by this class, overwriting any inherited values
534     for (int ii = 0; ii < metaObject->enumeratorCount(); ++ii) {
535         QMetaEnum e = metaObject->enumerator(ii);
536         for (int jj = 0; jj < e.keyCount(); ++jj)
537             m_enums.insert(QString::fromUtf8(e.key(jj)), e.value(jj));
538     }
539 }
540
541 QByteArray QQmlType::typeName() const
542 {
543     if (d->m_baseMetaObject)
544         return d->m_baseMetaObject->className();
545     else
546         return QByteArray();
547 }
548
549 const QString &QQmlType::elementName() const
550 {
551     return d->m_elementName;
552 }
553
554 const QString &QQmlType::qmlTypeName() const
555 {
556     if (d->m_name.isEmpty()) {
557         if (!d->m_module.isEmpty())
558             d->m_name = static_cast<QString>(d->m_module) + QLatin1Char('/') + d->m_elementName;
559         else
560             d->m_name = d->m_elementName;
561     }
562
563     return d->m_name;
564 }
565
566 QObject *QQmlType::create() const
567 {
568     d->init();
569
570     QObject *rv = (QObject *)operator new(d->m_allocationSize);
571     d->m_newFunc(rv);
572
573     if (rv && !d->m_metaObjects.isEmpty())
574         (void)new QQmlProxyMetaObject(rv, &d->m_metaObjects);
575
576     return rv;
577 }
578
579 void QQmlType::create(QObject **out, void **memory, size_t additionalMemory) const
580 {
581     d->init();
582
583     QObject *rv = (QObject *)operator new(d->m_allocationSize + additionalMemory);
584     d->m_newFunc(rv);
585
586     if (rv && !d->m_metaObjects.isEmpty())
587         (void)new QQmlProxyMetaObject(rv, &d->m_metaObjects);
588
589     *out = rv;
590     *memory = ((char *)rv) + d->m_allocationSize;
591 }
592
593 QQmlCustomParser *QQmlType::customParser() const
594 {
595     return d->m_customParser;
596 }
597
598 QQmlType::CreateFunc QQmlType::createFunction() const
599 {
600     return d->m_newFunc;
601 }
602
603 QString QQmlType::noCreationReason() const
604 {
605     return d->m_noCreationReason;
606 }
607
608 int QQmlType::createSize() const
609 {
610     return d->m_allocationSize;
611 }
612
613 bool QQmlType::isCreatable() const
614 {
615     return d->m_newFunc != 0;
616 }
617
618 bool QQmlType::isExtendedType() const
619 {
620     d->init();
621
622     return !d->m_metaObjects.isEmpty();
623 }
624
625 bool QQmlType::isInterface() const
626 {
627     return d->m_isInterface;
628 }
629
630 int QQmlType::typeId() const
631 {
632     return d->m_typeId;
633 }
634
635 int QQmlType::qListTypeId() const
636 {
637     return d->m_listId;
638 }
639
640 const QMetaObject *QQmlType::metaObject() const
641 {
642     d->init();
643
644     if (d->m_metaObjects.isEmpty())
645         return d->m_baseMetaObject;
646     else
647         return d->m_metaObjects.first().metaObject;
648
649 }
650
651 const QMetaObject *QQmlType::baseMetaObject() const
652 {
653     return d->m_baseMetaObject;
654 }
655
656 bool QQmlType::containsRevisionedAttributes() const
657 {
658     d->init();
659
660     return d->m_containsRevisionedAttributes;
661 }
662
663 int QQmlType::metaObjectRevision() const
664 {
665     return d->m_revision;
666 }
667
668 QQmlAttachedPropertiesFunc QQmlType::attachedPropertiesFunction() const
669 {
670     return d->m_attachedPropertiesFunc;
671 }
672
673 const QMetaObject *QQmlType::attachedPropertiesType() const
674 {
675     return d->m_attachedPropertiesType;
676 }
677
678 /*
679 This is the id passed to qmlAttachedPropertiesById().  This is different from the index
680 for the case that a single class is registered under two or more names (eg. Item in 
681 Qt 4.7 and QtQuick 1.0).
682 */
683 int QQmlType::attachedPropertiesId() const
684 {
685     return d->m_attachedPropertiesId;
686 }
687
688 int QQmlType::parserStatusCast() const
689 {
690     return d->m_parserStatusCast;
691 }
692
693 int QQmlType::propertyValueSourceCast() const
694 {
695     return d->m_propertyValueSourceCast;
696 }
697
698 int QQmlType::propertyValueInterceptorCast() const
699 {
700     return d->m_propertyValueInterceptorCast;
701 }
702
703 const char *QQmlType::interfaceIId() const
704 {
705     return d->m_iid;
706 }
707
708 int QQmlType::index() const
709 {
710     return d->m_index;
711 }
712
713 int QQmlType::enumValue(const QHashedStringRef &name, bool *ok) const
714 {
715     Q_ASSERT(ok);
716     *ok = true;
717
718     d->initEnums();
719
720     int *rv = d->m_enums.value(name);
721     if (rv)
722         return *rv;
723
724     *ok = false;
725     return -1;
726 }
727
728 int QQmlType::enumValue(const QHashedCStringRef &name, bool *ok) const
729 {
730     Q_ASSERT(ok);
731     *ok = true;
732
733     d->initEnums();
734
735     int *rv = d->m_enums.value(name);
736     if (rv)
737         return *rv;
738
739     *ok = false;
740     return -1;
741 }
742
743 int QQmlType::enumValue(const QHashedV8String &name, bool *ok) const
744 {
745     Q_ASSERT(ok);
746     *ok = true;
747
748     d->initEnums();
749
750     int *rv = d->m_enums.value(name);
751     if (rv)
752         return *rv;
753
754     *ok = false;
755     return -1;
756 }
757
758 QQmlTypeModule::QQmlTypeModule()
759 : d(new QQmlTypeModulePrivate)
760 {
761 }
762
763 QQmlTypeModule::~QQmlTypeModule()
764 {
765     delete d; d = 0;
766 }
767
768 QString QQmlTypeModule::module() const
769 {
770     return d->uri.uri;
771 }
772
773 int QQmlTypeModule::majorVersion() const
774 {
775     return d->uri.majorVersion;
776 }
777
778 int QQmlTypeModule::minimumMinorVersion() const
779 {
780     return d->minMinorVersion;
781 }
782
783 int QQmlTypeModule::maximumMinorVersion() const
784 {
785     return d->maxMinorVersion;
786 }
787
788 void QQmlTypeModulePrivate::add(QQmlType *type)
789 {
790     minMinorVersion = qMin(minMinorVersion, type->minorVersion());
791     maxMinorVersion = qMax(maxMinorVersion, type->minorVersion());
792
793     QList<QQmlType *> &list = typeHash[type->elementName()];
794     for (int ii = 0; ii < list.count(); ++ii) {
795         if (list.at(ii)->minorVersion() < type->minorVersion()) {
796             list.insert(ii, type);
797             return;
798         }
799     }
800     list.append(type);
801 }
802
803 QQmlType *QQmlTypeModule::typeNoLock(const QString &name, int minor)
804 {
805     // Expected that the caller has already handled locking metaTypeDataLock
806
807     QList<QQmlType *> *types = d->typeHash.value(name);
808     if (!types) return 0;
809
810     for (int ii = 0; ii < types->count(); ++ii)
811         if (types->at(ii)->minorVersion() <= minor)
812             return types->at(ii);
813
814     return 0;
815 }
816
817 QQmlType *QQmlTypeModule::type(const QHashedStringRef &name, int minor)
818 {
819     QReadLocker lock(metaTypeDataLock());
820
821     QList<QQmlType *> *types = d->typeHash.value(name);
822     if (!types) return 0;
823
824     for (int ii = 0; ii < types->count(); ++ii)
825         if (types->at(ii)->minorVersion() <= minor)
826             return types->at(ii);
827
828     return 0;
829 }
830
831 QQmlType *QQmlTypeModule::type(const QHashedV8String &name, int minor)
832 {
833     QReadLocker lock(metaTypeDataLock());
834
835     QList<QQmlType *> *types = d->typeHash.value(name);
836     if (!types) return 0;
837
838     for (int ii = 0; ii < types->count(); ++ii)
839         if (types->at(ii)->minorVersion() <= minor)
840             return types->at(ii);
841
842     return 0;
843 }
844
845
846 QQmlTypeModuleVersion::QQmlTypeModuleVersion()
847 : m_module(0), m_minor(0)
848 {
849 }
850
851 QQmlTypeModuleVersion::QQmlTypeModuleVersion(QQmlTypeModule *module, int minor)
852 : m_module(module), m_minor(minor)
853 {
854     Q_ASSERT(m_module);
855     Q_ASSERT(m_minor >= 0);
856 }
857
858 QQmlTypeModuleVersion::QQmlTypeModuleVersion(const QQmlTypeModuleVersion &o)
859 : m_module(o.m_module), m_minor(o.m_minor)
860 {
861 }
862
863 QQmlTypeModuleVersion &QQmlTypeModuleVersion::operator=(const QQmlTypeModuleVersion &o)
864 {
865     m_module = o.m_module;
866     m_minor = o.m_minor;
867     return *this;
868 }
869
870 QQmlTypeModule *QQmlTypeModuleVersion::module() const
871 {
872     return m_module;
873 }
874
875 int QQmlTypeModuleVersion::minorVersion() const
876 {
877     return m_minor;
878 }
879
880 QQmlType *QQmlTypeModuleVersion::type(const QHashedStringRef &name) const
881 {
882     if (m_module) return m_module->type(name, m_minor);
883     else return 0;
884 }
885
886 QQmlType *QQmlTypeModuleVersion::type(const QHashedV8String &name) const
887 {
888     if (m_module) return m_module->type(name, m_minor);
889     else return 0;
890 }
891
892
893 int registerAutoParentFunction(QQmlPrivate::RegisterAutoParent &autoparent)
894 {
895     QWriteLocker lock(metaTypeDataLock());
896     QQmlMetaTypeData *data = metaTypeData();
897
898     data->parentFunctions.append(autoparent.function);
899
900     return data->parentFunctions.count() - 1;
901 }
902
903 int registerInterface(const QQmlPrivate::RegisterInterface &interface)
904 {
905     if (interface.version > 0) 
906         qFatal("qmlRegisterType(): Cannot mix incompatible QML versions.");
907
908     QWriteLocker lock(metaTypeDataLock());
909     QQmlMetaTypeData *data = metaTypeData();
910
911     int index = data->types.count();
912
913     QQmlType *type = new QQmlType(index, interface);
914
915     data->types.append(type);
916     data->idToType.insert(type->typeId(), type);
917     data->idToType.insert(type->qListTypeId(), type);
918     // XXX No insertMulti, so no multi-version interfaces?
919     if (!type->elementName().isEmpty())
920         data->nameToType.insert(type->elementName(), type);
921
922     if (data->interfaces.size() <= interface.typeId)
923         data->interfaces.resize(interface.typeId + 16);
924     if (data->lists.size() <= interface.listId)
925         data->lists.resize(interface.listId + 16);
926     data->interfaces.setBit(interface.typeId, true);
927     data->lists.setBit(interface.listId, true);
928
929     return index;
930 }
931
932 int registerType(const QQmlPrivate::RegisterType &type)
933 {
934     if (type.elementName) {
935         for (int ii = 0; type.elementName[ii]; ++ii) {
936             if (!isalnum(type.elementName[ii])) {
937                 qWarning("qmlRegisterType(): Invalid QML element name \"%s\"", type.elementName);
938                 return -1;
939             }
940         }
941     }
942
943     QWriteLocker lock(metaTypeDataLock());
944     QQmlMetaTypeData *data = metaTypeData();
945
946     QString elementName = QString::fromUtf8(type.elementName);
947
948     if (type.uri && type.elementName) {
949         QString nameSpace = moduleFromUtf8(type.uri);
950
951         if (data->singletonTypeExists(nameSpace, elementName, type.versionMajor, type.versionMinor)) {
952             qWarning("Cannot register type %s in uri %s %d.%d (a conflicting singleton type already exists)", qPrintable(elementName), qPrintable(nameSpace), type.versionMajor, type.versionMinor);
953             return -1;
954         }
955
956         if (!data->typeRegistrationNamespace.isEmpty()) {
957             // We can only install types into the registered namespace
958             if (nameSpace != data->typeRegistrationNamespace) {
959                 QString failure(QCoreApplication::translate("qmlRegisterType",
960                                                             "Cannot install element '%1' into unregistered namespace '%2'"));
961                 data->typeRegistrationFailures.append(failure.arg(elementName).arg(nameSpace));
962                 return -1;
963             }
964         } else if (data->typeRegistrationNamespace != nameSpace) {
965             // Is the target namespace protected against further registrations?
966             if (data->protectedNamespaces.contains(nameSpace)) {
967                 QString failure(QCoreApplication::translate("qmlRegisterType",
968                                                             "Cannot install element '%1' into protected namespace '%2'"));
969                 data->typeRegistrationFailures.append(failure.arg(elementName).arg(nameSpace));
970                 return -1;
971             }
972         }
973     }
974
975     int index = data->types.count();
976
977     QQmlType *dtype = new QQmlType(index, elementName, type);
978
979     data->types.append(dtype);
980     data->idToType.insert(dtype->typeId(), dtype);
981     if (dtype->qListTypeId()) data->idToType.insert(dtype->qListTypeId(), dtype);
982
983     if (!dtype->elementName().isEmpty())
984         data->nameToType.insertMulti(dtype->elementName(), dtype);
985
986     data->metaObjectToType.insertMulti(dtype->baseMetaObject(), dtype);
987
988     if (data->objects.size() <= type.typeId)
989         data->objects.resize(type.typeId + 16);
990     if (data->lists.size() <= type.listId)
991         data->lists.resize(type.listId + 16);
992     data->objects.setBit(type.typeId, true);
993     if (type.listId) data->lists.setBit(type.listId, true);
994
995     if (!dtype->module().isEmpty()) {
996         const QHashedString &mod = dtype->module();
997
998         QQmlMetaTypeData::VersionedUri versionedUri(mod, type.versionMajor);
999         QQmlTypeModule *module = data->uriToModule.value(versionedUri);
1000         if (!module) {
1001             module = new QQmlTypeModule;
1002             module->d->uri = versionedUri;
1003             data->uriToModule.insert(versionedUri, module);
1004         }
1005         module->d->add(dtype);
1006     }
1007
1008     return index;
1009 }
1010
1011 int registerSingletonType(const QQmlPrivate::RegisterSingletonType &api)
1012 {
1013     QWriteLocker lock(metaTypeDataLock());
1014
1015     QQmlMetaTypeData *data = metaTypeData();
1016     QString uri = QString::fromUtf8(api.uri);
1017     QQmlMetaType::SingletonType import;
1018     import.major = api.versionMajor;
1019     import.minor = api.versionMinor;
1020     import.script = api.scriptApi;
1021     import.qobject = api.qobjectApi;
1022     Q_ASSERT(api.typeName);
1023     import.typeName = QString::fromUtf8(api.typeName);
1024     import.instanceMetaObject = (api.qobjectApi && api.version >= 1) ? api.instanceMetaObject : 0; // BC with version 0.
1025
1026     if (data->singletonTypeExists(uri, import.typeName, import.major, import.minor)) {
1027         qWarning("Cannot register singleton type %s in uri %s %d.%d (a conflicting singleton type already exists)", qPrintable(import.typeName), qPrintable(uri), import.major, import.minor);
1028         return -1;
1029     } else if (data->typeExists(uri, import.typeName, import.major, import.minor)) {
1030         qWarning("Cannot register singleton type %s in uri %s %d.%d (a conflicting type already exists)", qPrintable(import.typeName), qPrintable(uri), import.major, import.minor);
1031         return -1;
1032     }
1033
1034     int index = data->singletonTypeCount++;
1035
1036     QQmlMetaTypeData::SingletonTypeList *apiList = data->singletonTypes.value(uri);
1037     if (!apiList) {
1038         QQmlMetaTypeData::SingletonTypeList apis;
1039         apis.singletonTypes << import;
1040         data->singletonTypes.insert(uri, apis);
1041     } else {
1042         apiList->singletonTypes << import;
1043         apiList->sorted = false;
1044     }
1045
1046     return index;
1047 }
1048
1049
1050 /*
1051 This method is "over generalized" to allow us to (potentially) register more types of things in
1052 the future without adding exported symbols.
1053 */
1054 int QQmlPrivate::qmlregister(RegistrationType type, void *data)
1055 {
1056     if (type == TypeRegistration) {
1057         return registerType(*reinterpret_cast<RegisterType *>(data));
1058     } else if (type == InterfaceRegistration) {
1059         return registerInterface(*reinterpret_cast<RegisterInterface *>(data));
1060     } else if (type == AutoParentRegistration) {
1061         return registerAutoParentFunction(*reinterpret_cast<RegisterAutoParent *>(data));
1062     } else if (type == SingletonRegistration) {
1063         return registerSingletonType(*reinterpret_cast<RegisterSingletonType *>(data));
1064     }
1065     return -1;
1066 }
1067
1068 bool QQmlMetaType::namespaceContainsRegistrations(const QString &uri)
1069 {
1070     QQmlMetaTypeData *data = metaTypeData();
1071
1072     // Has any type previously been installed to this namespace?
1073     QHashedString nameSpace(uri);
1074     foreach (const QQmlType *type, data->types)
1075         if (type->module() == nameSpace)
1076             return true;
1077
1078     return false;
1079 }
1080
1081 void QQmlMetaType::protectNamespace(const QString &uri)
1082 {
1083     QQmlMetaTypeData *data = metaTypeData();
1084
1085     data->protectedNamespaces.insert(uri);
1086 }
1087
1088 void QQmlMetaType::setTypeRegistrationNamespace(const QString &uri)
1089 {
1090     QQmlMetaTypeData *data = metaTypeData();
1091
1092     data->typeRegistrationNamespace = uri;
1093     data->typeRegistrationFailures.clear();
1094 }
1095
1096 QStringList QQmlMetaType::typeRegistrationFailures()
1097 {
1098     QQmlMetaTypeData *data = metaTypeData();
1099
1100     return data->typeRegistrationFailures;
1101 }
1102
1103 QReadWriteLock *QQmlMetaType::typeRegistrationLock()
1104 {
1105     return metaTypeDataLock();
1106 }
1107
1108 /*
1109     Returns true if a module \a uri of any version is installed.
1110 */
1111 bool QQmlMetaType::isAnyModule(const QString &uri)
1112 {
1113     QReadLocker lock(metaTypeDataLock());
1114     QQmlMetaTypeData *data = metaTypeData();
1115
1116     // first, check Types
1117     for (QQmlMetaTypeData::TypeModules::ConstIterator iter = data->uriToModule.begin();
1118          iter != data->uriToModule.end(); ++iter) {
1119         if ((*iter)->module() == uri)
1120             return true;
1121     }
1122
1123     // then, check SingletonTypes
1124     QQmlMetaTypeData::SingletonTypeList *apiList = data->singletonTypes.value(uri);
1125     if (apiList)
1126         return true;
1127
1128     return false;
1129 }
1130
1131 /*
1132     Returns true if any type or API has been registered for the given \a module with at least
1133     versionMajor.versionMinor, or if types have been registered for \a module with at most
1134     versionMajor.versionMinor.
1135
1136     So if only 4.7 and 4.9 have been registered, 4.7,4.8, and 4.9 are valid, but not 4.6 nor 4.10.
1137 */
1138 bool QQmlMetaType::isModule(const QString &module, int versionMajor, int versionMinor)
1139 {
1140     Q_ASSERT(versionMajor >= 0 && versionMinor >= 0);
1141     QReadLocker lock(metaTypeDataLock());
1142
1143     QQmlMetaTypeData *data = metaTypeData();
1144
1145     // first, check Types
1146     QQmlTypeModule *tm = 
1147         data->uriToModule.value(QQmlMetaTypeData::VersionedUri(module, versionMajor));
1148     if (tm && tm->minimumMinorVersion() <= versionMinor && tm->maximumMinorVersion() >= versionMinor)
1149         return true;
1150
1151     // then, check SingletonTypes
1152     QQmlMetaTypeData::SingletonTypeList *apiList = data->singletonTypes.value(module);
1153     if (apiList) {
1154         foreach (const QQmlMetaType::SingletonType &mApi, apiList->singletonTypes) {
1155             if (mApi.major == versionMajor && mApi.minor == versionMinor) // XXX is this correct?
1156                 return true;
1157         }
1158     }
1159
1160     return false;
1161 }
1162
1163 QQmlTypeModule *QQmlMetaType::typeModule(const QString &uri, int majorVersion)
1164 {
1165     QReadLocker lock(metaTypeDataLock());
1166     QQmlMetaTypeData *data = metaTypeData();
1167     return data->uriToModule.value(QQmlMetaTypeData::VersionedUri(uri, majorVersion));
1168 }
1169
1170 QList<QQmlPrivate::AutoParentFunction> QQmlMetaType::parentFunctions()
1171 {
1172     QReadLocker lock(metaTypeDataLock());
1173     QQmlMetaTypeData *data = metaTypeData();
1174     return data->parentFunctions;
1175 }
1176
1177 static bool operator<(const QQmlMetaType::SingletonType &lhs, const QQmlMetaType::SingletonType &rhs)
1178 {
1179     return lhs.major < rhs.major || (lhs.major == rhs.major && lhs.minor < rhs.minor);
1180 }
1181
1182 QQmlMetaType::SingletonType
1183 QQmlMetaType::singletonType(const QString &uri, int versionMajor, int versionMinor)
1184 {
1185     QReadLocker lock(metaTypeDataLock());
1186     QQmlMetaTypeData *data = metaTypeData();
1187
1188     QQmlMetaTypeData::SingletonTypeList *apiList = data->singletonTypes.value(uri);
1189     if (!apiList)
1190         return SingletonType();
1191
1192     if (apiList->sorted == false) {
1193         qSort(apiList->singletonTypes.begin(), apiList->singletonTypes.end());
1194         apiList->sorted = true;
1195     }
1196
1197     for (int ii = apiList->singletonTypes.count() - 1; ii >= 0; --ii) {
1198         const SingletonType &import = apiList->singletonTypes.at(ii);
1199         if (import.major == versionMajor && import.minor <= versionMinor)
1200             return import;
1201     }
1202
1203     return SingletonType();
1204 }
1205
1206 QHash<QString, QList<QQmlMetaType::SingletonType> > QQmlMetaType::singletonTypes()
1207 {
1208     QReadLocker lock(metaTypeDataLock());
1209     QQmlMetaTypeData *data = metaTypeData();
1210
1211     QHash<QString, QList<SingletonType> > singletonTypes;
1212     QStringHash<QQmlMetaTypeData::SingletonTypeList>::ConstIterator it = data->singletonTypes.begin();
1213     for (; it != data->singletonTypes.end(); ++it)
1214         singletonTypes[it.key()] = it.value().singletonTypes;
1215
1216     return singletonTypes;
1217 }
1218
1219 QObject *QQmlMetaType::toQObject(const QVariant &v, bool *ok)
1220 {
1221     if (!isQObject(v.userType())) {
1222         if (ok) *ok = false;
1223         return 0;
1224     }
1225
1226     if (ok) *ok = true;
1227
1228     return *(QObject **)v.constData();
1229 }
1230
1231 bool QQmlMetaType::isQObject(int userType)
1232 {
1233     if (userType == QMetaType::QObjectStar)
1234         return true;
1235
1236     QReadLocker lock(metaTypeDataLock());
1237     QQmlMetaTypeData *data = metaTypeData();
1238     return userType >= 0 && userType < data->objects.size() && data->objects.testBit(userType);
1239 }
1240
1241 /*
1242     Returns the item type for a list of type \a id.
1243  */
1244 int QQmlMetaType::listType(int id)
1245 {
1246     QReadLocker lock(metaTypeDataLock());
1247     QQmlMetaTypeData *data = metaTypeData();
1248     QQmlType *type = data->idToType.value(id);
1249     if (type && type->qListTypeId() == id)
1250         return type->typeId();
1251     else
1252         return 0;
1253 }
1254
1255 int QQmlMetaType::attachedPropertiesFuncId(const QMetaObject *mo)
1256 {
1257     QReadLocker lock(metaTypeDataLock());
1258     QQmlMetaTypeData *data = metaTypeData();
1259
1260     QQmlType *type = data->metaObjectToType.value(mo);
1261     if (type && type->attachedPropertiesFunction())
1262         return type->attachedPropertiesId();
1263     else
1264         return -1;
1265 }
1266
1267 QQmlAttachedPropertiesFunc QQmlMetaType::attachedPropertiesFuncById(int id)
1268 {
1269     if (id < 0)
1270         return 0;
1271     QReadLocker lock(metaTypeDataLock());
1272     QQmlMetaTypeData *data = metaTypeData();
1273     return data->types.at(id)->attachedPropertiesFunction();
1274 }
1275
1276 QMetaProperty QQmlMetaType::defaultProperty(const QMetaObject *metaObject)
1277 {
1278     int idx = metaObject->indexOfClassInfo("DefaultProperty");
1279     if (-1 == idx)
1280         return QMetaProperty();
1281
1282     QMetaClassInfo info = metaObject->classInfo(idx);
1283     if (!info.value())
1284         return QMetaProperty();
1285
1286     idx = metaObject->indexOfProperty(info.value());
1287     if (-1 == idx)
1288         return QMetaProperty();
1289
1290     return metaObject->property(idx);
1291 }
1292
1293 QMetaProperty QQmlMetaType::defaultProperty(QObject *obj)
1294 {
1295     if (!obj)
1296         return QMetaProperty();
1297
1298     const QMetaObject *metaObject = obj->metaObject();
1299     return defaultProperty(metaObject);
1300 }
1301
1302 QMetaMethod QQmlMetaType::defaultMethod(const QMetaObject *metaObject)
1303 {
1304     int idx = metaObject->indexOfClassInfo("DefaultMethod");
1305     if (-1 == idx)
1306         return QMetaMethod();
1307
1308     QMetaClassInfo info = metaObject->classInfo(idx);
1309     if (!info.value())
1310         return QMetaMethod();
1311
1312     idx = metaObject->indexOfMethod(info.value());
1313     if (-1 == idx)
1314         return QMetaMethod();
1315
1316     return metaObject->method(idx);
1317 }
1318
1319 QMetaMethod QQmlMetaType::defaultMethod(QObject *obj)
1320 {
1321     if (!obj)
1322         return QMetaMethod();
1323
1324     const QMetaObject *metaObject = obj->metaObject();
1325     return defaultMethod(metaObject);
1326 }
1327
1328 QQmlMetaType::TypeCategory QQmlMetaType::typeCategory(int userType)
1329 {
1330     if (userType < 0)
1331         return Unknown;
1332     if (userType == QMetaType::QObjectStar)
1333         return Object;
1334
1335     QReadLocker lock(metaTypeDataLock());
1336     QQmlMetaTypeData *data = metaTypeData();
1337     if (userType < data->objects.size() && data->objects.testBit(userType))
1338         return Object;
1339     else if (userType < data->lists.size() && data->lists.testBit(userType))
1340         return List;
1341     else
1342         return Unknown;
1343 }
1344
1345 bool QQmlMetaType::isInterface(int userType)
1346 {
1347     QReadLocker lock(metaTypeDataLock());
1348     QQmlMetaTypeData *data = metaTypeData();
1349     return userType >= 0 && userType < data->interfaces.size() && data->interfaces.testBit(userType);
1350 }
1351
1352 const char *QQmlMetaType::interfaceIId(int userType)
1353 {
1354     QReadLocker lock(metaTypeDataLock());
1355     QQmlMetaTypeData *data = metaTypeData();
1356     QQmlType *type = data->idToType.value(userType);
1357     lock.unlock();
1358     if (type && type->isInterface() && type->typeId() == userType)
1359         return type->interfaceIId();
1360     else
1361         return 0;
1362 }
1363
1364 bool QQmlMetaType::isList(int userType)
1365 {
1366     QReadLocker lock(metaTypeDataLock());
1367     QQmlMetaTypeData *data = metaTypeData();
1368     return userType >= 0 && userType < data->lists.size() && data->lists.testBit(userType);
1369 }
1370
1371 /*!
1372     A custom string convertor allows you to specify a function pointer that
1373     returns a variant of \a type. For example, if you have written your own icon
1374     class that you want to support as an object property assignable in QML:
1375
1376     \code
1377     int type = qRegisterMetaType<SuperIcon>("SuperIcon");
1378     QML::addCustomStringConvertor(type, &SuperIcon::pixmapFromString);
1379     \endcode
1380
1381     The function pointer must be of the form:
1382     \code
1383     QVariant (*StringConverter)(const QString &);
1384     \endcode
1385  */
1386 void QQmlMetaType::registerCustomStringConverter(int type, StringConverter converter)
1387 {
1388     QWriteLocker lock(metaTypeDataLock());
1389
1390     QQmlMetaTypeData *data = metaTypeData();
1391     if (data->stringConverters.contains(type))
1392         return;
1393     data->stringConverters.insert(type, converter);
1394 }
1395
1396 /*!
1397     Return the custom string converter for \a type, previously installed through
1398     registerCustomStringConverter()
1399  */
1400 QQmlMetaType::StringConverter QQmlMetaType::customStringConverter(int type)
1401 {
1402     QReadLocker lock(metaTypeDataLock());
1403
1404     QQmlMetaTypeData *data = metaTypeData();
1405     return data->stringConverters.value(type);
1406 }
1407
1408 /*!
1409     Returns the type (if any) of URI-qualified named \a qualifiedName and version specified
1410     by \a version_major and \a version_minor.
1411 */
1412 QQmlType *QQmlMetaType::qmlType(const QString &qualifiedName, int version_major, int version_minor)
1413 {
1414     int slash = qualifiedName.indexOf(QLatin1Char('/'));
1415     if (slash <= 0)
1416         return 0;
1417
1418     QHashedStringRef module(qualifiedName.constData(), slash);
1419     QHashedStringRef name(qualifiedName.constData() + slash + 1, qualifiedName.length() - slash - 1);
1420
1421     return qmlType(name, module, version_major, version_minor);
1422 }
1423
1424 /*!
1425     Returns the type (if any) of \a name in \a module and version specified
1426     by \a version_major and \a version_minor.
1427 */
1428 QQmlType *QQmlMetaType::qmlType(const QHashedStringRef &name, const QHashedStringRef &module, int version_major, int version_minor)
1429 {
1430     Q_ASSERT(version_major >= 0 && version_minor >= 0);
1431     QReadLocker lock(metaTypeDataLock());
1432     QQmlMetaTypeData *data = metaTypeData();
1433
1434     QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.find(name);
1435     while (it != data->nameToType.end() && it.key() == name) {
1436         // XXX version_major<0 just a kludge for QQmlPropertyPrivate::initProperty
1437         if (version_major < 0 || (*it)->availableInVersion(module, version_major,version_minor))
1438             return (*it);
1439         ++it;
1440     }
1441
1442     return 0;
1443 }
1444
1445 /*!
1446     Returns the type (if any) that corresponds to the \a metaObject.  Returns null if no
1447     type is registered.
1448 */
1449 QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject)
1450 {
1451     QReadLocker lock(metaTypeDataLock());
1452     QQmlMetaTypeData *data = metaTypeData();
1453
1454     return data->metaObjectToType.value(metaObject);
1455 }
1456
1457 /*!
1458     Returns the type (if any) that corresponds to the \a metaObject in version specified
1459     by \a version_major and \a version_minor in module specified by \a uri.  Returns null if no
1460     type is registered.
1461 */
1462 QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, int version_major, int version_minor)
1463 {
1464     Q_ASSERT(version_major >= 0 && version_minor >= 0);
1465     QReadLocker lock(metaTypeDataLock());
1466     QQmlMetaTypeData *data = metaTypeData();
1467
1468     QQmlMetaTypeData::MetaObjects::const_iterator it = data->metaObjectToType.find(metaObject);
1469     while (it != data->metaObjectToType.end() && it.key() == metaObject) {
1470         QQmlType *t = *it;
1471         if (version_major < 0 || t->availableInVersion(module, version_major,version_minor))
1472             return t;
1473         ++it;
1474     }
1475
1476     return 0;
1477 }
1478
1479 /*!
1480     Returns the type (if any) that corresponds to the QVariant::Type \a userType.  
1481     Returns null if no type is registered.
1482 */
1483 QQmlType *QQmlMetaType::qmlType(int userType)
1484 {
1485     QReadLocker lock(metaTypeDataLock());
1486     QQmlMetaTypeData *data = metaTypeData();
1487
1488     QQmlType *type = data->idToType.value(userType);
1489     if (type && type->typeId() == userType)
1490         return type;
1491     else
1492         return 0;
1493 }
1494
1495 /*!
1496     Returns the list of registered QML type names.
1497 */
1498 QList<QString> QQmlMetaType::qmlTypeNames()
1499 {
1500     QReadLocker lock(metaTypeDataLock());
1501     QQmlMetaTypeData *data = metaTypeData();
1502
1503     QList<QString> names;
1504     QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.begin();
1505     while (it != data->nameToType.end()) {
1506         names += (*it)->qmlTypeName();
1507         ++it;
1508     }
1509
1510     return names;
1511 }
1512
1513 /*!
1514     Returns the list of registered QML types.
1515 */
1516 QList<QQmlType*> QQmlMetaType::qmlTypes()
1517 {
1518     QReadLocker lock(metaTypeDataLock());
1519     QQmlMetaTypeData *data = metaTypeData();
1520
1521     return data->nameToType.values();
1522 }
1523
1524 int QQmlMetaType::QQuickAnchorLineMetaTypeId()
1525 {
1526     static int id = 0;
1527     if (!id) {
1528         id = QMetaType::type("QQuickAnchorLine");
1529     }
1530     return id;
1531 }
1532
1533 QQmlMetaType::CompareFunction QQmlMetaType::anchorLineCompareFunction = 0;
1534
1535 void QQmlMetaType::setQQuickAnchorLineCompareFunction(CompareFunction fun)
1536 {
1537     anchorLineCompareFunction = fun;
1538 }
1539
1540 bool QQmlMetaType::QQuickAnchorLineCompare(const void *p1, const void *p2)
1541 {
1542     Q_ASSERT(anchorLineCompareFunction != 0);
1543     return anchorLineCompareFunction(p1, p2);
1544 }
1545
1546 QT_END_NAMESPACE