More efficient type name cache
[profile/ivi/qtdeclarative.git] / src / declarative / qml / qdeclarativemetatype.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <QtDeclarative/qdeclarativeprivate.h>
43 #include "private/qdeclarativemetatype_p.h"
44
45 #include <private/qdeclarativeproxymetaobject_p.h>
46 #include <private/qdeclarativecustomparser_p.h>
47 #include <private/qdeclarativeguard_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 <qmetatype.h>
56 #include <qobjectdefs.h>
57 #include <qdatetime.h>
58 #include <qbytearray.h>
59 #include <qreadwritelock.h>
60 #include <qstring.h>
61 #include <qstringlist.h>
62 #include <qvector.h>
63 #include <qlocale.h>
64 #include <QtCore/qcryptographichash.h>
65 #include <QtDeclarative/qjsvalue.h>
66
67 #include <ctype.h>
68
69 #ifdef QT_BOOTSTRAPPED
70 # ifndef QT_NO_GEOM_VARIANT
71 #  define QT_NO_GEOM_VARIANT
72 # endif
73 #else
74 #  include <qbitarray.h>
75 #  include <qurl.h>
76 #  include <qvariant.h>
77 #endif
78
79 #ifndef QT_NO_GEOM_VARIANT
80 # include <qsize.h>
81 # include <qpoint.h>
82 # include <qrect.h>
83 # include <qline.h>
84 # include <qvector3d.h>
85 #endif
86 #define NS(x) QT_PREPEND_NAMESPACE(x)
87
88 QT_BEGIN_NAMESPACE
89
90 struct QDeclarativeMetaTypeData
91 {
92     QDeclarativeMetaTypeData();
93     ~QDeclarativeMetaTypeData();
94     QList<QDeclarativeType *> types;
95     typedef QHash<int, QDeclarativeType *> Ids;
96     Ids idToType;
97     typedef QHash<QByteArray, QDeclarativeType *> Names;
98     Names nameToType;
99     typedef QHash<const QMetaObject *, QDeclarativeType *> MetaObjects;
100     MetaObjects metaObjectToType;
101     typedef QHash<int, QDeclarativeMetaType::StringConverter> StringConverters;
102     StringConverters stringConverters;
103
104     struct VersionedUri {
105         VersionedUri()
106         : majorVersion(0) {}
107         VersionedUri(const QByteArray &uri, int majorVersion)
108         : uri(uri), majorVersion(majorVersion) {}
109         bool operator==(const VersionedUri &other) const {
110             return other.majorVersion == majorVersion && other.uri == uri;
111         }
112         QByteArray uri;
113         int majorVersion;
114     };
115     typedef QHash<VersionedUri, QDeclarativeTypeModule *> TypeModules;
116     TypeModules uriToModule;
117
118     struct ModuleApiList {
119         ModuleApiList() : sorted(true) {}
120         QList<QDeclarativeMetaType::ModuleApi> moduleApis;
121         bool sorted;
122     };
123     typedef QHash<QByteArray, ModuleApiList> ModuleApis;
124     ModuleApis moduleApis;
125     int moduleApiCount;
126
127     QBitArray objects;
128     QBitArray interfaces;
129     QBitArray lists;
130
131     QList<QDeclarativePrivate::AutoParentFunction> parentFunctions;
132 };
133
134 class QDeclarativeTypeModulePrivate
135 {
136 public:
137     QDeclarativeTypeModulePrivate() 
138     : minMinorVersion(INT_MAX), maxMinorVersion(0) {}
139
140     QDeclarativeMetaTypeData::VersionedUri uri;
141
142     int minMinorVersion;
143     int maxMinorVersion;
144
145     void add(QDeclarativeType *);
146
147     QStringHash<QList<QDeclarativeType *> > typeHash;
148     QList<QDeclarativeType *> types;
149 };
150
151 Q_GLOBAL_STATIC(QDeclarativeMetaTypeData, metaTypeData)
152 Q_GLOBAL_STATIC(QReadWriteLock, metaTypeDataLock)
153
154 static uint qHash(const QDeclarativeMetaTypeData::VersionedUri &v)
155 {
156     return qHash(v.uri) ^ qHash(v.majorVersion);
157 }
158
159 QDeclarativeMetaTypeData::QDeclarativeMetaTypeData()
160 : moduleApiCount(0)
161 {
162 }
163
164 QDeclarativeMetaTypeData::~QDeclarativeMetaTypeData()
165 {
166     for (int i = 0; i < types.count(); ++i)
167         delete types.at(i);
168 }
169
170 class QDeclarativeTypePrivate
171 {
172 public:
173     QDeclarativeTypePrivate();
174
175     void init() const;
176     void initEnums() const;
177
178     bool m_isInterface : 1;
179     const char *m_iid;
180     QByteArray m_module;
181     QByteArray m_name;
182     QString m_elementName;
183     int m_version_maj;
184     int m_version_min;
185     int m_typeId; int m_listId; 
186     int m_revision;
187     mutable bool m_containsRevisionedAttributes;
188     mutable QDeclarativeType *m_superType;
189
190     int m_allocationSize;
191     void (*m_newFunc)(void *);
192     QString m_noCreationReason;
193
194     const QMetaObject *m_baseMetaObject;
195     QDeclarativeAttachedPropertiesFunc m_attachedPropertiesFunc;
196     const QMetaObject *m_attachedPropertiesType;
197     int m_attachedPropertiesId;
198     int m_parserStatusCast;
199     int m_propertyValueSourceCast;
200     int m_propertyValueInterceptorCast;
201     QObject *(*m_extFunc)(QObject *);
202     const QMetaObject *m_extMetaObject;
203     int m_index;
204     QDeclarativeCustomParser *m_customParser;
205     mutable volatile bool m_isSetup:1;
206     mutable volatile bool m_isEnumSetup:1;
207     mutable bool m_haveSuperType:1;
208     mutable QList<QDeclarativeProxyMetaObject::ProxyData> m_metaObjects;
209     mutable QStringHash<int> m_enums;
210
211     static QHash<const QMetaObject *, int> m_attachedPropertyIds;
212 };
213
214 QHash<const QMetaObject *, int> QDeclarativeTypePrivate::m_attachedPropertyIds;
215
216 QDeclarativeTypePrivate::QDeclarativeTypePrivate()
217 : m_isInterface(false), m_iid(0), m_typeId(0), m_listId(0), m_revision(0), m_containsRevisionedAttributes(false),
218   m_superType(0), m_allocationSize(0), m_newFunc(0), m_baseMetaObject(0), m_attachedPropertiesFunc(0), 
219   m_attachedPropertiesType(0), m_parserStatusCast(-1), m_propertyValueSourceCast(-1), 
220   m_propertyValueInterceptorCast(-1), m_extFunc(0), m_extMetaObject(0), m_index(-1), m_customParser(0), 
221   m_isSetup(false), m_isEnumSetup(false), m_haveSuperType(false)
222 {
223 }
224
225
226 QDeclarativeType::QDeclarativeType(int index, const QDeclarativePrivate::RegisterInterface &interface)
227 : d(new QDeclarativeTypePrivate)
228 {
229     d->m_isInterface = true;
230     d->m_iid = interface.iid;
231     d->m_typeId = interface.typeId;
232     d->m_listId = interface.listId;
233     d->m_newFunc = 0;
234     d->m_index = index;
235     d->m_isSetup = true;
236     d->m_version_maj = 0;
237     d->m_version_min = 0;
238 }
239
240 QDeclarativeType::QDeclarativeType(int index, const QDeclarativePrivate::RegisterType &type)
241 : d(new QDeclarativeTypePrivate)
242 {
243     QByteArray name = type.uri;
244     if (type.uri) name += '/';
245     name += type.elementName;
246
247     d->m_module = type.uri;
248     d->m_name = name;
249     d->m_version_maj = type.versionMajor;
250     d->m_version_min = type.versionMinor;
251     if (type.version >= 1) // revisions added in version 1
252         d->m_revision = type.revision;
253     d->m_typeId = type.typeId;
254     d->m_listId = type.listId;
255     d->m_allocationSize = type.objectSize;
256     d->m_newFunc = type.create;
257     d->m_noCreationReason = type.noCreationReason;
258     d->m_baseMetaObject = type.metaObject;
259     d->m_attachedPropertiesFunc = type.attachedPropertiesFunction;
260     d->m_attachedPropertiesType = type.attachedPropertiesMetaObject;
261     if (d->m_attachedPropertiesType) {
262         QHash<const QMetaObject *, int>::Iterator iter = d->m_attachedPropertyIds.find(d->m_baseMetaObject);
263         if (iter == d->m_attachedPropertyIds.end())
264             iter = d->m_attachedPropertyIds.insert(d->m_baseMetaObject, index);
265         d->m_attachedPropertiesId = *iter;
266     } else {
267         d->m_attachedPropertiesId = -1;
268     }
269     d->m_parserStatusCast = type.parserStatusCast;
270     d->m_propertyValueSourceCast = type.valueSourceCast;
271     d->m_propertyValueInterceptorCast = type.valueInterceptorCast;
272     d->m_extFunc = type.extensionObjectCreate;
273     d->m_index = index;
274     d->m_customParser = type.customParser;
275
276     if (type.extensionMetaObject)
277         d->m_extMetaObject = type.extensionMetaObject;
278 }
279
280 QDeclarativeType::~QDeclarativeType()
281 {
282     delete d->m_customParser;
283     delete d;
284 }
285
286 QByteArray QDeclarativeType::module() const
287 {
288     return d->m_module;
289 }
290
291 int QDeclarativeType::majorVersion() const
292 {
293     return d->m_version_maj;
294 }
295
296 int QDeclarativeType::minorVersion() const
297 {
298     return d->m_version_min;
299 }
300
301 bool QDeclarativeType::availableInVersion(int vmajor, int vminor) const
302 {
303     Q_ASSERT(vmajor >= 0 && vminor >= 0);
304     return vmajor == d->m_version_maj && vminor >= d->m_version_min;
305 }
306
307 bool QDeclarativeType::availableInVersion(const QByteArray &module, int vmajor, int vminor) const
308 {
309     Q_ASSERT(vmajor >= 0 && vminor >= 0);
310     return module == d->m_module && vmajor == d->m_version_maj && vminor >= d->m_version_min;
311 }
312
313 // returns the nearest _registered_ super class
314 QDeclarativeType *QDeclarativeType::superType() const
315 {
316     if (!d->m_haveSuperType) {
317         const QMetaObject *mo = d->m_baseMetaObject->superClass();
318         while (mo && !d->m_superType) {
319             d->m_superType = QDeclarativeMetaType::qmlType(mo, d->m_module, d->m_version_maj, d->m_version_min);
320             mo = mo->superClass();
321         }
322         d->m_haveSuperType = true;
323     }
324
325     return d->m_superType;
326 }
327
328 static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo, 
329                   const QMetaObject *ignoreStart, const QMetaObject *ignoreEnd)
330 {
331     // Set classname
332     builder.setClassName(ignoreEnd->className());
333
334     // Clone Q_CLASSINFO
335     for (int ii = mo->classInfoOffset(); ii < mo->classInfoCount(); ++ii) {
336         QMetaClassInfo info = mo->classInfo(ii);
337
338         int otherIndex = ignoreEnd->indexOfClassInfo(info.name());
339         if (otherIndex >= ignoreStart->classInfoOffset() + ignoreStart->classInfoCount()) {
340             // Skip 
341         } else {
342             builder.addClassInfo(info.name(), info.value());
343         }
344     }
345
346     // Clone Q_PROPERTY
347     for (int ii = mo->propertyOffset(); ii < mo->propertyCount(); ++ii) {
348         QMetaProperty property = mo->property(ii);
349
350         int otherIndex = ignoreEnd->indexOfProperty(property.name());
351         if (otherIndex >= ignoreStart->propertyOffset() + ignoreStart->propertyCount()) {
352             builder.addProperty(QByteArray("__qml_ignore__") + property.name(), QByteArray("void"));
353             // Skip 
354         } else {
355             builder.addProperty(property);
356         }
357     }
358
359     // Clone Q_METHODS
360     for (int ii = mo->methodOffset(); ii < mo->methodCount(); ++ii) {
361         QMetaMethod method = mo->method(ii);
362
363         // More complex - need to search name
364         QByteArray name = method.signature();
365         int parenIdx = name.indexOf('(');
366         if (parenIdx != -1) name = name.left(parenIdx);
367
368
369         bool found = false;
370
371         for (int ii = ignoreStart->methodOffset() + ignoreStart->methodCount(); 
372              !found && ii < ignoreEnd->methodOffset() + ignoreEnd->methodCount();
373              ++ii) {
374
375             QMetaMethod other = ignoreEnd->method(ii);
376             QByteArray othername = other.signature();
377             int parenIdx = othername.indexOf('(');
378             if (parenIdx != -1) othername = othername.left(parenIdx);
379
380             found = name == othername;
381         }
382
383         QMetaMethodBuilder m = builder.addMethod(method);
384         if (found) // SKIP
385             m.setAccess(QMetaMethod::Private);
386     }
387
388     // Clone Q_ENUMS
389     for (int ii = mo->enumeratorOffset(); ii < mo->enumeratorCount(); ++ii) {
390         QMetaEnum enumerator = mo->enumerator(ii);
391
392         int otherIndex = ignoreEnd->indexOfEnumerator(enumerator.name());
393         if (otherIndex >= ignoreStart->enumeratorOffset() + ignoreStart->enumeratorCount()) {
394             // Skip 
395         } else {
396             builder.addEnumerator(enumerator);
397         }
398     }
399 }
400
401 void QDeclarativeTypePrivate::init() const
402 {
403     if (m_isSetup) return;
404
405     QWriteLocker lock(metaTypeDataLock());
406     if (m_isSetup)
407         return;
408
409     // Setup extended meta object
410     // XXX - very inefficient
411     const QMetaObject *mo = m_baseMetaObject;
412     if (m_extFunc) {
413         QMetaObject *mmo = new QMetaObject;
414         *mmo = *m_extMetaObject;
415         mmo->d.superdata = mo;
416         QDeclarativeProxyMetaObject::ProxyData data = { mmo, m_extFunc, 0, 0 };
417         m_metaObjects << data;
418     }
419
420     mo = mo->d.superdata;
421     while(mo) {
422         QDeclarativeType *t = metaTypeData()->metaObjectToType.value(mo);
423         if (t) {
424             if (t->d->m_extFunc) {
425                 QMetaObjectBuilder builder;
426                 clone(builder, t->d->m_extMetaObject, t->d->m_baseMetaObject, m_baseMetaObject);
427                 QMetaObject *mmo = builder.toMetaObject();
428                 mmo->d.superdata = m_baseMetaObject;
429                 if (!m_metaObjects.isEmpty())
430                     m_metaObjects.last().metaObject->d.superdata = mmo;
431                 QDeclarativeProxyMetaObject::ProxyData data = { mmo, t->d->m_extFunc, 0, 0 };
432                 m_metaObjects << data;
433             }
434         }
435         mo = mo->d.superdata;
436     }
437
438     for (int ii = 0; ii < m_metaObjects.count(); ++ii) {
439         m_metaObjects[ii].propertyOffset =
440             m_metaObjects.at(ii).metaObject->propertyOffset();
441         m_metaObjects[ii].methodOffset =
442             m_metaObjects.at(ii).metaObject->methodOffset();
443     }
444     
445     // Check for revisioned details
446     {
447         const QMetaObject *mo = 0;
448         if (m_metaObjects.isEmpty())
449             mo = m_baseMetaObject;
450         else
451             mo = m_metaObjects.first().metaObject;
452
453         for (int ii = 0; !m_containsRevisionedAttributes && ii < mo->propertyCount(); ++ii) {
454             if (mo->property(ii).revision() != 0)
455                 m_containsRevisionedAttributes = true;
456         }
457
458         for (int ii = 0; !m_containsRevisionedAttributes && ii < mo->methodCount(); ++ii) {
459             if (mo->method(ii).revision() != 0)
460                 m_containsRevisionedAttributes = true;
461         }
462     }
463
464     m_isSetup = true;
465     lock.unlock();
466 }
467
468 void QDeclarativeTypePrivate::initEnums() const
469 {
470     if (m_isEnumSetup) return;
471
472     init();
473
474     QWriteLocker lock(metaTypeDataLock());
475     if (m_isEnumSetup) return;
476
477     const QMetaObject *metaObject = m_baseMetaObject;
478     for (int ii = 0; ii < metaObject->enumeratorCount(); ++ii) {
479
480         QMetaEnum e = metaObject->enumerator(ii);
481
482         for (int jj = 0; jj < e.keyCount(); ++jj) 
483             m_enums.insert(QString::fromUtf8(e.key(jj)), e.value(jj));
484     }
485
486     m_isEnumSetup = true;
487 }
488
489 QByteArray QDeclarativeType::typeName() const
490 {
491     if (d->m_baseMetaObject)
492         return d->m_baseMetaObject->className();
493     else
494         return QByteArray();
495 }
496
497 const QString &QDeclarativeType::elementName() const
498 {
499     if (d->m_elementName.isEmpty()) {
500         QByteArray n = qmlTypeName();
501         int idx = n.lastIndexOf('/');
502         d->m_elementName = QString::fromUtf8(n.mid(idx + 1));
503     }
504     return d->m_elementName;
505 }
506
507 QByteArray QDeclarativeType::qmlTypeName() const
508 {
509     return d->m_name;
510 }
511
512 QObject *QDeclarativeType::create() const
513 {
514     d->init();
515
516     QObject *rv = (QObject *)operator new(d->m_allocationSize);
517     d->m_newFunc(rv);
518
519     if (rv && !d->m_metaObjects.isEmpty())
520         (void *)new QDeclarativeProxyMetaObject(rv, &d->m_metaObjects);
521
522     return rv;
523 }
524
525 void QDeclarativeType::create(QObject **out, void **memory, size_t additionalMemory) const
526 {
527     d->init();
528
529     QObject *rv = (QObject *)operator new(d->m_allocationSize + additionalMemory);
530     d->m_newFunc(rv);
531
532     if (rv && !d->m_metaObjects.isEmpty())
533         (void *)new QDeclarativeProxyMetaObject(rv, &d->m_metaObjects);
534
535     *out = rv;
536     *memory = ((char *)rv) + d->m_allocationSize;
537 }
538
539 QDeclarativeCustomParser *QDeclarativeType::customParser() const
540 {
541     return d->m_customParser;
542 }
543
544 QDeclarativeType::CreateFunc QDeclarativeType::createFunction() const
545 {
546     return d->m_newFunc;
547 }
548
549 QString QDeclarativeType::noCreationReason() const
550 {
551     return d->m_noCreationReason;
552 }
553
554 int QDeclarativeType::createSize() const
555 {
556     return d->m_allocationSize;
557 }
558
559 bool QDeclarativeType::isCreatable() const
560 {
561     return d->m_newFunc != 0;
562 }
563
564 bool QDeclarativeType::isExtendedType() const
565 {
566     d->init();
567
568     return !d->m_metaObjects.isEmpty();
569 }
570
571 bool QDeclarativeType::isInterface() const
572 {
573     return d->m_isInterface;
574 }
575
576 int QDeclarativeType::typeId() const
577 {
578     return d->m_typeId;
579 }
580
581 int QDeclarativeType::qListTypeId() const
582 {
583     return d->m_listId;
584 }
585
586 const QMetaObject *QDeclarativeType::metaObject() const
587 {
588     d->init();
589
590     if (d->m_metaObjects.isEmpty())
591         return d->m_baseMetaObject;
592     else
593         return d->m_metaObjects.first().metaObject;
594
595 }
596
597 const QMetaObject *QDeclarativeType::baseMetaObject() const
598 {
599     return d->m_baseMetaObject;
600 }
601
602 bool QDeclarativeType::containsRevisionedAttributes() const
603 {
604     d->init();
605
606     return d->m_containsRevisionedAttributes;
607 }
608
609 int QDeclarativeType::metaObjectRevision() const
610 {
611     return d->m_revision;
612 }
613
614 QDeclarativeAttachedPropertiesFunc QDeclarativeType::attachedPropertiesFunction() const
615 {
616     return d->m_attachedPropertiesFunc;
617 }
618
619 const QMetaObject *QDeclarativeType::attachedPropertiesType() const
620 {
621     return d->m_attachedPropertiesType;
622 }
623
624 /*
625 This is the id passed to qmlAttachedPropertiesById().  This is different from the index
626 for the case that a single class is registered under two or more names (eg. Item in 
627 Qt 4.7 and QtQuick 1.0).
628 */
629 int QDeclarativeType::attachedPropertiesId() const
630 {
631     return d->m_attachedPropertiesId;
632 }
633
634 int QDeclarativeType::parserStatusCast() const
635 {
636     return d->m_parserStatusCast;
637 }
638
639 int QDeclarativeType::propertyValueSourceCast() const
640 {
641     return d->m_propertyValueSourceCast;
642 }
643
644 int QDeclarativeType::propertyValueInterceptorCast() const
645 {
646     return d->m_propertyValueInterceptorCast;
647 }
648
649 const char *QDeclarativeType::interfaceIId() const
650 {
651     return d->m_iid;
652 }
653
654 int QDeclarativeType::index() const
655 {
656     return d->m_index;
657 }
658
659 int QDeclarativeType::enumValue(const QHashedStringRef &name) const
660 {
661     d->initEnums();
662
663     int *rv = d->m_enums.value(name);
664     return rv?*rv:-1;
665 }
666
667 int QDeclarativeType::enumValue(const QHashedV8String &name) const
668 {
669     d->initEnums();
670
671     int *rv = d->m_enums.value(name);
672     return rv?*rv:-1;
673 }
674
675 QDeclarativeTypeModule::QDeclarativeTypeModule()
676 : d(new QDeclarativeTypeModulePrivate)
677 {
678 }
679
680 QDeclarativeTypeModule::~QDeclarativeTypeModule()
681 {
682     delete d; d = 0;
683 }
684
685 QByteArray QDeclarativeTypeModule::module() const
686 {
687     return d->uri.uri;
688 }
689
690 int QDeclarativeTypeModule::majorVersion() const
691 {
692     return d->uri.majorVersion;
693 }
694
695 int QDeclarativeTypeModule::minimumMinorVersion() const
696 {
697     return d->minMinorVersion;
698 }
699
700 int QDeclarativeTypeModule::maximumMinorVersion() const
701 {
702     return d->maxMinorVersion;
703 }
704
705 void QDeclarativeTypeModulePrivate::add(QDeclarativeType *type)
706 {
707     types << type;
708
709     minMinorVersion = qMin(minMinorVersion, type->minorVersion());
710     maxMinorVersion = qMax(maxMinorVersion, type->minorVersion());
711
712     QList<QDeclarativeType *> &list = typeHash[type->elementName()];
713     for (int ii = 0; ii < list.count(); ++ii) {
714         if (list.at(ii)->minorVersion() < type->minorVersion()) {
715             list.insert(ii, type);
716             return;
717         }
718     }
719     list.append(type);
720 }
721
722 QList<QDeclarativeType *> QDeclarativeTypeModule::types()
723 {
724     QList<QDeclarativeType *> rv;
725     QReadLocker lock(metaTypeDataLock());
726     rv = d->types;
727     return rv;
728 }
729
730 QList<QDeclarativeType *> QDeclarativeTypeModule::type(const QString &name)
731 {
732     QReadLocker lock(metaTypeDataLock());
733     QList<QDeclarativeType *> rv;
734     for (int ii = 0; ii < d->types.count(); ++ii) {
735         if (d->types.at(ii)->elementName() == name)
736             rv << d->types.at(ii);
737     }
738     return rv;
739 }
740
741 QDeclarativeType *QDeclarativeTypeModule::type(const QHashedStringRef &name, int minor)
742 {
743     QReadLocker lock(metaTypeDataLock());
744
745     QList<QDeclarativeType *> *types = d->typeHash.value(name);
746     if (!types) return 0;
747
748     for (int ii = 0; ii < types->count(); ++ii)
749         if (types->at(ii)->minorVersion() <= minor)
750             return types->at(ii);
751
752     return 0;
753 }
754
755 QDeclarativeType *QDeclarativeTypeModule::type(const QHashedV8String &name, int minor)
756 {
757     QReadLocker lock(metaTypeDataLock());
758
759     QList<QDeclarativeType *> *types = d->typeHash.value(name);
760     if (!types) return 0;
761
762     for (int ii = 0; ii < types->count(); ++ii)
763         if (types->at(ii)->minorVersion() <= minor)
764             return types->at(ii);
765
766     return 0;
767 }
768
769
770 QDeclarativeTypeModuleVersion::QDeclarativeTypeModuleVersion()
771 : m_module(0), m_minor(0)
772 {
773 }
774
775 QDeclarativeTypeModuleVersion::QDeclarativeTypeModuleVersion(QDeclarativeTypeModule *module, int minor)
776 : m_module(module), m_minor(minor)
777 {
778     Q_ASSERT(m_module);
779     Q_ASSERT(m_minor >= 0);
780 }
781
782 QDeclarativeTypeModuleVersion::QDeclarativeTypeModuleVersion(const QDeclarativeTypeModuleVersion &o)
783 : m_module(o.m_module), m_minor(o.m_minor)
784 {
785 }
786
787 QDeclarativeTypeModuleVersion &QDeclarativeTypeModuleVersion::operator=(const QDeclarativeTypeModuleVersion &o)
788 {
789     m_module = o.m_module;
790     m_minor = o.m_minor;
791     return *this;
792 }
793
794 QDeclarativeTypeModule *QDeclarativeTypeModuleVersion::module() const
795 {
796     return m_module;
797 }
798
799 int QDeclarativeTypeModuleVersion::minorVersion() const
800 {
801     return m_minor;
802 }
803
804 QDeclarativeType *QDeclarativeTypeModuleVersion::type(const QHashedStringRef &name) const
805 {
806     if (m_module) return m_module->type(name, m_minor);
807     else return 0;
808 }
809
810 QDeclarativeType *QDeclarativeTypeModuleVersion::type(const QHashedV8String &name) const
811 {
812     if (m_module) return m_module->type(name, m_minor);
813     else return 0;
814 }
815
816
817 int registerAutoParentFunction(QDeclarativePrivate::RegisterAutoParent &autoparent)
818 {
819     QWriteLocker lock(metaTypeDataLock());
820     QDeclarativeMetaTypeData *data = metaTypeData();
821
822     data->parentFunctions.append(autoparent.function);
823
824     return data->parentFunctions.count() - 1;
825 }
826
827 int registerInterface(const QDeclarativePrivate::RegisterInterface &interface)
828 {
829     if (interface.version > 0) 
830         qFatal("qmlRegisterType(): Cannot mix incompatible QML versions.");
831
832     QWriteLocker lock(metaTypeDataLock());
833     QDeclarativeMetaTypeData *data = metaTypeData();
834
835     int index = data->types.count();
836
837     QDeclarativeType *type = new QDeclarativeType(index, interface);
838
839     data->types.append(type);
840     data->idToType.insert(type->typeId(), type);
841     data->idToType.insert(type->qListTypeId(), type);
842     // XXX No insertMulti, so no multi-version interfaces?
843     if (!type->qmlTypeName().isEmpty())
844         data->nameToType.insert(type->qmlTypeName(), type);
845
846     if (data->interfaces.size() <= interface.typeId)
847         data->interfaces.resize(interface.typeId + 16);
848     if (data->lists.size() <= interface.listId)
849         data->lists.resize(interface.listId + 16);
850     data->interfaces.setBit(interface.typeId, true);
851     data->lists.setBit(interface.listId, true);
852
853     return index;
854 }
855
856 int registerType(const QDeclarativePrivate::RegisterType &type)
857 {
858     if (type.elementName) {
859         for (int ii = 0; type.elementName[ii]; ++ii) {
860             if (!isalnum(type.elementName[ii])) {
861                 qWarning("qmlRegisterType(): Invalid QML element name \"%s\"", type.elementName);
862                 return -1;
863             }
864         }
865     }
866
867     QWriteLocker lock(metaTypeDataLock());
868     QDeclarativeMetaTypeData *data = metaTypeData();
869     int index = data->types.count();
870
871     QDeclarativeType *dtype = new QDeclarativeType(index, type);
872
873     data->types.append(dtype);
874     data->idToType.insert(dtype->typeId(), dtype);
875     if (dtype->qListTypeId()) data->idToType.insert(dtype->qListTypeId(), dtype);
876
877     if (!dtype->qmlTypeName().isEmpty())
878         data->nameToType.insertMulti(dtype->qmlTypeName(), dtype);
879
880     data->metaObjectToType.insertMulti(dtype->baseMetaObject(), dtype);
881
882     if (data->objects.size() <= type.typeId)
883         data->objects.resize(type.typeId + 16);
884     if (data->lists.size() <= type.listId)
885         data->lists.resize(type.listId + 16);
886     data->objects.setBit(type.typeId, true);
887     if (type.listId) data->lists.setBit(type.listId, true);
888
889     if (type.uri) {
890         QByteArray mod(type.uri);
891
892         QDeclarativeMetaTypeData::VersionedUri versionedUri(mod, type.versionMajor);
893         QDeclarativeTypeModule *module = data->uriToModule.value(versionedUri);
894         if (!module) {
895             module = new QDeclarativeTypeModule;
896             module->d->uri = versionedUri;
897             data->uriToModule.insert(versionedUri, module);
898         }
899         module->d->add(dtype);
900     }
901
902     return index;
903 }
904
905 int registerModuleApi(const QDeclarativePrivate::RegisterModuleApi &api)
906 {
907     QWriteLocker lock(metaTypeDataLock());
908
909     QDeclarativeMetaTypeData *data = metaTypeData();
910     QByteArray uri(api.uri);
911     QDeclarativeMetaType::ModuleApi import;
912     import.major = api.versionMajor;
913     import.minor = api.versionMinor;
914     import.script = api.scriptApi;
915     import.qobject = api.qobjectApi;
916
917     int index = data->moduleApiCount++;
918
919     QDeclarativeMetaTypeData::ModuleApis::Iterator iter = data->moduleApis.find(uri);
920     if (iter == data->moduleApis.end()) {
921         QDeclarativeMetaTypeData::ModuleApiList apis;
922         apis.moduleApis << import;
923         data->moduleApis.insert(uri, apis);
924     } else {
925         iter->moduleApis << import;
926         iter->sorted = false;
927     }
928
929     return index;
930 }
931
932
933 /*
934 This method is "over generalized" to allow us to (potentially) register more types of things in
935 the future without adding exported symbols.
936 */
937 int QDeclarativePrivate::qmlregister(RegistrationType type, void *data)
938 {
939     if (type == TypeRegistration) {
940         return registerType(*reinterpret_cast<RegisterType *>(data));
941     } else if (type == InterfaceRegistration) {
942         return registerInterface(*reinterpret_cast<RegisterInterface *>(data));
943     } else if (type == AutoParentRegistration) {
944         return registerAutoParentFunction(*reinterpret_cast<RegisterAutoParent *>(data));
945     } else if (type == ModuleApiRegistration) {
946         return registerModuleApi(*reinterpret_cast<RegisterModuleApi *>(data));
947     }
948     return -1;
949 }
950
951 bool QDeclarativeMetaType::isAnyModule(const QByteArray &module)
952 {
953     QDeclarativeMetaTypeData *data = metaTypeData();
954
955     QDeclarativeMetaTypeData::ModuleInfoHash::Iterator it = data->modules.begin();
956     while (it != data->modules.end()) {
957         if (it.key().first == module)
958             return true;
959         ++it;
960     }
961
962     return false;
963 }
964
965 /*
966     Returns true if a module \a uri of any version is installed.
967 */
968 bool QDeclarativeMetaType::isAnyModule(const QByteArray &uri)
969 {
970     QReadLocker lock(metaTypeDataLock());
971     QDeclarativeMetaTypeData *data = metaTypeData();
972
973     for (QDeclarativeMetaTypeData::TypeModules::ConstIterator iter = data->uriToModule.begin();
974          iter != data->uriToModule.end(); ++iter) {
975         if ((*iter)->module() == uri)
976             return true;
977     }
978
979     return false;
980 }
981
982 /*
983     Returns true if any type or API has been registered for the given \a module with at least
984     versionMajor.versionMinor, or if types have been registered for \a module with at most
985     versionMajor.versionMinor.
986
987     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.
988 */
989 bool QDeclarativeMetaType::isModule(const QByteArray &module, int versionMajor, int versionMinor)
990 {
991     Q_ASSERT(versionMajor >= 0 && versionMinor >= 0);
992     QReadLocker lock(metaTypeDataLock());
993
994     QDeclarativeMetaTypeData *data = metaTypeData();
995
996     // first, check Types
997     QDeclarativeTypeModule *tm = 
998         data->uriToModule.value(QDeclarativeMetaTypeData::VersionedUri(module, versionMajor));
999     if (tm && tm->minimumMinorVersion() <= versionMinor && tm->maximumMinorVersion() >= versionMinor)
1000         return true;
1001
1002     // then, check ModuleApis
1003     foreach (const QDeclarativeMetaType::ModuleApi &mApi, data->moduleApis.value(module).moduleApis) {
1004         if (mApi.major == versionMajor && mApi.minor == versionMinor) // XXX is this correct?
1005             return true;
1006     }
1007
1008     return false;
1009 }
1010
1011 QDeclarativeTypeModule *QDeclarativeMetaType::typeModule(const QByteArray &uri, int majorVersion)
1012 {
1013     QReadLocker lock(metaTypeDataLock());
1014     QDeclarativeMetaTypeData *data = metaTypeData();
1015     return data->uriToModule.value(QDeclarativeMetaTypeData::VersionedUri(uri, majorVersion));
1016 }
1017
1018 QList<QDeclarativePrivate::AutoParentFunction> QDeclarativeMetaType::parentFunctions()
1019 {
1020     QReadLocker lock(metaTypeDataLock());
1021     QDeclarativeMetaTypeData *data = metaTypeData();
1022     return data->parentFunctions;
1023 }
1024
1025 static bool operator<(const QDeclarativeMetaType::ModuleApi &lhs, const QDeclarativeMetaType::ModuleApi &rhs)
1026 {
1027     return lhs.major < rhs.major || (lhs.major == rhs.major && lhs.minor < rhs.minor);
1028 }
1029
1030 QDeclarativeMetaType::ModuleApi
1031 QDeclarativeMetaType::moduleApi(const QByteArray &uri, int versionMajor, int versionMinor)
1032 {
1033     QReadLocker lock(metaTypeDataLock());
1034     QDeclarativeMetaTypeData *data = metaTypeData();
1035
1036     QDeclarativeMetaTypeData::ModuleApis::Iterator iter = data->moduleApis.find(uri);
1037     if (iter == data->moduleApis.end())
1038         return ModuleApi();
1039
1040     if (iter->sorted == false) {
1041         qSort(iter->moduleApis.begin(), iter->moduleApis.end());
1042         iter->sorted = true;
1043     }
1044
1045     for (int ii = iter->moduleApis.count() - 1; ii >= 0; --ii) {
1046         const ModuleApi &import = iter->moduleApis.at(ii);
1047         if (import.major == versionMajor && import.minor <= versionMinor)
1048             return import;
1049     }
1050
1051     return ModuleApi();
1052 }
1053
1054 QObject *QDeclarativeMetaType::toQObject(const QVariant &v, bool *ok)
1055 {
1056     if (!isQObject(v.userType())) {
1057         if (ok) *ok = false;
1058         return 0;
1059     }
1060
1061     if (ok) *ok = true;
1062
1063     return *(QObject **)v.constData();
1064 }
1065
1066 bool QDeclarativeMetaType::isQObject(int userType)
1067 {
1068     if (userType == QMetaType::QObjectStar)
1069         return true;
1070
1071     QReadLocker lock(metaTypeDataLock());
1072     QDeclarativeMetaTypeData *data = metaTypeData();
1073     return userType >= 0 && userType < data->objects.size() && data->objects.testBit(userType);
1074 }
1075
1076 /*
1077     Returns the item type for a list of type \a id.
1078  */
1079 int QDeclarativeMetaType::listType(int id)
1080 {
1081     QReadLocker lock(metaTypeDataLock());
1082     QDeclarativeMetaTypeData *data = metaTypeData();
1083     QDeclarativeType *type = data->idToType.value(id);
1084     if (type && type->qListTypeId() == id)
1085         return type->typeId();
1086     else
1087         return 0;
1088 }
1089
1090 int QDeclarativeMetaType::attachedPropertiesFuncId(const QMetaObject *mo)
1091 {
1092     QReadLocker lock(metaTypeDataLock());
1093     QDeclarativeMetaTypeData *data = metaTypeData();
1094
1095     QDeclarativeType *type = data->metaObjectToType.value(mo);
1096     if (type && type->attachedPropertiesFunction())
1097         return type->attachedPropertiesId();
1098     else
1099         return -1;
1100 }
1101
1102 QDeclarativeAttachedPropertiesFunc QDeclarativeMetaType::attachedPropertiesFuncById(int id)
1103 {
1104     if (id < 0)
1105         return 0;
1106     QReadLocker lock(metaTypeDataLock());
1107     QDeclarativeMetaTypeData *data = metaTypeData();
1108     return data->types.at(id)->attachedPropertiesFunction();
1109 }
1110
1111 QMetaProperty QDeclarativeMetaType::defaultProperty(const QMetaObject *metaObject)
1112 {
1113     int idx = metaObject->indexOfClassInfo("DefaultProperty");
1114     if (-1 == idx)
1115         return QMetaProperty();
1116
1117     QMetaClassInfo info = metaObject->classInfo(idx);
1118     if (!info.value())
1119         return QMetaProperty();
1120
1121     idx = metaObject->indexOfProperty(info.value());
1122     if (-1 == idx)
1123         return QMetaProperty();
1124
1125     return metaObject->property(idx);
1126 }
1127
1128 QMetaProperty QDeclarativeMetaType::defaultProperty(QObject *obj)
1129 {
1130     if (!obj)
1131         return QMetaProperty();
1132
1133     const QMetaObject *metaObject = obj->metaObject();
1134     return defaultProperty(metaObject);
1135 }
1136
1137 QMetaMethod QDeclarativeMetaType::defaultMethod(const QMetaObject *metaObject)
1138 {
1139     int idx = metaObject->indexOfClassInfo("DefaultMethod");
1140     if (-1 == idx)
1141         return QMetaMethod();
1142
1143     QMetaClassInfo info = metaObject->classInfo(idx);
1144     if (!info.value())
1145         return QMetaMethod();
1146
1147     idx = metaObject->indexOfMethod(info.value());
1148     if (-1 == idx)
1149         return QMetaMethod();
1150
1151     return metaObject->method(idx);
1152 }
1153
1154 QMetaMethod QDeclarativeMetaType::defaultMethod(QObject *obj)
1155 {
1156     if (!obj)
1157         return QMetaMethod();
1158
1159     const QMetaObject *metaObject = obj->metaObject();
1160     return defaultMethod(metaObject);
1161 }
1162
1163 QDeclarativeMetaType::TypeCategory QDeclarativeMetaType::typeCategory(int userType)
1164 {
1165     if (userType < 0)
1166         return Unknown;
1167     if (userType == QMetaType::QObjectStar)
1168         return Object;
1169
1170     QReadLocker lock(metaTypeDataLock());
1171     QDeclarativeMetaTypeData *data = metaTypeData();
1172     if (userType < data->objects.size() && data->objects.testBit(userType))
1173         return Object;
1174     else if (userType < data->lists.size() && data->lists.testBit(userType))
1175         return List;
1176     else
1177         return Unknown;
1178 }
1179
1180 bool QDeclarativeMetaType::isInterface(int userType)
1181 {
1182     QReadLocker lock(metaTypeDataLock());
1183     QDeclarativeMetaTypeData *data = metaTypeData();
1184     return userType >= 0 && userType < data->interfaces.size() && data->interfaces.testBit(userType);
1185 }
1186
1187 const char *QDeclarativeMetaType::interfaceIId(int userType)
1188 {
1189     QReadLocker lock(metaTypeDataLock());
1190     QDeclarativeMetaTypeData *data = metaTypeData();
1191     QDeclarativeType *type = data->idToType.value(userType);
1192     lock.unlock();
1193     if (type && type->isInterface() && type->typeId() == userType)
1194         return type->interfaceIId();
1195     else
1196         return 0;
1197 }
1198
1199 bool QDeclarativeMetaType::isList(int userType)
1200 {
1201     QReadLocker lock(metaTypeDataLock());
1202     QDeclarativeMetaTypeData *data = metaTypeData();
1203     return userType >= 0 && userType < data->lists.size() && data->lists.testBit(userType);
1204 }
1205
1206 /*!
1207     A custom string convertor allows you to specify a function pointer that
1208     returns a variant of \a type. For example, if you have written your own icon
1209     class that you want to support as an object property assignable in QML:
1210
1211     \code
1212     int type = qRegisterMetaType<SuperIcon>("SuperIcon");
1213     QML::addCustomStringConvertor(type, &SuperIcon::pixmapFromString);
1214     \endcode
1215
1216     The function pointer must be of the form:
1217     \code
1218     QVariant (*StringConverter)(const QString &);
1219     \endcode
1220  */
1221 void QDeclarativeMetaType::registerCustomStringConverter(int type, StringConverter converter)
1222 {
1223     QWriteLocker lock(metaTypeDataLock());
1224
1225     QDeclarativeMetaTypeData *data = metaTypeData();
1226     if (data->stringConverters.contains(type))
1227         return;
1228     data->stringConverters.insert(type, converter);
1229 }
1230
1231 /*!
1232     Return the custom string converter for \a type, previously installed through
1233     registerCustomStringConverter()
1234  */
1235 QDeclarativeMetaType::StringConverter QDeclarativeMetaType::customStringConverter(int type)
1236 {
1237     QReadLocker lock(metaTypeDataLock());
1238
1239     QDeclarativeMetaTypeData *data = metaTypeData();
1240     return data->stringConverters.value(type);
1241 }
1242
1243 /*!
1244     Returns the type (if any) of URI-qualified named \a name in version specified
1245     by \a version_major and \a version_minor.
1246 */
1247 QDeclarativeType *QDeclarativeMetaType::qmlType(const QByteArray &name, int version_major, int version_minor)
1248 {
1249     Q_ASSERT(version_major >= 0 && version_minor >= 0);
1250     QReadLocker lock(metaTypeDataLock());
1251     QDeclarativeMetaTypeData *data = metaTypeData();
1252
1253     QList<QDeclarativeType*> types = data->nameToType.values(name);
1254     foreach (QDeclarativeType *t, types) {
1255         // XXX version_major<0 just a kludge for QDeclarativePropertyPrivate::initProperty
1256         if (version_major<0 || t->availableInVersion(version_major,version_minor))
1257             return t;
1258     }
1259     return 0;
1260 }
1261
1262 /*!
1263     Returns the type (if any) that corresponds to the \a metaObject.  Returns null if no
1264     type is registered.
1265 */
1266 QDeclarativeType *QDeclarativeMetaType::qmlType(const QMetaObject *metaObject)
1267 {
1268     QReadLocker lock(metaTypeDataLock());
1269     QDeclarativeMetaTypeData *data = metaTypeData();
1270
1271     return data->metaObjectToType.value(metaObject);
1272 }
1273
1274 /*!
1275     Returns the type (if any) that corresponds to the \a metaObject in version specified
1276     by \a version_major and \a version_minor in module specified by \a uri.  Returns null if no
1277     type is registered.
1278 */
1279 QDeclarativeType *QDeclarativeMetaType::qmlType(const QMetaObject *metaObject, const QByteArray &module, int version_major, int version_minor)
1280 {
1281     Q_ASSERT(version_major >= 0 && version_minor >= 0);
1282     QReadLocker lock(metaTypeDataLock());
1283     QDeclarativeMetaTypeData *data = metaTypeData();
1284
1285     QDeclarativeMetaTypeData::MetaObjects::const_iterator it = data->metaObjectToType.find(metaObject);
1286     while (it != data->metaObjectToType.end() && it.key() == metaObject) {
1287         QDeclarativeType *t = *it;
1288         if (version_major < 0 || t->availableInVersion(module, version_major,version_minor))
1289             return t;
1290         ++it;
1291     }
1292
1293     return 0;
1294 }
1295
1296 /*!
1297     Returns the type (if any) that corresponds to the QVariant::Type \a userType.  
1298     Returns null if no type is registered.
1299 */
1300 QDeclarativeType *QDeclarativeMetaType::qmlType(int userType)
1301 {
1302     QReadLocker lock(metaTypeDataLock());
1303     QDeclarativeMetaTypeData *data = metaTypeData();
1304
1305     QDeclarativeType *type = data->idToType.value(userType);
1306     if (type && type->typeId() == userType)
1307         return type;
1308     else
1309         return 0;
1310 }
1311
1312 /*!
1313     Returns the list of registered QML type names.
1314 */
1315 QList<QByteArray> QDeclarativeMetaType::qmlTypeNames()
1316 {
1317     QReadLocker lock(metaTypeDataLock());
1318     QDeclarativeMetaTypeData *data = metaTypeData();
1319
1320     return data->nameToType.keys();
1321 }
1322
1323 /*!
1324     Returns the list of registered QML types.
1325 */
1326 QList<QDeclarativeType*> QDeclarativeMetaType::qmlTypes()
1327 {
1328     QReadLocker lock(metaTypeDataLock());
1329     QDeclarativeMetaTypeData *data = metaTypeData();
1330
1331     return data->nameToType.values();
1332 }
1333
1334 QT_END_NAMESPACE
1335
1336 #include <QtGui/qfont.h>
1337 #include <QtGui/qpixmap.h>
1338 #include <QtGui/qbrush.h>
1339 #include <QtGui/qcolor.h>
1340 #include <QtGui/qpalette.h>
1341 #include <QtGui/qicon.h>
1342 #include <QtGui/qimage.h>
1343 #include <QtGui/qpolygon.h>
1344 #include <QtGui/qregion.h>
1345 #include <QtGui/qbitmap.h>
1346 #include <QtGui/qcursor.h>
1347 #include <QtGui/qsizepolicy.h>
1348 #include <QtGui/qkeysequence.h>
1349 #include <QtGui/qpen.h>
1350
1351 //#include <QtGui/qtextlength.h>
1352 #include <QtGui/qtextformat.h>
1353 #include <QtGui/qmatrix.h>
1354 #include <QtGui/qtransform.h>
1355 #include <QtGui/qmatrix4x4.h>
1356 #include <QtGui/qvector2d.h>
1357 #include <QtGui/qvector3d.h>
1358 #include <QtGui/qvector4d.h>
1359 #include <QtGui/qquaternion.h>
1360 #include <private/qv8engine_p.h>
1361
1362 Q_DECLARE_METATYPE(QJSValue);
1363 Q_DECLARE_METATYPE(QDeclarativeV8Handle);
1364
1365 QT_BEGIN_NAMESPACE
1366
1367 bool QDeclarativeMetaType::canCopy(int type)
1368 {
1369     switch(type) {
1370     case QMetaType::VoidStar:
1371     case QMetaType::QObjectStar:
1372     case QMetaType::QWidgetStar:
1373     case QMetaType::Long:
1374     case QMetaType::Int:
1375     case QMetaType::Short:
1376     case QMetaType::Char:
1377     case QMetaType::ULong:
1378     case QMetaType::UInt:
1379     case QMetaType::LongLong:
1380     case QMetaType::ULongLong:
1381     case QMetaType::UShort:
1382     case QMetaType::UChar:
1383     case QMetaType::Bool:
1384     case QMetaType::Float:
1385     case QMetaType::Double:
1386     case QMetaType::QChar:
1387     case QMetaType::QVariantMap:
1388     case QMetaType::QVariantHash:
1389     case QMetaType::QVariantList:
1390     case QMetaType::QByteArray:
1391     case QMetaType::QString:
1392     case QMetaType::QStringList:
1393     case QMetaType::QBitArray:
1394     case QMetaType::QDate:
1395     case QMetaType::QTime:
1396     case QMetaType::QDateTime:
1397     case QMetaType::QUrl:
1398     case QMetaType::QLocale:
1399     case QMetaType::QRect:
1400     case QMetaType::QRectF:
1401     case QMetaType::QSize:
1402     case QMetaType::QSizeF:
1403     case QMetaType::QLine:
1404     case QMetaType::QLineF:
1405     case QMetaType::QPoint:
1406     case QMetaType::QPointF:
1407     case QMetaType::QVector3D:
1408 #ifndef QT_NO_REGEXP
1409     case QMetaType::QRegExp:
1410 #endif
1411     case QMetaType::Void:
1412 #ifdef QT3_SUPPORT
1413     case QMetaType::QColorGroup:
1414 #endif
1415     case QMetaType::QFont:
1416     case QMetaType::QPixmap:
1417     case QMetaType::QBrush:
1418     case QMetaType::QColor:
1419     case QMetaType::QPalette:
1420     case QMetaType::QIcon:
1421     case QMetaType::QImage:
1422     case QMetaType::QPolygon:
1423     case QMetaType::QRegion:
1424     case QMetaType::QBitmap:
1425 #ifndef QT_NO_CURSOR
1426     case QMetaType::QCursor:
1427 #endif
1428     case QMetaType::QSizePolicy:
1429     case QMetaType::QKeySequence:
1430     case QMetaType::QPen:
1431     case QMetaType::QTextLength:
1432     case QMetaType::QTextFormat:
1433     case QMetaType::QMatrix:
1434     case QMetaType::QTransform:
1435     case QMetaType::QMatrix4x4:
1436     case QMetaType::QVector2D:
1437     case QMetaType::QVector4D:
1438     case QMetaType::QQuaternion:
1439         return true;
1440
1441     default:
1442         if (type == qMetaTypeId<QVariant>() ||
1443             type == qMetaTypeId<QJSValue>() ||
1444             type == qMetaTypeId<QDeclarativeV8Handle>() ||
1445             typeCategory(type) != Unknown) {
1446             return true;
1447         }
1448         break;
1449     }
1450
1451     return false;
1452 }
1453
1454 /*!
1455     Copies \a copy into \a data, assuming they both are of type \a type.  If
1456     \a copy is zero, a default type is copied.  Returns true if the copy was
1457     successful and false if not.
1458
1459     \note This should move into QMetaType once complete
1460
1461 */
1462 bool QDeclarativeMetaType::copy(int type, void *data, const void *copy)
1463 {
1464     if (copy) {
1465         switch(type) {
1466         case QMetaType::VoidStar:
1467         case QMetaType::QObjectStar:
1468         case QMetaType::QWidgetStar:
1469             *static_cast<void **>(data) = *static_cast<void* const *>(copy);
1470             return true;
1471         case QMetaType::Long:
1472             *static_cast<long *>(data) = *static_cast<const long*>(copy);
1473             return true;
1474         case QMetaType::Int:
1475             *static_cast<int *>(data) = *static_cast<const int*>(copy);
1476             return true;
1477         case QMetaType::Short:
1478             *static_cast<short *>(data) = *static_cast<const short*>(copy);
1479             return true;
1480         case QMetaType::Char:
1481             *static_cast<char *>(data) = *static_cast<const char*>(copy);
1482             return true;
1483         case QMetaType::ULong:
1484             *static_cast<ulong *>(data) = *static_cast<const ulong*>(copy);
1485             return true;
1486         case QMetaType::UInt:
1487             *static_cast<uint *>(data) = *static_cast<const uint*>(copy);
1488             return true;
1489         case QMetaType::LongLong:
1490             *static_cast<qlonglong *>(data) = *static_cast<const qlonglong*>(copy);
1491             return true;
1492         case QMetaType::ULongLong:
1493             *static_cast<qulonglong *>(data) = *static_cast<const qulonglong*>(copy);
1494             return true;
1495         case QMetaType::UShort:
1496             *static_cast<ushort *>(data) = *static_cast<const ushort*>(copy);
1497             return true;
1498         case QMetaType::UChar:
1499             *static_cast<uchar *>(data) = *static_cast<const uchar*>(copy);
1500             return true;
1501         case QMetaType::Bool:
1502             *static_cast<bool *>(data) = *static_cast<const bool*>(copy);
1503             return true;
1504         case QMetaType::Float:
1505             *static_cast<float *>(data) = *static_cast<const float*>(copy);
1506             return true;
1507         case QMetaType::Double:
1508             *static_cast<double *>(data) = *static_cast<const double*>(copy);
1509             return true;
1510         case QMetaType::QChar:
1511             *static_cast<NS(QChar) *>(data) = *static_cast<const NS(QChar)*>(copy);
1512             return true;
1513         case QMetaType::QVariantMap:
1514             *static_cast<NS(QVariantMap) *>(data) = *static_cast<const NS(QVariantMap)*>(copy);
1515             return true;
1516         case QMetaType::QVariantHash:
1517             *static_cast<NS(QVariantHash) *>(data) = *static_cast<const NS(QVariantHash)*>(copy);
1518             return true;
1519         case QMetaType::QVariantList:
1520             *static_cast<NS(QVariantList) *>(data) = *static_cast<const NS(QVariantList)*>(copy);
1521             return true;
1522         case QMetaType::QByteArray:
1523             *static_cast<NS(QByteArray) *>(data) = *static_cast<const NS(QByteArray)*>(copy);
1524             return true;
1525         case QMetaType::QString:
1526             *static_cast<NS(QString) *>(data) = *static_cast<const NS(QString)*>(copy);
1527             return true;
1528         case QMetaType::QStringList:
1529             *static_cast<NS(QStringList) *>(data) = *static_cast<const NS(QStringList)*>(copy);
1530             return true;
1531         case QMetaType::QBitArray:
1532             *static_cast<NS(QBitArray) *>(data) = *static_cast<const NS(QBitArray)*>(copy);
1533             return true;
1534         case QMetaType::QDate:
1535             *static_cast<NS(QDate) *>(data) = *static_cast<const NS(QDate)*>(copy);
1536             return true;
1537         case QMetaType::QTime:
1538             *static_cast<NS(QTime) *>(data) = *static_cast<const NS(QTime)*>(copy);
1539             return true;
1540         case QMetaType::QDateTime:
1541             *static_cast<NS(QDateTime) *>(data) = *static_cast<const NS(QDateTime)*>(copy);
1542             return true;
1543         case QMetaType::QUrl:
1544             *static_cast<NS(QUrl) *>(data) = *static_cast<const NS(QUrl)*>(copy);
1545             return true;
1546         case QMetaType::QLocale:
1547             *static_cast<NS(QLocale) *>(data) = *static_cast<const NS(QLocale)*>(copy);
1548             return true;
1549         case QMetaType::QRect:
1550             *static_cast<NS(QRect) *>(data) = *static_cast<const NS(QRect)*>(copy);
1551             return true;
1552         case QMetaType::QRectF:
1553             *static_cast<NS(QRectF) *>(data) = *static_cast<const NS(QRectF)*>(copy);
1554             return true;
1555         case QMetaType::QSize:
1556             *static_cast<NS(QSize) *>(data) = *static_cast<const NS(QSize)*>(copy);
1557             return true;
1558         case QMetaType::QSizeF:
1559             *static_cast<NS(QSizeF) *>(data) = *static_cast<const NS(QSizeF)*>(copy);
1560             return true;
1561         case QMetaType::QLine:
1562             *static_cast<NS(QLine) *>(data) = *static_cast<const NS(QLine)*>(copy);
1563             return true;
1564         case QMetaType::QLineF:
1565             *static_cast<NS(QLineF) *>(data) = *static_cast<const NS(QLineF)*>(copy);
1566             return true;
1567         case QMetaType::QPoint:
1568             *static_cast<NS(QPoint) *>(data) = *static_cast<const NS(QPoint)*>(copy);
1569             return true;
1570         case QMetaType::QPointF:
1571             *static_cast<NS(QPointF) *>(data) = *static_cast<const NS(QPointF)*>(copy);
1572             return true;
1573         case QMetaType::QVector3D:
1574             *static_cast<NS(QVector3D) *>(data) = *static_cast<const NS(QVector3D)*>(copy);
1575             return true;
1576 #ifndef QT_NO_REGEXP
1577         case QMetaType::QRegExp:
1578             *static_cast<NS(QRegExp) *>(data) = *static_cast<const NS(QRegExp)*>(copy);
1579             return true;
1580 #endif
1581         case QMetaType::Void:
1582             return true;
1583
1584
1585 #ifdef QT3_SUPPORT
1586         case QMetaType::QColorGroup:
1587             *static_cast<NS(QColorGroup) *>(data) = *static_cast<const NS(QColorGroup)*>(copy);
1588             return true;
1589 #endif
1590
1591         case QMetaType::QFont:
1592             *static_cast<NS(QFont) *>(data) = *static_cast<const NS(QFont)*>(copy);
1593             return true;
1594         case QMetaType::QPixmap:
1595             *static_cast<NS(QPixmap) *>(data) = *static_cast<const NS(QPixmap)*>(copy);
1596             return true;
1597         case QMetaType::QBrush:
1598             *static_cast<NS(QBrush) *>(data) = *static_cast<const NS(QBrush)*>(copy);
1599             return true;
1600         case QMetaType::QColor:
1601             *static_cast<NS(QColor) *>(data) = *static_cast<const NS(QColor)*>(copy);
1602             return true;
1603         case QMetaType::QPalette:
1604             *static_cast<NS(QPalette) *>(data) = *static_cast<const NS(QPalette)*>(copy);
1605             return true;
1606         case QMetaType::QIcon:
1607             *static_cast<NS(QIcon) *>(data) = *static_cast<const NS(QIcon)*>(copy);
1608             return true;
1609         case QMetaType::QImage:
1610             *static_cast<NS(QImage) *>(data) = *static_cast<const NS(QImage)*>(copy);
1611             return true;
1612         case QMetaType::QPolygon:
1613             *static_cast<NS(QPolygon) *>(data) = *static_cast<const NS(QPolygon)*>(copy);
1614             return true;
1615         case QMetaType::QRegion:
1616             *static_cast<NS(QRegion) *>(data) = *static_cast<const NS(QRegion)*>(copy);
1617             return true;
1618         case QMetaType::QBitmap:
1619             *static_cast<NS(QBitmap) *>(data) = *static_cast<const NS(QBitmap)*>(copy);
1620             return true;
1621 #ifndef QT_NO_CURSOR
1622         case QMetaType::QCursor:
1623             *static_cast<NS(QCursor) *>(data) = *static_cast<const NS(QCursor)*>(copy);
1624             return true;
1625 #endif
1626         case QMetaType::QSizePolicy:
1627             *static_cast<NS(QSizePolicy) *>(data) = *static_cast<const NS(QSizePolicy)*>(copy);
1628             return true;
1629         case QMetaType::QKeySequence:
1630             *static_cast<NS(QKeySequence) *>(data) = *static_cast<const NS(QKeySequence)*>(copy);
1631             return true;
1632         case QMetaType::QPen:
1633             *static_cast<NS(QPen) *>(data) = *static_cast<const NS(QPen)*>(copy);
1634             return true;
1635         case QMetaType::QTextLength:
1636             *static_cast<NS(QTextLength) *>(data) = *static_cast<const NS(QTextLength)*>(copy);
1637             return true;
1638         case QMetaType::QTextFormat:
1639             *static_cast<NS(QTextFormat) *>(data) = *static_cast<const NS(QTextFormat)*>(copy);
1640             return true;
1641         case QMetaType::QMatrix:
1642             *static_cast<NS(QMatrix) *>(data) = *static_cast<const NS(QMatrix)*>(copy);
1643             return true;
1644         case QMetaType::QTransform:
1645             *static_cast<NS(QTransform) *>(data) = *static_cast<const NS(QTransform)*>(copy);
1646             return true;
1647         case QMetaType::QMatrix4x4:
1648             *static_cast<NS(QMatrix4x4) *>(data) = *static_cast<const NS(QMatrix4x4)*>(copy);
1649             return true;
1650         case QMetaType::QVector2D:
1651             *static_cast<NS(QVector2D) *>(data) = *static_cast<const NS(QVector2D)*>(copy);
1652             return true;
1653         case QMetaType::QVector4D:
1654             *static_cast<NS(QVector4D) *>(data) = *static_cast<const NS(QVector4D)*>(copy);
1655             return true;
1656         case QMetaType::QQuaternion:
1657             *static_cast<NS(QQuaternion) *>(data) = *static_cast<const NS(QQuaternion)*>(copy);
1658             return true;
1659
1660         default:
1661             if (type == qMetaTypeId<QVariant>()) {
1662                 *static_cast<NS(QVariant) *>(data) = *static_cast<const NS(QVariant)*>(copy);
1663                 return true;
1664             } else if (type == qMetaTypeId<QJSValue>()) {
1665                 *static_cast<NS(QJSValue) *>(data) = *static_cast<const NS(QJSValue)*>(copy);
1666                 return true;
1667             } else if (type == qMetaTypeId<QDeclarativeV8Handle>()) {
1668                 *static_cast<NS(QDeclarativeV8Handle) *>(data) = *static_cast<const NS(QDeclarativeV8Handle)*>(copy);
1669                 return true;
1670             } else if (typeCategory(type) != Unknown) {
1671                 *static_cast<void **>(data) = *static_cast<void* const *>(copy);
1672                 return true;
1673             }
1674             break;
1675         }
1676     } else {
1677         switch(type) {
1678         case QMetaType::VoidStar:
1679         case QMetaType::QObjectStar:
1680         case QMetaType::QWidgetStar:
1681             *static_cast<void **>(data) = 0;
1682             return true;
1683         case QMetaType::Long:
1684             *static_cast<long *>(data) = long(0);
1685             return true;
1686         case QMetaType::Int:
1687             *static_cast<int *>(data) = int(0);
1688             return true;
1689         case QMetaType::Short:
1690             *static_cast<short *>(data) = short(0);
1691             return true;
1692         case QMetaType::Char:
1693             *static_cast<char *>(data) = char(0);
1694             return true;
1695         case QMetaType::ULong:
1696             *static_cast<ulong *>(data) = ulong(0);
1697             return true;
1698         case QMetaType::UInt:
1699             *static_cast<uint *>(data) = uint(0);
1700             return true;
1701         case QMetaType::LongLong:
1702             *static_cast<qlonglong *>(data) = qlonglong(0);
1703             return true;
1704         case QMetaType::ULongLong:
1705             *static_cast<qulonglong *>(data) = qulonglong(0);
1706             return true;
1707         case QMetaType::UShort:
1708             *static_cast<ushort *>(data) = ushort(0);
1709             return true;
1710         case QMetaType::UChar:
1711             *static_cast<uchar *>(data) = uchar(0);
1712             return true;
1713         case QMetaType::Bool:
1714             *static_cast<bool *>(data) = bool(false);
1715             return true;
1716         case QMetaType::Float:
1717             *static_cast<float *>(data) = float(0);
1718             return true;
1719         case QMetaType::Double:
1720             *static_cast<double *>(data) = double(0);
1721             return true;
1722         case QMetaType::QChar:
1723             *static_cast<NS(QChar) *>(data) = NS(QChar)();
1724             return true;
1725         case QMetaType::QVariantMap:
1726             *static_cast<NS(QVariantMap) *>(data) = NS(QVariantMap)();
1727             return true;
1728         case QMetaType::QVariantHash:
1729             *static_cast<NS(QVariantHash) *>(data) = NS(QVariantHash)();
1730             return true;
1731         case QMetaType::QVariantList:
1732             *static_cast<NS(QVariantList) *>(data) = NS(QVariantList)();
1733             return true;
1734         case QMetaType::QByteArray:
1735             *static_cast<NS(QByteArray) *>(data) = NS(QByteArray)();
1736             return true;
1737         case QMetaType::QString:
1738             *static_cast<NS(QString) *>(data) = NS(QString)();
1739             return true;
1740         case QMetaType::QStringList:
1741             *static_cast<NS(QStringList) *>(data) = NS(QStringList)();
1742             return true;
1743         case QMetaType::QBitArray:
1744             *static_cast<NS(QBitArray) *>(data) = NS(QBitArray)();
1745             return true;
1746         case QMetaType::QDate:
1747             *static_cast<NS(QDate) *>(data) = NS(QDate)();
1748             return true;
1749         case QMetaType::QTime:
1750             *static_cast<NS(QTime) *>(data) = NS(QTime)();
1751             return true;
1752         case QMetaType::QDateTime:
1753             *static_cast<NS(QDateTime) *>(data) = NS(QDateTime)();
1754             return true;
1755         case QMetaType::QUrl:
1756             *static_cast<NS(QUrl) *>(data) = NS(QUrl)();
1757             return true;
1758         case QMetaType::QLocale:
1759             *static_cast<NS(QLocale) *>(data) = NS(QLocale)();
1760             return true;
1761         case QMetaType::QRect:
1762             *static_cast<NS(QRect) *>(data) = NS(QRect)();
1763             return true;
1764         case QMetaType::QRectF:
1765             *static_cast<NS(QRectF) *>(data) = NS(QRectF)();
1766             return true;
1767         case QMetaType::QSize:
1768             *static_cast<NS(QSize) *>(data) = NS(QSize)();
1769             return true;
1770         case QMetaType::QSizeF:
1771             *static_cast<NS(QSizeF) *>(data) = NS(QSizeF)();
1772             return true;
1773         case QMetaType::QLine:
1774             *static_cast<NS(QLine) *>(data) = NS(QLine)();
1775             return true;
1776         case QMetaType::QLineF:
1777             *static_cast<NS(QLineF) *>(data) = NS(QLineF)();
1778             return true;
1779         case QMetaType::QPoint:
1780             *static_cast<NS(QPoint) *>(data) = NS(QPoint)();
1781             return true;
1782         case QMetaType::QPointF:
1783             *static_cast<NS(QPointF) *>(data) = NS(QPointF)();
1784             return true;
1785         case QMetaType::QVector3D:
1786             *static_cast<NS(QVector3D) *>(data) = NS(QVector3D)();
1787             return true;
1788 #ifndef QT_NO_REGEXP
1789         case QMetaType::QRegExp:
1790             *static_cast<NS(QRegExp) *>(data) = NS(QRegExp)();
1791             return true;
1792 #endif
1793         case QMetaType::Void:
1794             return true;
1795
1796 #ifdef QT3_SUPPORT
1797         case QMetaType::QColorGroup:
1798             *static_cast<NS(QColorGroup) *>(data) = NS(QColorGroup)();
1799             return true;
1800 #endif
1801
1802         case QMetaType::QFont:
1803             *static_cast<NS(QFont) *>(data) = NS(QFont)();
1804             return true;
1805         case QMetaType::QPixmap:
1806             *static_cast<NS(QPixmap) *>(data) = NS(QPixmap)();
1807             return true;
1808         case QMetaType::QBrush:
1809             *static_cast<NS(QBrush) *>(data) = NS(QBrush)();
1810             return true;
1811         case QMetaType::QColor:
1812             *static_cast<NS(QColor) *>(data) = NS(QColor)();
1813             return true;
1814         case QMetaType::QPalette:
1815             *static_cast<NS(QPalette) *>(data) = NS(QPalette)();
1816             return true;
1817         case QMetaType::QIcon:
1818             *static_cast<NS(QIcon) *>(data) = NS(QIcon)();
1819             return true;
1820         case QMetaType::QImage:
1821             *static_cast<NS(QImage) *>(data) = NS(QImage)();
1822             return true;
1823         case QMetaType::QPolygon:
1824             *static_cast<NS(QPolygon) *>(data) = NS(QPolygon)();
1825             return true;
1826         case QMetaType::QRegion:
1827             *static_cast<NS(QRegion) *>(data) = NS(QRegion)();
1828             return true;
1829         case QMetaType::QBitmap:
1830             *static_cast<NS(QBitmap) *>(data) = NS(QBitmap)();
1831             return true;
1832 #ifndef QT_NO_CURSOR
1833         case QMetaType::QCursor:
1834             *static_cast<NS(QCursor) *>(data) = NS(QCursor)();
1835             return true;
1836 #endif
1837         case QMetaType::QSizePolicy:
1838             *static_cast<NS(QSizePolicy) *>(data) = NS(QSizePolicy)();
1839             return true;
1840         case QMetaType::QKeySequence:
1841             *static_cast<NS(QKeySequence) *>(data) = NS(QKeySequence)();
1842             return true;
1843         case QMetaType::QPen:
1844             *static_cast<NS(QPen) *>(data) = NS(QPen)();
1845             return true;
1846         case QMetaType::QTextLength:
1847             *static_cast<NS(QTextLength) *>(data) = NS(QTextLength)();
1848             return true;
1849         case QMetaType::QTextFormat:
1850             *static_cast<NS(QTextFormat) *>(data) = NS(QTextFormat)();
1851             return true;
1852         case QMetaType::QMatrix:
1853             *static_cast<NS(QMatrix) *>(data) = NS(QMatrix)();
1854             return true;
1855         case QMetaType::QTransform:
1856             *static_cast<NS(QTransform) *>(data) = NS(QTransform)();
1857             return true;
1858         case QMetaType::QMatrix4x4:
1859             *static_cast<NS(QMatrix4x4) *>(data) = NS(QMatrix4x4)();
1860             return true;
1861         case QMetaType::QVector2D:
1862             *static_cast<NS(QVector2D) *>(data) = NS(QVector2D)();
1863             return true;
1864         case QMetaType::QVector4D:
1865             *static_cast<NS(QVector4D) *>(data) = NS(QVector4D)();
1866             return true;
1867         case QMetaType::QQuaternion:
1868             *static_cast<NS(QQuaternion) *>(data) = NS(QQuaternion)();
1869             return true;
1870         default:
1871             if (type == qMetaTypeId<QVariant>()) {
1872                 *static_cast<NS(QVariant) *>(data) = NS(QVariant)();
1873                 return true;
1874             } else if (type == qMetaTypeId<QJSValue>()) {
1875                 *static_cast<NS(QJSValue) *>(data) = NS(QJSValue)();
1876                 return true;
1877             } else if (type == qMetaTypeId<QDeclarativeV8Handle>()) {
1878                 *static_cast<NS(QDeclarativeV8Handle) *>(data) = NS(QDeclarativeV8Handle)();
1879                 return true;
1880             } else if (typeCategory(type) != Unknown) {
1881                 *static_cast<void **>(data) = 0;
1882                 return true;
1883             }
1884             break;
1885         }
1886     }
1887
1888     return false;
1889 }
1890
1891 QT_END_NAMESPACE