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