Immense Particles Refactor Part A
[profile/ivi/qtdeclarative.git] / src / declarative / qml / qdeclarativeengine.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 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "private/qdeclarativeengine_p.h"
43 #include "qdeclarativeengine.h"
44
45 #include "private/qdeclarativecontext_p.h"
46 #include "private/qdeclarativecompiler_p.h"
47 #include "private/qdeclarativeglobalscriptclass_p.h"
48 #include "qdeclarative.h"
49 #include "qdeclarativecontext.h"
50 #include "qdeclarativeexpression.h"
51 #include "qdeclarativecomponent.h"
52 #include "private/qdeclarativebinding_p_p.h"
53 #include "private/qdeclarativevme_p.h"
54 #include "private/qdeclarativeenginedebug_p.h"
55 #include "private/qdeclarativestringconverters_p.h"
56 #include "private/qdeclarativexmlhttprequest_p.h"
57 #include "private/qdeclarativesqldatabase_p.h"
58 #include "private/qdeclarativescarceresourcescriptclass_p.h"
59 #include "private/qdeclarativetypenamescriptclass_p.h"
60 #include "private/qdeclarativelistscriptclass_p.h"
61 #include "qdeclarativescriptstring.h"
62 #include "private/qdeclarativeglobal_p.h"
63 #include "private/qdeclarativeworkerscript_p.h"
64 #include "private/qdeclarativecomponent_p.h"
65 #include "qdeclarativenetworkaccessmanagerfactory.h"
66 #include "qdeclarativeimageprovider.h"
67 #include "private/qdeclarativedirparser_p.h"
68 #include "qdeclarativeextensioninterface.h"
69 #include "private/qdeclarativelist_p.h"
70 #include "private/qdeclarativetypenamecache_p.h"
71 #include "private/qdeclarativeinclude_p.h"
72 #include "private/qdeclarativenotifier_p.h"
73 #include "private/qdeclarativedebugtrace_p.h"
74 #include "private/qdeclarativeapplication_p.h"
75 #include "private/qjsdebugservice_p.h"
76
77 #include <QtCore/qmetaobject.h>
78 #include <QScriptClass>
79 #include <QNetworkReply>
80 #include <QNetworkRequest>
81 #include <QNetworkAccessManager>
82 #include <QDesktopServices>
83 #include <QTimer>
84 #include <QList>
85 #include <QPair>
86 #include <QDebug>
87 #include <QMetaObject>
88 #include <QStack>
89 #include <QMap>
90 #include <QPluginLoader>
91 #include <QtGui/qfontdatabase.h>
92 #include <QtCore/qlibraryinfo.h>
93 #include <QtCore/qthreadstorage.h>
94 #include <QtCore/qthread.h>
95 #include <QtCore/qcoreapplication.h>
96 #include <QtCore/qdir.h>
97 #include <QtCore/qmutex.h>
98 #include <QtGui/qcolor.h>
99 #include <QtGui/qvector3d.h>
100 #include <QtGui/qsound.h>
101 #include <QtCore/qcryptographichash.h>
102
103 #include <private/qobject_p.h>
104 #include <private/qscriptdeclarativeclass_p.h>
105
106 #include <private/qdeclarativeitemsmodule_p.h>
107 #include <private/qdeclarativeutilmodule_p.h>
108 #include <private/qsgitemsmodule_p.h>
109 #include <private/qsgparticlesmodule_p.h>
110 #include <qsgtexture.h>
111
112 #ifdef Q_OS_WIN // for %APPDATA%
113 #include <qt_windows.h>
114 #include <qlibrary.h>
115 #include <windows.h>
116
117 #define CSIDL_APPDATA           0x001a  // <username>\Application Data
118 #endif
119
120 Q_DECLARE_METATYPE(QDeclarativeProperty)
121
122 QT_BEGIN_NAMESPACE
123
124 /*!
125   \qmlclass QtObject QObject
126   \ingroup qml-utility-elements
127   \since 4.7
128   \brief The QtObject element is the most basic element in QML.
129
130   The QtObject element is a non-visual element which contains only the
131   objectName property.
132
133   It can be useful to create a QtObject if you need an extremely
134   lightweight element to enclose a set of custom properties:
135
136   \snippet doc/src/snippets/declarative/qtobject.qml 0
137
138   It can also be useful for C++ integration, as it is just a plain
139   QObject. See the QObject documentation for further details.
140 */
141 /*!
142   \qmlproperty string QML:QtObject::objectName
143   This property holds the QObject::objectName for this specific object instance.
144
145   This allows a C++ application to locate an item within a QML component
146   using the QObject::findChild() method. For example, the following C++
147   application locates the child \l Rectangle item and dynamically changes its
148   \c color value:
149
150     \qml
151     // MyRect.qml
152
153     import QtQuick 1.0
154
155     Item {
156         width: 200; height: 200
157
158         Rectangle {
159             anchors.fill: parent
160             color: "red"
161             objectName: "myRect"
162         }
163     }
164     \endqml
165
166     \code
167     // main.cpp
168
169     QDeclarativeView view;
170     view.setSource(QUrl::fromLocalFile("MyRect.qml"));
171     view.show();
172
173     QDeclarativeItem *item = view.rootObject()->findChild<QDeclarativeItem*>("myRect");
174     if (item)
175         item->setProperty("color", QColor(Qt::yellow));
176     \endcode
177 */
178
179 struct StaticQtMetaObject : public QObject
180 {
181     static const QMetaObject *get()
182         { return &static_cast<StaticQtMetaObject*> (0)->staticQtMetaObject; }
183 };
184
185 static bool qt_QmlQtModule_registered = false;
186 bool QDeclarativeEnginePrivate::qml_debugging_enabled = false;
187
188 void QDeclarativeEnginePrivate::defineModule()
189 {
190     qmlRegisterType<QDeclarativeComponent>("QtQuick",1,0,"Component");
191     qmlRegisterType<QObject>("QtQuick",1,0,"QtObject");
192     qmlRegisterType<QDeclarativeWorkerScript>("QtQuick",1,0,"WorkerScript");
193
194 #ifndef QT_NO_IMPORT_QT47_QML
195     qmlRegisterType<QDeclarativeComponent>("Qt",4,7,"Component");
196     qmlRegisterType<QObject>("Qt",4,7,"QtObject");
197     qmlRegisterType<QDeclarativeWorkerScript>("Qt",4,7,"WorkerScript");
198 #endif
199
200     qmlRegisterType<QDeclarativeBinding>();
201 }
202
203 /*!
204 \qmlclass QML:Qt QDeclarativeEnginePrivate
205   \ingroup qml-utility-elements
206 \brief The QML global Qt object provides useful enums and functions from Qt.
207
208 \keyword QmlGlobalQtObject
209
210 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
211
212 The \c Qt object is a global object with utility functions, properties and enums.
213
214 It is not instantiable; to use it, call the members of the global \c Qt object directly.
215 For example:
216
217 \qml
218 import QtQuick 1.0
219
220 Text {
221     color: Qt.rgba(1, 0, 0, 1)
222     text: Qt.md5("hello, world")
223 }
224 \endqml
225
226
227 \section1 Enums
228
229 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
230 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
231
232
233 \section1 Types
234 The Qt object also contains helper functions for creating objects of specific
235 data types. This is primarily useful when setting the properties of an item
236 when the property has one of the following types:
237
238 \list
239 \o \c color - use \l{QML:Qt::rgba()}{Qt.rgba()}, \l{QML:Qt::hsla()}{Qt.hsla()}, \l{QML:Qt::darker()}{Qt.darker()}, \l{QML:Qt::lighter()}{Qt.lighter()} or \l{QML:Qt::tint()}{Qt.tint()}
240 \o \c rect - use \l{QML:Qt::rect()}{Qt.rect()}
241 \o \c point - use \l{QML:Qt::point()}{Qt.point()}
242 \o \c size - use \l{QML:Qt::size()}{Qt.size()}
243 \o \c vector3d - use \l{QML:Qt::vector3d()}{Qt.vector3d()}
244 \endlist
245
246 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
247
248 \section1 Date/Time Formatters
249
250 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
251
252 \list
253     \o \l{QML:Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
254     \o \l{QML:Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
255     \o \l{QML:Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
256 \endlist
257
258 The format specification is described at \l{QML:Qt::formatDateTime}{Qt.formatDateTime}.
259
260
261 \section1 Dynamic Object Creation
262 The following functions on the global object allow you to dynamically create QML
263 items from files or strings. See \l{Dynamic Object Management in QML} for an overview
264 of their use.
265
266 \list
267     \o \l{QML:Qt::createComponent()}{object Qt.createComponent(url)}
268     \o \l{QML:Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
269 \endlist
270 */
271
272
273 /*!
274     \qmlproperty object QML:Qt::application
275     \since QtQuick 1.1
276
277     The \c application object provides access to global application state
278     properties shared by many QML components.
279
280     Its properties are:
281
282     \table
283     \row
284     \o \c application.active
285     \o
286     This read-only property indicates whether the application is the top-most and focused
287     application, and the user is able to interact with the application. The property
288     is false when the application is in the background, the device keylock or screen
289     saver is active, the screen backlight is turned off, or the global system dialog
290     is being displayed on top of the application. It can be used for stopping and
291     pausing animations, timers and active processing of data in order to save device
292     battery power and free device memory and processor load when the application is not
293     active.
294
295     \row
296     \o \c application.layoutDirection
297     \o
298     This read-only property can be used to query the default layout direction of the
299     application. On system start-up, the default layout direction depends on the
300     application's language. The property has a value of \c Qt.RightToLeft in locales
301     where text and graphic elements are read from right to left, and \c Qt.LeftToRight
302     where the reading direction flows from left to right. You can bind to this
303     property to customize your application layouts to support both layout directions.
304
305     Possible values are:
306
307     \list
308     \o Qt.LeftToRight - Text and graphics elements should be positioned
309                         from left to right.
310     \o Qt.RightToLeft - Text and graphics elements should be positioned
311                         from right to left.
312     \endlist
313     \endtable
314
315     The following example uses the \c application object to indicate
316     whether the application is currently active:
317
318     \snippet doc/src/snippets/declarative/application.qml document
319
320 */
321
322
323 /*!
324 \qmlmethod object Qt::include(string url, jsobject callback)
325
326 Includes another JavaScript file. This method can only be used from within JavaScript files,
327 and not regular QML files.
328
329 This imports all functions from \a url into the current script's namespace.
330
331 Qt.include() returns an object that describes the status of the operation.  The object has
332 a single property, \c {status}, that is set to one of the following values:
333
334 \table
335 \header \o Symbol \o Value \o Description
336 \row \o result.OK \o 0 \o The include completed successfully.
337 \row \o result.LOADING \o 1 \o Data is being loaded from the network.
338 \row \o result.NETWORK_ERROR \o 2 \o A network error occurred while fetching the url.
339 \row \o result.EXCEPTION \o 3 \o A JavaScript exception occurred while executing the included code.
340 An additional \c exception property will be set in this case.
341 \endtable
342
343 The \c status property will be updated as the operation progresses.
344
345 If provided, \a callback is invoked when the operation completes.  The callback is passed
346 the same object as is returned from the Qt.include() call.
347 */
348 // Qt.include() is implemented in qdeclarativeinclude.cpp
349
350
351 QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e)
352 : captureProperties(false), rootContext(0), isDebugging(false),
353   outputWarningsToStdErr(true), contextClass(0), sharedContext(0), sharedScope(0),
354   objectClass(0), valueTypeClass(0), globalClass(0), cleanup(0), erroredBindings(0),
355   inProgressCreations(0), scriptEngine(this), workerScriptEngine(0), componentAttached(0),
356   inBeginCreate(false), networkAccessManager(0), networkAccessManagerFactory(0),
357   scarceResources(0), scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
358   sgContext(0)
359 {
360     if (!qt_QmlQtModule_registered) {
361         qt_QmlQtModule_registered = true;
362         QDeclarativeItemModule::defineModule();
363         QDeclarativeUtilModule::defineModule();
364         QDeclarativeEnginePrivate::defineModule();
365         QSGItemsModule::defineModule();
366         QSGParticlesModule::defineModule();
367         QDeclarativeValueTypeFactory::registerValueTypes();
368     }
369     globalClass = new QDeclarativeGlobalScriptClass(&scriptEngine);
370 }
371
372 /*!
373   \qmlmethod url Qt::resolvedUrl(url url)
374   Returns \a url resolved relative to the URL of the caller.
375 */
376 QUrl QDeclarativeScriptEngine::resolvedUrl(QScriptContext *context, const QUrl& url)
377 {
378     if (p) {
379         QDeclarativeContextData *ctxt = p->getContext(context);
380         if (ctxt)
381             return ctxt->resolvedUrl(url);
382         else
383             return p->getUrl(context).resolved(url);
384     }
385     return baseUrl.resolved(url);
386 }
387
388 QDeclarativeScriptEngine::QDeclarativeScriptEngine(QDeclarativeEnginePrivate *priv)
389 : p(priv), sqlQueryClass(0), namedNodeMapClass(0), nodeListClass(0)
390 {
391     // Note that all documentation for stuff put on the global object goes in
392     // doc/src/declarative/globalobject.qdoc
393
394     bool mainthread = priv != 0;
395
396     QScriptValue qtObject =
397         newQMetaObject(StaticQtMetaObject::get());
398     globalObject().setProperty(QLatin1String("Qt"), qtObject);
399
400 #ifndef QT_NO_DESKTOPSERVICES
401     offlineStoragePath = QDesktopServices::storageLocation(QDesktopServices::DataLocation).replace(QLatin1Char('/'), QDir::separator())
402         + QDir::separator() + QLatin1String("QML")
403         + QDir::separator() + QLatin1String("OfflineStorage");
404 #endif
405
406 #ifndef QT_NO_XMLSTREAMREADER
407     qt_add_qmlxmlhttprequest(this);
408 #endif
409     qt_add_qmlsqldatabase(this);
410     // XXX A Multimedia "Qt.Sound" class also needs to be made available,
411     // XXX but we don't want a dependency in that cirection.
412     // XXX When the above a done some better way, that way should also be
413     // XXX used to add Qt.Sound class.
414
415     //types
416     if (mainthread)
417         qtObject.setProperty(QLatin1String("include"), newFunction(QDeclarativeInclude::include, 2));
418     else
419         qtObject.setProperty(QLatin1String("include"), newFunction(QDeclarativeInclude::worker_include, 2));
420
421     qtObject.setProperty(QLatin1String("isQtObject"), newFunction(QDeclarativeEnginePrivate::isQtObject, 1));
422     qtObject.setProperty(QLatin1String("rgba"), newFunction(QDeclarativeEnginePrivate::rgba, 4));
423     qtObject.setProperty(QLatin1String("hsla"), newFunction(QDeclarativeEnginePrivate::hsla, 4));
424     qtObject.setProperty(QLatin1String("rect"), newFunction(QDeclarativeEnginePrivate::rect, 4));
425     qtObject.setProperty(QLatin1String("point"), newFunction(QDeclarativeEnginePrivate::point, 2));
426     qtObject.setProperty(QLatin1String("size"), newFunction(QDeclarativeEnginePrivate::size, 2));
427     qtObject.setProperty(QLatin1String("vector3d"), newFunction(QDeclarativeEnginePrivate::vector3d, 3));
428
429     if (mainthread) {
430         //color helpers
431         qtObject.setProperty(QLatin1String("lighter"), newFunction(QDeclarativeEnginePrivate::lighter, 1));
432         qtObject.setProperty(QLatin1String("darker"), newFunction(QDeclarativeEnginePrivate::darker, 1));
433         qtObject.setProperty(QLatin1String("tint"), newFunction(QDeclarativeEnginePrivate::tint, 2));
434     }
435
436 #ifndef QT_NO_DATESTRING
437     //date/time formatting
438     qtObject.setProperty(QLatin1String("formatDate"),newFunction(QDeclarativeEnginePrivate::formatDate, 2));
439     qtObject.setProperty(QLatin1String("formatTime"),newFunction(QDeclarativeEnginePrivate::formatTime, 2));
440     qtObject.setProperty(QLatin1String("formatDateTime"),newFunction(QDeclarativeEnginePrivate::formatDateTime, 2));
441 #endif
442
443     //misc methods
444     qtObject.setProperty(QLatin1String("openUrlExternally"),newFunction(QDeclarativeEnginePrivate::desktopOpenUrl, 1));
445     qtObject.setProperty(QLatin1String("fontFamilies"),newFunction(QDeclarativeEnginePrivate::fontFamilies, 0));
446     qtObject.setProperty(QLatin1String("md5"),newFunction(QDeclarativeEnginePrivate::md5, 1));
447     qtObject.setProperty(QLatin1String("btoa"),newFunction(QDeclarativeEnginePrivate::btoa, 1));
448     qtObject.setProperty(QLatin1String("atob"),newFunction(QDeclarativeEnginePrivate::atob, 1));
449     qtObject.setProperty(QLatin1String("quit"), newFunction(QDeclarativeEnginePrivate::quit, 0));
450     qtObject.setProperty(QLatin1String("resolvedUrl"),newFunction(QDeclarativeScriptEngine::resolvedUrl, 1));
451
452     if (mainthread) {
453         qtObject.setProperty(QLatin1String("createQmlObject"),
454                 newFunction(QDeclarativeEnginePrivate::createQmlObject, 1));
455         qtObject.setProperty(QLatin1String("createComponent"),
456                 newFunction(QDeclarativeEnginePrivate::createComponent, 1));
457     }
458
459     //firebug/webkit compat
460     QScriptValue consoleObject = newObject();
461     consoleObject.setProperty(QLatin1String("log"),newFunction(QDeclarativeEnginePrivate::consoleLog, 1));
462     consoleObject.setProperty(QLatin1String("debug"),newFunction(QDeclarativeEnginePrivate::consoleLog, 1));
463     globalObject().setProperty(QLatin1String("console"), consoleObject);
464
465     // translation functions need to be installed
466     // before the global script class is constructed (QTBUG-6437)
467     installTranslatorFunctions();
468 }
469
470 QDeclarativeScriptEngine::~QDeclarativeScriptEngine()
471 {
472     delete sqlQueryClass;
473     delete nodeListClass;
474     delete namedNodeMapClass;
475 }
476
477 QScriptValue QDeclarativeScriptEngine::resolvedUrl(QScriptContext *ctxt, QScriptEngine *engine)
478 {
479     QString arg = ctxt->argument(0).toString();
480     QUrl r = QDeclarativeScriptEngine::get(engine)->resolvedUrl(ctxt,QUrl(arg));
481     return QScriptValue(r.toString());
482 }
483
484 QNetworkAccessManager *QDeclarativeScriptEngine::networkAccessManager()
485 {
486     return p->getNetworkAccessManager();
487 }
488
489 QDeclarativeEnginePrivate::~QDeclarativeEnginePrivate()
490 {
491     Q_ASSERT(inProgressCreations == 0);
492     Q_ASSERT(bindValues.isEmpty());
493     Q_ASSERT(parserStatus.isEmpty());
494
495     while (cleanup) {
496         QDeclarativeCleanup *c = cleanup;
497         cleanup = c->next;
498         if (cleanup) cleanup->prev = &cleanup;
499         c->next = 0;
500         c->prev = 0;
501         c->clear();
502     }
503
504     delete rootContext;
505     rootContext = 0;
506     delete contextClass;
507     contextClass = 0;
508     delete objectClass;
509     objectClass = 0;
510     delete scarceResourceClass;
511     scarceResourceClass = 0;
512     delete valueTypeClass;
513     valueTypeClass = 0;
514     delete typeNameClass;
515     typeNameClass = 0;
516     delete listClass;
517     listClass = 0;
518     delete globalClass;
519     globalClass = 0;
520
521     for(QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
522         (*iter)->release();
523     for(QHash<const QMetaObject *, QDeclarativePropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
524         (*iter)->release();
525     for(QHash<QPair<QDeclarativeType *, int>, QDeclarativePropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
526         (*iter)->release();
527     for(QHash<QDeclarativeMetaType::ModuleApi, QDeclarativeMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
528         delete (*iter)->qobjectApi;
529         delete *iter;
530     }
531 }
532
533 void QDeclarativeEnginePrivate::clear(SimpleList<QDeclarativeAbstractBinding> &bvs)
534 {
535     bvs.clear();
536 }
537
538 void QDeclarativeEnginePrivate::clear(SimpleList<QDeclarativeParserStatus> &pss)
539 {
540     for (int ii = 0; ii < pss.count; ++ii) {
541         QDeclarativeParserStatus *ps = pss.at(ii);
542         if(ps)
543             ps->d = 0;
544     }
545     pss.clear();
546 }
547
548 void QDeclarativePrivate::qdeclarativeelement_destructor(QObject *o)
549 {
550     QObjectPrivate *p = QObjectPrivate::get(o);
551     if (p->declarativeData) {
552         QDeclarativeData *d = static_cast<QDeclarativeData*>(p->declarativeData);
553         if (d->ownContext && d->context) {
554             d->context->destroy();
555             d->context = 0;
556         }
557     }
558 }
559
560 void QDeclarativeData::destroyed(QAbstractDeclarativeData *d, QObject *o)
561 {
562     static_cast<QDeclarativeData *>(d)->destroyed(o);
563 }
564
565 void QDeclarativeData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
566 {
567     static_cast<QDeclarativeData *>(d)->parentChanged(o, p);
568 }
569
570 void QDeclarativeData::objectNameChanged(QAbstractDeclarativeData *d, QObject *o)
571 {
572     static_cast<QDeclarativeData *>(d)->objectNameChanged(o);
573 }
574
575 void QDeclarativeEnginePrivate::init()
576 {
577     Q_Q(QDeclarativeEngine);
578     qRegisterMetaType<QVariant>("QVariant");
579     qRegisterMetaType<QDeclarativeScriptString>("QDeclarativeScriptString");
580     qRegisterMetaType<QScriptValue>("QScriptValue");
581     qRegisterMetaType<QDeclarativeComponent::Status>("QDeclarativeComponent::Status");
582
583     QDeclarativeData::init();
584
585     contextClass = new QDeclarativeContextScriptClass(q);
586     objectClass = new QDeclarativeObjectScriptClass(q);
587     scarceResourceClass = new QDeclarativeScarceResourceScriptClass(q);
588     valueTypeClass = new QDeclarativeValueTypeScriptClass(q);
589     typeNameClass = new QDeclarativeTypeNameScriptClass(q);
590     listClass = new QDeclarativeListScriptClass(q);
591     rootContext = new QDeclarativeContext(q,true);
592
593     QScriptValue applicationObject = objectClass->newQObject(new QDeclarativeApplication(q));
594     scriptEngine.globalObject().property(QLatin1String("Qt")).setProperty(QLatin1String("application"), applicationObject);
595
596     if (QCoreApplication::instance()->thread() == q->thread() &&
597         QDeclarativeEngineDebugServer::isDebuggingEnabled()) {
598         isDebugging = true;
599         QDeclarativeEngineDebugServer::instance()->addEngine(q);
600         QJSDebugService::instance()->addEngine(q);
601     }
602 }
603
604 QDeclarativeWorkerScriptEngine *QDeclarativeEnginePrivate::getWorkerScriptEngine()
605 {
606     Q_Q(QDeclarativeEngine);
607     if (!workerScriptEngine)
608         workerScriptEngine = new QDeclarativeWorkerScriptEngine(q);
609     return workerScriptEngine;
610 }
611
612 /*!
613   \class QDeclarativeEngine
614   \since 4.7
615   \brief The QDeclarativeEngine class provides an environment for instantiating QML components.
616   \mainclass
617
618   Each QML component is instantiated in a QDeclarativeContext.
619   QDeclarativeContext's are essential for passing data to QML
620   components.  In QML, contexts are arranged hierarchically and this
621   hierarchy is managed by the QDeclarativeEngine.
622
623   Prior to creating any QML components, an application must have
624   created a QDeclarativeEngine to gain access to a QML context.  The
625   following example shows how to create a simple Text item.
626
627   \code
628   QDeclarativeEngine engine;
629   QDeclarativeComponent component(&engine);
630   component.setData("import QtQuick 1.0\nText { text: \"Hello world!\" }", QUrl());
631   QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(component.create());
632
633   //add item to view, etc
634   ...
635   \endcode
636
637   In this case, the Text item will be created in the engine's
638   \l {QDeclarativeEngine::rootContext()}{root context}.
639
640   \sa QDeclarativeComponent QDeclarativeContext
641 */
642
643 /*!
644   Create a new QDeclarativeEngine with the given \a parent.
645 */
646 QDeclarativeEngine::QDeclarativeEngine(QObject *parent)
647 : QObject(*new QDeclarativeEnginePrivate(this), parent)
648 {
649     Q_D(QDeclarativeEngine);
650     d->init();
651 }
652
653 /*!
654   Destroys the QDeclarativeEngine.
655
656   Any QDeclarativeContext's created on this engine will be
657   invalidated, but not destroyed (unless they are parented to the
658   QDeclarativeEngine object).
659 */
660 QDeclarativeEngine::~QDeclarativeEngine()
661 {
662     Q_D(QDeclarativeEngine);
663     if (d->isDebugging) {
664         QDeclarativeEngineDebugServer::instance()->remEngine(this);
665     }
666
667     // if we are the parent of any of the qobject module api instances,
668     // we need to remove them from our internal list, in order to prevent
669     // a segfault in engine private dtor.
670     QList<QDeclarativeMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
671     QObject *currQObjectApi = 0;
672     QDeclarativeMetaType::ModuleApiInstance *currInstance = 0;
673     foreach (const QDeclarativeMetaType::ModuleApi &key, keys) {
674         currInstance = d->moduleApiInstances.value(key);
675         currQObjectApi = currInstance->qobjectApi;
676         if (this->children().contains(currQObjectApi)) {
677             delete currQObjectApi;
678             delete currInstance;
679             d->moduleApiInstances.remove(key);
680         }
681     }
682 }
683
684 /*! \fn void QDeclarativeEngine::quit()
685     This signal is emitted when the QML loaded by the engine would like to quit.
686  */
687
688 /*! \fn void QDeclarativeEngine::warnings(const QList<QDeclarativeError> &warnings)
689     This signal is emitted when \a warnings messages are generated by QML.
690  */
691
692 /*!
693   Clears the engine's internal component cache.
694
695   Normally the QDeclarativeEngine caches components loaded from qml
696   files.  This method clears this cache and forces the component to be
697   reloaded.
698  */
699 void QDeclarativeEngine::clearComponentCache()
700 {
701     Q_D(QDeclarativeEngine);
702     d->typeLoader.clearCache();
703 }
704
705 /*!
706   Returns the engine's root context.
707
708   The root context is automatically created by the QDeclarativeEngine.
709   Data that should be available to all QML component instances
710   instantiated by the engine should be put in the root context.
711
712   Additional data that should only be available to a subset of
713   component instances should be added to sub-contexts parented to the
714   root context.
715 */
716 QDeclarativeContext *QDeclarativeEngine::rootContext() const
717 {
718     Q_D(const QDeclarativeEngine);
719     return d->rootContext;
720 }
721
722 /*!
723   Sets the \a factory to use for creating QNetworkAccessManager(s).
724
725   QNetworkAccessManager is used for all network access by QML.  By
726   implementing a factory it is possible to create custom
727   QNetworkAccessManager with specialized caching, proxy and cookie
728   support.
729
730   The factory must be set before executing the engine.
731 */
732 void QDeclarativeEngine::setNetworkAccessManagerFactory(QDeclarativeNetworkAccessManagerFactory *factory)
733 {
734     Q_D(QDeclarativeEngine);
735     QMutexLocker locker(&d->mutex);
736     d->networkAccessManagerFactory = factory;
737 }
738
739 /*!
740   Returns the current QDeclarativeNetworkAccessManagerFactory.
741
742   \sa setNetworkAccessManagerFactory()
743 */
744 QDeclarativeNetworkAccessManagerFactory *QDeclarativeEngine::networkAccessManagerFactory() const
745 {
746     Q_D(const QDeclarativeEngine);
747     return d->networkAccessManagerFactory;
748 }
749
750 QNetworkAccessManager *QDeclarativeEnginePrivate::createNetworkAccessManager(QObject *parent) const
751 {
752     QMutexLocker locker(&mutex);
753     QNetworkAccessManager *nam;
754     if (networkAccessManagerFactory) {
755         nam = networkAccessManagerFactory->create(parent);
756     } else {
757         nam = new QNetworkAccessManager(parent);
758     }
759
760     return nam;
761 }
762
763 QNetworkAccessManager *QDeclarativeEnginePrivate::getNetworkAccessManager() const
764 {
765     Q_Q(const QDeclarativeEngine);
766     if (!networkAccessManager)
767         networkAccessManager = createNetworkAccessManager(const_cast<QDeclarativeEngine*>(q));
768     return networkAccessManager;
769 }
770
771 /*!
772   Returns a common QNetworkAccessManager which can be used by any QML
773   element instantiated by this engine.
774
775   If a QDeclarativeNetworkAccessManagerFactory has been set and a
776   QNetworkAccessManager has not yet been created, the
777   QDeclarativeNetworkAccessManagerFactory will be used to create the
778   QNetworkAccessManager; otherwise the returned QNetworkAccessManager
779   will have no proxy or cache set.
780
781   \sa setNetworkAccessManagerFactory()
782 */
783 QNetworkAccessManager *QDeclarativeEngine::networkAccessManager() const
784 {
785     Q_D(const QDeclarativeEngine);
786     return d->getNetworkAccessManager();
787 }
788
789 /*!
790
791   Sets the \a provider to use for images requested via the \e
792   image: url scheme, with host \a providerId. The QDeclarativeEngine
793   takes ownership of \a provider.
794
795   Image providers enable support for pixmap and threaded image
796   requests. See the QDeclarativeImageProvider documentation for details on
797   implementing and using image providers.
798
799   All required image providers should be added to the engine before any
800   QML sources files are loaded.
801
802   Note that images loaded from a QDeclarativeImageProvider are cached
803   by QPixmapCache, similar to any image loaded by QML.
804
805   \sa removeImageProvider()
806 */
807 void QDeclarativeEngine::addImageProvider(const QString &providerId, QDeclarativeImageProvider *provider)
808 {
809     Q_D(QDeclarativeEngine);
810     QMutexLocker locker(&d->mutex);
811     d->imageProviders.insert(providerId.toLower(), QSharedPointer<QDeclarativeImageProvider>(provider));
812 }
813
814 /*!
815   Returns the QDeclarativeImageProvider set for \a providerId.
816 */
817 QDeclarativeImageProvider *QDeclarativeEngine::imageProvider(const QString &providerId) const
818 {
819     Q_D(const QDeclarativeEngine);
820     QMutexLocker locker(&d->mutex);
821     return d->imageProviders.value(providerId).data();
822 }
823
824 /*!
825   Removes the QDeclarativeImageProvider for \a providerId.
826
827   Returns the provider if it was found; otherwise returns 0.
828
829   \sa addImageProvider()
830 */
831 void QDeclarativeEngine::removeImageProvider(const QString &providerId)
832 {
833     Q_D(QDeclarativeEngine);
834     QMutexLocker locker(&d->mutex);
835     d->imageProviders.take(providerId);
836 }
837
838 QDeclarativeImageProvider::ImageType QDeclarativeEnginePrivate::getImageProviderType(const QUrl &url)
839 {
840     QMutexLocker locker(&mutex);
841     QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
842     locker.unlock();
843     if (provider)
844         return provider->imageType();
845     return QDeclarativeImageProvider::Invalid;
846 }
847
848 QSGTexture *QDeclarativeEnginePrivate::getTextureFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
849 {
850     QMutexLocker locker(&mutex);
851     QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
852     locker.unlock();
853     if (provider) {
854         QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
855         return provider->requestTexture(imageId, size, req_size);
856     }
857     return 0;
858 }
859
860 QImage QDeclarativeEnginePrivate::getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
861 {
862     QMutexLocker locker(&mutex);
863     QImage image;
864     QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
865     locker.unlock();
866     if (provider) {
867         QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
868         image = provider->requestImage(imageId, size, req_size);
869     }
870     return image;
871 }
872
873 QPixmap QDeclarativeEnginePrivate::getPixmapFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
874 {
875     QMutexLocker locker(&mutex);
876     QPixmap pixmap;
877     QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
878     locker.unlock();
879     if (provider) {
880         QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
881         pixmap = provider->requestPixmap(imageId, size, req_size);
882     }
883     return pixmap;
884 }
885
886 /*!
887   Return the base URL for this engine.  The base URL is only used to
888   resolve components when a relative URL is passed to the
889   QDeclarativeComponent constructor.
890
891   If a base URL has not been explicitly set, this method returns the
892   application's current working directory.
893
894   \sa setBaseUrl()
895 */
896 QUrl QDeclarativeEngine::baseUrl() const
897 {
898     Q_D(const QDeclarativeEngine);
899     if (d->baseUrl.isEmpty()) {
900         return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
901     } else {
902         return d->baseUrl;
903     }
904 }
905
906 /*!
907   Set the  base URL for this engine to \a url.
908
909   \sa baseUrl()
910 */
911 void QDeclarativeEngine::setBaseUrl(const QUrl &url)
912 {
913     Q_D(QDeclarativeEngine);
914     d->baseUrl = url;
915 }
916
917 /*!
918   Returns true if warning messages will be output to stderr in addition
919   to being emitted by the warnings() signal, otherwise false.
920
921   The default value is true.
922 */
923 bool QDeclarativeEngine::outputWarningsToStandardError() const
924 {
925     Q_D(const QDeclarativeEngine);
926     return d->outputWarningsToStdErr;
927 }
928
929 /*!
930   Set whether warning messages will be output to stderr to \a enabled.
931
932   If \a enabled is true, any warning messages generated by QML will be
933   output to stderr and emitted by the warnings() signal.  If \a enabled
934   is false, on the warnings() signal will be emitted.  This allows
935   applications to handle warning output themselves.
936
937   The default value is true.
938 */
939 void QDeclarativeEngine::setOutputWarningsToStandardError(bool enabled)
940 {
941     Q_D(QDeclarativeEngine);
942     d->outputWarningsToStdErr = enabled;
943 }
944
945 /*!
946   Returns the QDeclarativeContext for the \a object, or 0 if no
947   context has been set.
948
949   When the QDeclarativeEngine instantiates a QObject, the context is
950   set automatically.
951   */
952 QDeclarativeContext *QDeclarativeEngine::contextForObject(const QObject *object)
953 {
954     if(!object)
955         return 0;
956
957     QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
958
959     QDeclarativeData *data =
960         static_cast<QDeclarativeData *>(priv->declarativeData);
961
962     if (!data)
963         return 0;
964     else if (data->outerContext)
965         return data->outerContext->asQDeclarativeContext();
966     else
967         return 0;
968 }
969
970 /*!
971   Sets the QDeclarativeContext for the \a object to \a context.
972   If the \a object already has a context, a warning is
973   output, but the context is not changed.
974
975   When the QDeclarativeEngine instantiates a QObject, the context is
976   set automatically.
977  */
978 void QDeclarativeEngine::setContextForObject(QObject *object, QDeclarativeContext *context)
979 {
980     if (!object || !context)
981         return;
982
983     QDeclarativeData *data = QDeclarativeData::get(object, true);
984     if (data->context) {
985         qWarning("QDeclarativeEngine::setContextForObject(): Object already has a QDeclarativeContext");
986         return;
987     }
988
989     QDeclarativeContextData *contextData = QDeclarativeContextData::get(context);
990     contextData->addObject(object);
991 }
992
993 /*!
994   \enum QDeclarativeEngine::ObjectOwnership
995
996   Ownership controls whether or not QML automatically destroys the
997   QObject when the object is garbage collected by the JavaScript
998   engine.  The two ownership options are:
999
1000   \value CppOwnership The object is owned by C++ code, and will
1001   never be deleted by QML.  The JavaScript destroy() method cannot be
1002   used on objects with CppOwnership.  This option is similar to
1003   QScriptEngine::QtOwnership.
1004
1005   \value JavaScriptOwnership The object is owned by JavaScript.
1006   When the object is returned to QML as the return value of a method
1007   call or property access, QML will delete the object if there are no
1008   remaining JavaScript references to it and it has no
1009   QObject::parent().  This option is similar to
1010   QScriptEngine::ScriptOwnership.
1011
1012   Generally an application doesn't need to set an object's ownership
1013   explicitly.  QML uses a heuristic to set the default object
1014   ownership.  By default, an object that is created by QML has
1015   JavaScriptOwnership.  The exception to this are the root objects
1016   created by calling QDeclarativeCompnent::create() or
1017   QDeclarativeComponent::beginCreate() which have CppOwnership by
1018   default.  The ownership of these root-level objects is considered to
1019   have been transferred to the C++ caller.
1020
1021   Objects not-created by QML have CppOwnership by default.  The
1022   exception to this is objects returned from a C++ method call.  The
1023   ownership of these objects is passed to JavaScript.
1024
1025   Calling setObjectOwnership() overrides the default ownership
1026   heuristic used by QML.
1027 */
1028
1029 /*!
1030   Sets the \a ownership of \a object.
1031 */
1032 void QDeclarativeEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
1033 {
1034     if (!object)
1035         return;
1036
1037     QDeclarativeData *ddata = QDeclarativeData::get(object, true);
1038     if (!ddata)
1039         return;
1040
1041     ddata->indestructible = (ownership == CppOwnership)?true:false;
1042     ddata->explicitIndestructibleSet = true;
1043 }
1044
1045 /*!
1046   Returns the ownership of \a object.
1047 */
1048 QDeclarativeEngine::ObjectOwnership QDeclarativeEngine::objectOwnership(QObject *object)
1049 {
1050     if (!object)
1051         return CppOwnership;
1052
1053     QDeclarativeData *ddata = QDeclarativeData::get(object, false);
1054     if (!ddata)
1055         return CppOwnership;
1056     else
1057         return ddata->indestructible?CppOwnership:JavaScriptOwnership;
1058 }
1059
1060 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
1061 {
1062     QDeclarativeData *data = QDeclarativeData::get(object);
1063
1064     if (data && data->deferredComponent) {
1065         if (QDeclarativeDebugService::isDebuggingEnabled()) {
1066             QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Creating);
1067             QDeclarativeType *type = QDeclarativeMetaType::qmlType(object->metaObject());
1068             QString typeName = type ? QLatin1String(type->qmlTypeName()) : QString::fromLatin1(object->metaObject()->className());
1069             QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Creating, typeName);
1070             if (data->outerContext)
1071                 QDeclarativeDebugTrace::rangeLocation(QDeclarativeDebugTrace::Creating, data->outerContext->url, data->lineNumber);
1072         }
1073         QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(data->context->engine);
1074
1075         QDeclarativeComponentPrivate::ConstructionState state;
1076         QDeclarativeComponentPrivate::beginDeferred(ep, object, &state);
1077
1078         data->deferredComponent->release();
1079         data->deferredComponent = 0;
1080
1081         QDeclarativeComponentPrivate::complete(ep, &state);
1082         QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Creating);
1083     }
1084 }
1085
1086 QDeclarativeContext *qmlContext(const QObject *obj)
1087 {
1088     return QDeclarativeEngine::contextForObject(obj);
1089 }
1090
1091 QDeclarativeEngine *qmlEngine(const QObject *obj)
1092 {
1093     QDeclarativeContext *context = QDeclarativeEngine::contextForObject(obj);
1094     return context?context->engine():0;
1095 }
1096
1097 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1098 {
1099     QDeclarativeData *data = QDeclarativeData::get(object);
1100     if (!data)
1101         return 0; // Attached properties are only on objects created by QML
1102
1103     QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1104     if (rv || !create)
1105         return rv;
1106
1107     QDeclarativeAttachedPropertiesFunc pf = QDeclarativeMetaType::attachedPropertiesFuncById(id);
1108     if (!pf)
1109         return 0;
1110
1111     rv = pf(const_cast<QObject *>(object));
1112
1113     if (rv)
1114         data->attachedProperties()->insert(id, rv);
1115
1116     return rv;
1117 }
1118
1119 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1120                                      const QMetaObject *attachedMetaObject, bool create)
1121 {
1122     if (*idCache == -1)
1123         *idCache = QDeclarativeMetaType::attachedPropertiesFuncId(attachedMetaObject);
1124
1125     if (*idCache == -1 || !object)
1126         return 0;
1127
1128     return qmlAttachedPropertiesObjectById(*idCache, object, create);
1129 }
1130
1131 class QDeclarativeDataExtended {
1132 public:
1133     QDeclarativeDataExtended();
1134     ~QDeclarativeDataExtended();
1135
1136     QHash<int, QObject *> attachedProperties;
1137     QDeclarativeNotifier objectNameNotifier;
1138 };
1139
1140 QDeclarativeDataExtended::QDeclarativeDataExtended()
1141 {
1142 }
1143
1144 QDeclarativeDataExtended::~QDeclarativeDataExtended()
1145 {
1146 }
1147
1148 QDeclarativeNotifier *QDeclarativeData::objectNameNotifier() const
1149 {
1150     if (!extendedData) extendedData = new QDeclarativeDataExtended;
1151     return &extendedData->objectNameNotifier;
1152 }
1153
1154 QHash<int, QObject *> *QDeclarativeData::attachedProperties() const
1155 {
1156     if (!extendedData) extendedData = new QDeclarativeDataExtended;
1157     return &extendedData->attachedProperties;
1158 }
1159
1160 void QDeclarativeData::destroyed(QObject *object)
1161 {
1162     if (deferredComponent)
1163         deferredComponent->release();
1164
1165     if (nextContextObject)
1166         nextContextObject->prevContextObject = prevContextObject;
1167     if (prevContextObject)
1168         *prevContextObject = nextContextObject;
1169
1170     QDeclarativeAbstractBinding *binding = bindings;
1171     while (binding) {
1172         QDeclarativeAbstractBinding *next = binding->m_nextBinding;
1173         binding->m_prevBinding = 0;
1174         binding->m_nextBinding = 0;
1175         binding->destroy();
1176         binding = next;
1177     }
1178
1179     if (bindingBits)
1180         free(bindingBits);
1181
1182     if (propertyCache)
1183         propertyCache->release();
1184
1185     if (ownContext && context)
1186         context->destroy();
1187
1188     while (guards) {
1189         QDeclarativeGuard<QObject> *guard = guards;
1190         *guard = (QObject *)0;
1191         guard->objectDestroyed(object);
1192     }
1193
1194     if (scriptValue)
1195         delete scriptValue;
1196
1197     if (extendedData)
1198         delete extendedData;
1199
1200     if (ownMemory)
1201         delete this;
1202 }
1203
1204 void QDeclarativeData::parentChanged(QObject *, QObject *parent)
1205 {
1206     if (!parent && scriptValue) { delete scriptValue; scriptValue = 0; }
1207 }
1208
1209 void QDeclarativeData::objectNameChanged(QObject *)
1210 {
1211     if (extendedData) objectNameNotifier()->notify();
1212 }
1213
1214 bool QDeclarativeData::hasBindingBit(int bit) const
1215 {
1216     if (bindingBitsSize > bit)
1217         return bindingBits[bit / 32] & (1 << (bit % 32));
1218     else
1219         return false;
1220 }
1221
1222 void QDeclarativeData::clearBindingBit(int bit)
1223 {
1224     if (bindingBitsSize > bit)
1225         bindingBits[bit / 32] &= ~(1 << (bit % 32));
1226 }
1227
1228 void QDeclarativeData::setBindingBit(QObject *obj, int bit)
1229 {
1230     if (bindingBitsSize <= bit) {
1231         int props = obj->metaObject()->propertyCount();
1232         Q_ASSERT(bit < props);
1233
1234         int arraySize = (props + 31) / 32;
1235         int oldArraySize = bindingBitsSize / 32;
1236
1237         bindingBits = (quint32 *)realloc(bindingBits,
1238                                          arraySize * sizeof(quint32));
1239
1240         memset(bindingBits + oldArraySize,
1241                0x00,
1242                sizeof(quint32) * (arraySize - oldArraySize));
1243
1244         bindingBitsSize = arraySize * 32;
1245     }
1246
1247     bindingBits[bit / 32] |= (1 << (bit % 32));
1248 }
1249
1250 /*!
1251     Creates a QScriptValue allowing you to use \a object in QML script.
1252     \a engine is the QDeclarativeEngine it is to be created in.
1253
1254     The QScriptValue returned is a QtScript Object, not a QtScript QObject, due
1255     to the special needs of QML requiring more functionality than a standard
1256     QtScript QObject.
1257 */
1258 QScriptValue QDeclarativeEnginePrivate::qmlScriptObject(QObject* object,
1259                                                QDeclarativeEngine* engine)
1260 {
1261     QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine);
1262     return enginePriv->objectClass->newQObject(object);
1263 }
1264
1265 /*!
1266     Returns the QDeclarativeContext for the executing QScript \a ctxt.
1267 */
1268 QDeclarativeContextData *QDeclarativeEnginePrivate::getContext(QScriptContext *ctxt)
1269 {
1270     QScriptValue scopeNode = QScriptDeclarativeClass::scopeChainValue(ctxt, -3);
1271     Q_ASSERT(scopeNode.isValid());
1272     Q_ASSERT(QScriptDeclarativeClass::scriptClass(scopeNode) == contextClass);
1273     return contextClass->contextFromValue(scopeNode);
1274 }
1275
1276 /*!
1277     Returns the QUrl associated with the script \a ctxt for the case that there is
1278     no QDeclarativeContext.
1279 */
1280 QUrl QDeclarativeEnginePrivate::getUrl(QScriptContext *ctxt)
1281 {
1282     QScriptValue scopeNode = QScriptDeclarativeClass::scopeChainValue(ctxt, -3);
1283     Q_ASSERT(scopeNode.isValid());
1284     Q_ASSERT(QScriptDeclarativeClass::scriptClass(scopeNode) == contextClass);
1285     return contextClass->urlFromValue(scopeNode);
1286 }
1287
1288 QString QDeclarativeEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
1289 {
1290     if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
1291         if (url.authority().isEmpty())
1292             return QLatin1Char(':') + url.path();
1293         return QString();
1294     }
1295     return url.toLocalFile();
1296 }
1297
1298 /*!
1299 \qmlmethod object Qt::createComponent(url)
1300
1301 Returns a \l Component object created using the QML file at the specified \a url,
1302 or \c null if an empty string was given.
1303
1304 The returned component's \l Component::status property indicates whether the
1305 component was successfully created. If the status is \c Component.Error,
1306 see \l Component::errorString() for an error description.
1307
1308 Call \l {Component::createObject()}{Component.createObject()} on the returned
1309 component to create an object instance of the component.
1310
1311 For example:
1312
1313 \snippet doc/src/snippets/declarative/createComponent-simple.qml 0
1314
1315 See \l {Dynamic Object Management in QML} for more information on using this function.
1316
1317 To create a QML object from an arbitrary string of QML (instead of a file),
1318 use \l{QML:Qt::createQmlObject()}{Qt.createQmlObject()}.
1319 */
1320
1321 QScriptValue QDeclarativeEnginePrivate::createComponent(QScriptContext *ctxt, QScriptEngine *engine)
1322 {
1323     QDeclarativeEnginePrivate *activeEnginePriv =
1324         static_cast<QDeclarativeScriptEngine*>(engine)->p;
1325     QDeclarativeEngine* activeEngine = activeEnginePriv->q_func();
1326
1327     if(ctxt->argumentCount() != 1) {
1328         return ctxt->throwError(QLatin1String("Qt.createComponent(): Invalid arguments"));
1329     } else {
1330
1331         QString arg = ctxt->argument(0).toString();
1332         if (arg.isEmpty())
1333             return engine->nullValue();
1334         QUrl url = QDeclarativeScriptEngine::get(engine)->resolvedUrl(ctxt, QUrl(arg));
1335         QDeclarativeContextData* context = activeEnginePriv->getContext(ctxt);
1336         QDeclarativeComponent *c = new QDeclarativeComponent(activeEngine, url, activeEngine);
1337         QDeclarativeComponentPrivate::get(c)->creationContext = context;
1338         QDeclarativeData::get(c, true)->setImplicitDestructible();
1339         return activeEnginePriv->objectClass->newQObject(c, qMetaTypeId<QDeclarativeComponent*>());
1340     }
1341 }
1342
1343 /*!
1344 \qmlmethod object Qt::createQmlObject(string qml, object parent, string filepath)
1345
1346 Returns a new object created from the given \a string of QML which will have the specified \a parent,
1347 or \c null if there was an error in creating the object.
1348
1349 If \a filepath is specified, it will be used for error reporting for the created object.
1350
1351 Example (where \c parentItem is the id of an existing QML item):
1352
1353 \snippet doc/src/snippets/declarative/createQmlObject.qml 0
1354
1355 In the case of an error, a QtScript Error object is thrown. This object has an additional property,
1356 \c qmlErrors, which is an array of the errors encountered.
1357 Each object in this array has the members \c lineNumber, \c columnNumber, \c fileName and \c message.
1358 For example, if the above snippet had misspelled color as 'colro' then the array would contain an object like the following:
1359 { "lineNumber" : 1, "columnNumber" : 32, "fileName" : "dynamicSnippet1", "message" : "Cannot assign to non-existent property \"colro\""}.
1360
1361 Note that this function returns immediately, and therefore may not work if
1362 the \a qml string loads new components (that is, external QML files that have not yet been loaded).
1363 If this is the case, consider using \l{QML:Qt::createComponent()}{Qt.createComponent()} instead.
1364
1365 See \l {Dynamic Object Management in QML} for more information on using this function.
1366 */
1367
1368 QScriptValue QDeclarativeEnginePrivate::createQmlObject(QScriptContext *ctxt, QScriptEngine *engine)
1369 {
1370     QDeclarativeEnginePrivate *activeEnginePriv =
1371         static_cast<QDeclarativeScriptEngine*>(engine)->p;
1372     QDeclarativeEngine* activeEngine = activeEnginePriv->q_func();
1373
1374     if(ctxt->argumentCount() < 2 || ctxt->argumentCount() > 3)
1375         return ctxt->throwError(QLatin1String("Qt.createQmlObject(): Invalid arguments"));
1376
1377     QDeclarativeContextData* context = activeEnginePriv->getContext(ctxt);
1378     Q_ASSERT(context);
1379
1380     QString qml = ctxt->argument(0).toString();
1381     if (qml.isEmpty())
1382         return engine->nullValue();
1383
1384     QUrl url;
1385     if(ctxt->argumentCount() > 2)
1386         url = QUrl(ctxt->argument(2).toString());
1387     else
1388         url = QUrl(QLatin1String("inline"));
1389
1390     if (url.isValid() && url.isRelative())
1391         url = context->resolvedUrl(url);
1392
1393     QObject *parentArg = activeEnginePriv->objectClass->toQObject(ctxt->argument(1));
1394     if(!parentArg)
1395         return ctxt->throwError(QLatin1String("Qt.createQmlObject(): Missing parent object"));
1396
1397     QDeclarativeComponent component(activeEngine);
1398     component.setData(qml.toUtf8(), url);
1399
1400     if(component.isError()) {
1401         QList<QDeclarativeError> errors = component.errors();
1402         QString errstr = QLatin1String("Qt.createQmlObject() failed to create object: ");
1403         QScriptValue arr = ctxt->engine()->newArray(errors.length());
1404         int i = 0;
1405         foreach (const QDeclarativeError &error, errors){
1406             errstr += QLatin1String("\n    ") + error.toString();
1407             QScriptValue qmlErrObject = ctxt->engine()->newObject();
1408             qmlErrObject.setProperty(QLatin1String("lineNumber"), QScriptValue(error.line()));
1409             qmlErrObject.setProperty(QLatin1String("columnNumber"), QScriptValue(error.column()));
1410             qmlErrObject.setProperty(QLatin1String("fileName"), QScriptValue(error.url().toString()));
1411             qmlErrObject.setProperty(QLatin1String("message"), QScriptValue(error.description()));
1412             arr.setProperty(i++, qmlErrObject);
1413         }
1414         QScriptValue err = ctxt->throwError(errstr);
1415         err.setProperty(QLatin1String("qmlErrors"),arr);
1416         return err;
1417     }
1418
1419     if (!component.isReady())
1420         return ctxt->throwError(QLatin1String("Qt.createQmlObject(): Component is not ready"));
1421
1422     QObject *obj = component.beginCreate(context->asQDeclarativeContext());
1423     if(obj)
1424         QDeclarativeData::get(obj, true)->setImplicitDestructible();
1425     component.completeCreate();
1426
1427     if(component.isError()) {
1428         QList<QDeclarativeError> errors = component.errors();
1429         QString errstr = QLatin1String("Qt.createQmlObject() failed to create object: ");
1430         QScriptValue arr = ctxt->engine()->newArray(errors.length());
1431         int i = 0;
1432         foreach (const QDeclarativeError &error, errors){
1433             errstr += QLatin1String("\n    ") + error.toString();
1434             QScriptValue qmlErrObject = ctxt->engine()->newObject();
1435             qmlErrObject.setProperty(QLatin1String("lineNumber"), QScriptValue(error.line()));
1436             qmlErrObject.setProperty(QLatin1String("columnNumber"), QScriptValue(error.column()));
1437             qmlErrObject.setProperty(QLatin1String("fileName"), QScriptValue(error.url().toString()));
1438             qmlErrObject.setProperty(QLatin1String("message"), QScriptValue(error.description()));
1439             arr.setProperty(i++, qmlErrObject);
1440         }
1441         QScriptValue err = ctxt->throwError(errstr);
1442         err.setProperty(QLatin1String("qmlErrors"),arr);
1443         return err;
1444     }
1445
1446     Q_ASSERT(obj);
1447
1448     obj->setParent(parentArg);
1449
1450     QList<QDeclarativePrivate::AutoParentFunction> functions = QDeclarativeMetaType::parentFunctions();
1451     for (int ii = 0; ii < functions.count(); ++ii) {
1452         if (QDeclarativePrivate::Parented == functions.at(ii)(obj, parentArg))
1453             break;
1454     }
1455
1456     QDeclarativeData::get(obj, true)->setImplicitDestructible();
1457     return activeEnginePriv->objectClass->newQObject(obj, QMetaType::QObjectStar);
1458 }
1459
1460 /*!
1461 \qmlmethod bool Qt::isQtObject(object)
1462 Returns true if \c object is a valid reference to a Qt or QML object, otherwise false.
1463 */
1464 QScriptValue QDeclarativeEnginePrivate::isQtObject(QScriptContext *ctxt, QScriptEngine *engine)
1465 {
1466     if (ctxt->argumentCount() == 0)
1467         return QScriptValue(engine, false);
1468
1469     return QScriptValue(engine, 0 != ctxt->argument(0).toQObject());
1470 }
1471
1472 /*!
1473 \qmlmethod Qt::vector3d(real x, real y, real z)
1474 Returns a Vector3D with the specified \c x, \c y and \c z.
1475 */
1476 QScriptValue QDeclarativeEnginePrivate::vector3d(QScriptContext *ctxt, QScriptEngine *engine)
1477 {
1478     if(ctxt->argumentCount() != 3)
1479         return ctxt->throwError(QLatin1String("Qt.vector(): Invalid arguments"));
1480     qsreal x = ctxt->argument(0).toNumber();
1481     qsreal y = ctxt->argument(1).toNumber();
1482     qsreal z = ctxt->argument(2).toNumber();
1483     return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QVector3D(x, y, z)));
1484 }
1485
1486 /*!
1487 \qmlmethod string Qt::formatDate(datetime date, variant format)
1488
1489 Returns a string representation of \c date, optionally formatted according
1490 to \c format.
1491
1492 The \a date parameter may be a JavaScript \c Date object, a \l{date}{date}
1493 property, a QDate, or QDateTime value. The \a format parameter may be any of
1494 the possible format values as described for
1495 \l{QML:Qt::formatDateTime()}{Qt.formatDateTime()}.
1496
1497 If \a format is not specified, \a date is formatted using
1498 \l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}.
1499 */
1500 #ifndef QT_NO_DATESTRING
1501 QScriptValue QDeclarativeEnginePrivate::formatDate(QScriptContext*ctxt, QScriptEngine*engine)
1502 {
1503     int argCount = ctxt->argumentCount();
1504     if(argCount == 0 || argCount > 2)
1505         return ctxt->throwError(QLatin1String("Qt.formatDate(): Invalid arguments"));
1506
1507     QDate date = ctxt->argument(0).toDateTime().date();
1508     Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
1509     if (argCount == 2) {
1510         QScriptValue formatArg = ctxt->argument(1);
1511         if (formatArg.isString()) {
1512             QString format = formatArg.toString();
1513             return engine->newVariant(QVariant::fromValue(date.toString(format)));
1514         } else if (formatArg.isNumber()) {
1515             enumFormat = Qt::DateFormat(formatArg.toUInt32());
1516         } else {
1517             return ctxt->throwError(QLatin1String("Qt.formatDate(): Invalid date format"));
1518         }
1519     }
1520     return engine->newVariant(QVariant::fromValue(date.toString(enumFormat)));
1521 }
1522
1523 /*!
1524 \qmlmethod string Qt::formatTime(datetime time, variant format)
1525
1526 Returns a string representation of \c time, optionally formatted according to
1527 \c format.
1528
1529 The \a time parameter may be a JavaScript \c Date object, a QTime, or QDateTime
1530 value. The \a format parameter may be any of the possible format values as
1531 described for \l{QML:Qt::formatDateTime()}{Qt.formatDateTime()}.
1532
1533 If \a format is not specified, \a time is formatted using
1534 \l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}.
1535 */
1536 QScriptValue QDeclarativeEnginePrivate::formatTime(QScriptContext*ctxt, QScriptEngine*engine)
1537 {
1538     int argCount = ctxt->argumentCount();
1539     if(argCount == 0 || argCount > 2)
1540         return ctxt->throwError(QLatin1String("Qt.formatTime(): Invalid arguments"));
1541
1542     QTime time;
1543     QScriptValue sv = ctxt->argument(0);
1544     if (sv.isDate())
1545         time = sv.toDateTime().time();
1546     else if (sv.toVariant().type() == QVariant::Time)
1547         time = sv.toVariant().toTime();
1548
1549     Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
1550     if (argCount == 2) {
1551         QScriptValue formatArg = ctxt->argument(1);
1552         if (formatArg.isString()) {
1553             QString format = formatArg.toString();
1554             return engine->newVariant(QVariant::fromValue(time.toString(format)));
1555         } else if (formatArg.isNumber()) {
1556             enumFormat = Qt::DateFormat(formatArg.toUInt32());
1557         } else {
1558             return ctxt->throwError(QLatin1String("Qt.formatTime(): Invalid time format"));
1559         }
1560     }
1561     return engine->newVariant(QVariant::fromValue(time.toString(enumFormat)));
1562 }
1563
1564 /*!
1565 \qmlmethod string Qt::formatDateTime(datetime dateTime, variant format)
1566
1567 Returns a string representation of \c datetime, optionally formatted according to
1568 \c format.
1569
1570 The \a date parameter may be a JavaScript \c Date object, a \l{date}{date}
1571 property, a QDate, QTime, or QDateTime value.
1572
1573 If \a format is not provided, \a dateTime is formatted using
1574 \l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}. Otherwise,
1575 \a format should be either.
1576
1577 \list
1578 \o One of the Qt::DateFormat enumeration values, such as
1579    \c Qt.DefaultLocaleShortDate or \c Qt.ISODate
1580 \o A string that specifies the format of the returned string, as detailed below.
1581 \endlist
1582
1583 If \a format specifies a format string, it should use the following expressions
1584 to specify the date:
1585
1586     \table
1587     \header \i Expression \i Output
1588     \row \i d \i the day as number without a leading zero (1 to 31)
1589     \row \i dd \i the day as number with a leading zero (01 to 31)
1590     \row \i ddd
1591             \i the abbreviated localized day name (e.g. 'Mon' to 'Sun').
1592             Uses QDate::shortDayName().
1593     \row \i dddd
1594             \i the long localized day name (e.g. 'Monday' to 'Qt::Sunday').
1595             Uses QDate::longDayName().
1596     \row \i M \i the month as number without a leading zero (1-12)
1597     \row \i MM \i the month as number with a leading zero (01-12)
1598     \row \i MMM
1599             \i the abbreviated localized month name (e.g. 'Jan' to 'Dec').
1600             Uses QDate::shortMonthName().
1601     \row \i MMMM
1602             \i the long localized month name (e.g. 'January' to 'December').
1603             Uses QDate::longMonthName().
1604     \row \i yy \i the year as two digit number (00-99)
1605     \row \i yyyy \i the year as four digit number
1606     \endtable
1607
1608 In addition the following expressions can be used to specify the time:
1609
1610     \table
1611     \header \i Expression \i Output
1612     \row \i h
1613          \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
1614     \row \i hh
1615          \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
1616     \row \i m \i the minute without a leading zero (0 to 59)
1617     \row \i mm \i the minute with a leading zero (00 to 59)
1618     \row \i s \i the second without a leading zero (0 to 59)
1619     \row \i ss \i the second with a leading zero (00 to 59)
1620     \row \i z \i the milliseconds without leading zeroes (0 to 999)
1621     \row \i zzz \i the milliseconds with leading zeroes (000 to 999)
1622     \row \i AP
1623             \i use AM/PM display. \e AP will be replaced by either "AM" or "PM".
1624     \row \i ap
1625             \i use am/pm display. \e ap will be replaced by either "am" or "pm".
1626     \endtable
1627
1628     All other input characters will be ignored. Any sequence of characters that
1629     are enclosed in single quotes will be treated as text and not be used as an
1630     expression. Two consecutive single quotes ("''") are replaced by a single quote
1631     in the output.
1632
1633 For example, if the following date/time value was specified:
1634
1635     \code
1636     // 21 May 2001 14:13:09
1637     var dateTime = new Date(2001, 5, 21, 14, 13, 09)
1638     \endcode
1639
1640 This \a dateTime value could be passed to \c Qt.formatDateTime(),
1641 \l {QML:Qt::formatDate()}{Qt.formatDate()} or \l {QML:Qt::formatTime()}{Qt.formatTime()}
1642 with the \a format values below to produce the following results:
1643
1644     \table
1645     \header \i Format \i Result
1646     \row \i "dd.MM.yyyy"      \i 21.05.2001
1647     \row \i "ddd MMMM d yy"   \i Tue May 21 01
1648     \row \i "hh:mm:ss.zzz"    \i 14:13:09.042
1649     \row \i "h:m:s ap"        \i 2:13:9 pm
1650     \endtable
1651 */
1652 QScriptValue QDeclarativeEnginePrivate::formatDateTime(QScriptContext*ctxt, QScriptEngine*engine)
1653 {
1654     int argCount = ctxt->argumentCount();
1655     if(argCount == 0 || argCount > 2)
1656         return ctxt->throwError(QLatin1String("Qt.formatDateTime(): Invalid arguments"));
1657
1658     QDateTime date = ctxt->argument(0).toDateTime();
1659     Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
1660     if (argCount == 2) {
1661         QScriptValue formatArg = ctxt->argument(1);
1662         if (formatArg.isString()) {
1663             QString format = formatArg.toString();
1664             return engine->newVariant(QVariant::fromValue(date.toString(format)));
1665         } else if (formatArg.isNumber()) {
1666             enumFormat = Qt::DateFormat(formatArg.toUInt32());
1667         } else {
1668             return ctxt->throwError(QLatin1String("Qt.formatDateTime(): Invalid datetime format"));
1669         }
1670     }
1671     return engine->newVariant(QVariant::fromValue(date.toString(enumFormat)));
1672 }
1673 #endif // QT_NO_DATESTRING
1674
1675 /*!
1676 \qmlmethod color Qt::rgba(real red, real green, real blue, real alpha)
1677
1678 Returns a color with the specified \c red, \c green, \c blue and \c alpha components.
1679 All components should be in the range 0-1 inclusive.
1680 */
1681 QScriptValue QDeclarativeEnginePrivate::rgba(QScriptContext *ctxt, QScriptEngine *engine)
1682 {
1683     int argCount = ctxt->argumentCount();
1684     if(argCount < 3 || argCount > 4)
1685         return ctxt->throwError(QLatin1String("Qt.rgba(): Invalid arguments"));
1686     qsreal r = ctxt->argument(0).toNumber();
1687     qsreal g = ctxt->argument(1).toNumber();
1688     qsreal b = ctxt->argument(2).toNumber();
1689     qsreal a = (argCount == 4) ? ctxt->argument(3).toNumber() : 1;
1690
1691     if (r < 0.0) r=0.0;
1692     if (r > 1.0) r=1.0;
1693     if (g < 0.0) g=0.0;
1694     if (g > 1.0) g=1.0;
1695     if (b < 0.0) b=0.0;
1696     if (b > 1.0) b=1.0;
1697     if (a < 0.0) a=0.0;
1698     if (a > 1.0) a=1.0;
1699
1700     return engine->toScriptValue(QVariant::fromValue(QColor::fromRgbF(r, g, b, a)));
1701 }
1702
1703 /*!
1704 \qmlmethod color Qt::hsla(real hue, real saturation, real lightness, real alpha)
1705
1706 Returns a color with the specified \c hue, \c saturation, \c lightness and \c alpha components.
1707 All components should be in the range 0-1 inclusive.
1708 */
1709 QScriptValue QDeclarativeEnginePrivate::hsla(QScriptContext *ctxt, QScriptEngine *engine)
1710 {
1711     int argCount = ctxt->argumentCount();
1712     if(argCount < 3 || argCount > 4)
1713         return ctxt->throwError(QLatin1String("Qt.hsla(): Invalid arguments"));
1714     qsreal h = ctxt->argument(0).toNumber();
1715     qsreal s = ctxt->argument(1).toNumber();
1716     qsreal l = ctxt->argument(2).toNumber();
1717     qsreal a = (argCount == 4) ? ctxt->argument(3).toNumber() : 1;
1718
1719     if (h < 0.0) h=0.0;
1720     if (h > 1.0) h=1.0;
1721     if (s < 0.0) s=0.0;
1722     if (s > 1.0) s=1.0;
1723     if (l < 0.0) l=0.0;
1724     if (l > 1.0) l=1.0;
1725     if (a < 0.0) a=0.0;
1726     if (a > 1.0) a=1.0;
1727
1728     return engine->toScriptValue(QVariant::fromValue(QColor::fromHslF(h, s, l, a)));
1729 }
1730
1731 /*!
1732 \qmlmethod rect Qt::rect(int x, int y, int width, int height)
1733
1734 Returns a \c rect with the top-left corner at \c x, \c y and the specified \c width and \c height.
1735
1736 The returned object has \c x, \c y, \c width and \c height attributes with the given values.
1737 */
1738 QScriptValue QDeclarativeEnginePrivate::rect(QScriptContext *ctxt, QScriptEngine *engine)
1739 {
1740     if(ctxt->argumentCount() != 4)
1741         return ctxt->throwError(QLatin1String("Qt.rect(): Invalid arguments"));
1742
1743     qsreal x = ctxt->argument(0).toNumber();
1744     qsreal y = ctxt->argument(1).toNumber();
1745     qsreal w = ctxt->argument(2).toNumber();
1746     qsreal h = ctxt->argument(3).toNumber();
1747
1748     return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QRectF(x, y, w, h)));
1749 }
1750
1751 /*!
1752 \qmlmethod point Qt::point(int x, int y)
1753 Returns a Point with the specified \c x and \c y coordinates.
1754 */
1755 QScriptValue QDeclarativeEnginePrivate::point(QScriptContext *ctxt, QScriptEngine *engine)
1756 {
1757     if(ctxt->argumentCount() != 2)
1758         return ctxt->throwError(QLatin1String("Qt.point(): Invalid arguments"));
1759     qsreal x = ctxt->argument(0).toNumber();
1760     qsreal y = ctxt->argument(1).toNumber();
1761     return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QPointF(x, y)));
1762 }
1763
1764 /*!
1765 \qmlmethod Qt::size(int width, int height)
1766 Returns a Size with the specified \c width and \c height.
1767 */
1768 QScriptValue QDeclarativeEnginePrivate::size(QScriptContext *ctxt, QScriptEngine *engine)
1769 {
1770     if(ctxt->argumentCount() != 2)
1771         return ctxt->throwError(QLatin1String("Qt.size(): Invalid arguments"));
1772     qsreal w = ctxt->argument(0).toNumber();
1773     qsreal h = ctxt->argument(1).toNumber();
1774     return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QSizeF(w, h)));
1775 }
1776
1777 /*!
1778 \qmlmethod color Qt::lighter(color baseColor, real factor)
1779 Returns a color lighter than \c baseColor by the \c factor provided.
1780
1781 If the factor is greater than 1.0, this functions returns a lighter color.
1782 Setting factor to 1.5 returns a color that is 50% brighter. If the factor is less than 1.0,
1783 the return color is darker, but we recommend using the Qt.darker() function for this purpose.
1784 If the factor is 0 or negative, the return value is unspecified.
1785
1786 The function converts the current RGB color to HSV, multiplies the value (V) component
1787 by factor and converts the color back to RGB.
1788
1789 If \c factor is not supplied, returns a color 50% lighter than \c baseColor (factor 1.5).
1790 */
1791 QScriptValue QDeclarativeEnginePrivate::lighter(QScriptContext *ctxt, QScriptEngine *engine)
1792 {
1793     if(ctxt->argumentCount() != 1 && ctxt->argumentCount() != 2)
1794         return ctxt->throwError(QLatin1String("Qt.lighter(): Invalid arguments"));
1795     QVariant v = ctxt->argument(0).toVariant();
1796     QColor color;
1797     if (v.userType() == QVariant::Color)
1798         color = v.value<QColor>();
1799     else if (v.userType() == QVariant::String) {
1800         bool ok;
1801         color = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
1802         if (!ok)
1803             return engine->nullValue();
1804     } else
1805         return engine->nullValue();
1806     qsreal factor = 1.5;
1807     if (ctxt->argumentCount() == 2)
1808         factor = ctxt->argument(1).toNumber();
1809     color = color.lighter(int(qRound(factor*100.)));
1810     return engine->toScriptValue(QVariant::fromValue(color));
1811 }
1812
1813 /*!
1814 \qmlmethod color Qt::darker(color baseColor, real factor)
1815 Returns a color darker than \c baseColor by the \c factor provided.
1816
1817 If the factor is greater than 1.0, this function returns a darker color.
1818 Setting factor to 3.0 returns a color that has one-third the brightness.
1819 If the factor is less than 1.0, the return color is lighter, but we recommend using
1820 the Qt.lighter() function for this purpose. If the factor is 0 or negative, the return
1821 value is unspecified.
1822
1823 The function converts the current RGB color to HSV, divides the value (V) component
1824 by factor and converts the color back to RGB.
1825
1826 If \c factor is not supplied, returns a color 50% darker than \c baseColor (factor 2.0).
1827 */
1828 QScriptValue QDeclarativeEnginePrivate::darker(QScriptContext *ctxt, QScriptEngine *engine)
1829 {
1830     if(ctxt->argumentCount() != 1 && ctxt->argumentCount() != 2)
1831         return ctxt->throwError(QLatin1String("Qt.darker(): Invalid arguments"));
1832     QVariant v = ctxt->argument(0).toVariant();
1833     QColor color;
1834     if (v.userType() == QVariant::Color)
1835         color = v.value<QColor>();
1836     else if (v.userType() == QVariant::String) {
1837         bool ok;
1838         color = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
1839         if (!ok)
1840             return engine->nullValue();
1841     } else
1842         return engine->nullValue();
1843     qsreal factor = 2.0;
1844     if (ctxt->argumentCount() == 2)
1845         factor = ctxt->argument(1).toNumber();
1846     color = color.darker(int(qRound(factor*100.)));
1847     return engine->toScriptValue(QVariant::fromValue(color));
1848 }
1849
1850 /*!
1851 \qmlmethod bool Qt::openUrlExternally(url target)
1852 Attempts to open the specified \c target url in an external application, based on the user's desktop preferences. Returns true if it succeeds, and false otherwise.
1853 */
1854 QScriptValue QDeclarativeEnginePrivate::desktopOpenUrl(QScriptContext *ctxt, QScriptEngine *e)
1855 {
1856     if(ctxt->argumentCount() < 1)
1857         return QScriptValue(e, false);
1858     bool ret = false;
1859 #ifndef QT_NO_DESKTOPSERVICES
1860     ret = QDesktopServices::openUrl(QDeclarativeScriptEngine::get(e)->resolvedUrl(ctxt, QUrl(ctxt->argument(0).toString())));
1861 #endif
1862     return QScriptValue(e, ret);
1863 }
1864
1865 /*!
1866 \qmlmethod list<string> Qt::fontFamilies()
1867 Returns a list of the font families available to the application.
1868 */
1869
1870 QScriptValue QDeclarativeEnginePrivate::fontFamilies(QScriptContext *ctxt, QScriptEngine *e)
1871 {
1872     if(ctxt->argumentCount() != 0)
1873         return ctxt->throwError(QLatin1String("Qt.fontFamilies(): Invalid arguments"));
1874
1875     QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(e);
1876     QFontDatabase database;
1877     return p->scriptValueFromVariant(database.families());
1878 }
1879
1880 /*!
1881 \qmlmethod string Qt::md5(data)
1882 Returns a hex string of the md5 hash of \c data.
1883 */
1884 QScriptValue QDeclarativeEnginePrivate::md5(QScriptContext *ctxt, QScriptEngine *)
1885 {
1886     if (ctxt->argumentCount() != 1)
1887         return ctxt->throwError(QLatin1String("Qt.md5(): Invalid arguments"));
1888
1889     QByteArray data = ctxt->argument(0).toString().toUtf8();
1890     QByteArray result = QCryptographicHash::hash(data, QCryptographicHash::Md5);
1891
1892     return QScriptValue(QLatin1String(result.toHex()));
1893 }
1894
1895 /*!
1896 \qmlmethod string Qt::btoa(data)
1897 Binary to ASCII - this function returns a base64 encoding of \c data.
1898 */
1899 QScriptValue QDeclarativeEnginePrivate::btoa(QScriptContext *ctxt, QScriptEngine *)
1900 {
1901     if (ctxt->argumentCount() != 1)
1902         return ctxt->throwError(QLatin1String("Qt.btoa(): Invalid arguments"));
1903
1904     QByteArray data = ctxt->argument(0).toString().toUtf8();
1905
1906     return QScriptValue(QLatin1String(data.toBase64()));
1907 }
1908
1909 /*!
1910 \qmlmethod string Qt::atob(data)
1911 ASCII to binary - this function returns a base64 decoding of \c data.
1912 */
1913
1914 QScriptValue QDeclarativeEnginePrivate::atob(QScriptContext *ctxt, QScriptEngine *)
1915 {
1916     if (ctxt->argumentCount() != 1)
1917         return ctxt->throwError(QLatin1String("Qt.atob(): Invalid arguments"));
1918
1919     QByteArray data = ctxt->argument(0).toString().toUtf8();
1920
1921     return QScriptValue(QLatin1String(QByteArray::fromBase64(data)));
1922 }
1923
1924 QScriptValue QDeclarativeEnginePrivate::consoleLog(QScriptContext *ctxt, QScriptEngine *e)
1925 {
1926     if(ctxt->argumentCount() < 1)
1927         return e->newVariant(QVariant(false));
1928
1929     QByteArray msg;
1930
1931     for (int i=0; i<ctxt->argumentCount(); ++i) {
1932         if (!msg.isEmpty()) msg += ' ';
1933         msg += ctxt->argument(i).toString().toLocal8Bit();
1934         // does not support firebug "%[a-z]" formatting, since firebug really
1935         // does just ignore the format letter, which makes it pointless.
1936     }
1937
1938     qDebug("%s",msg.constData());
1939
1940     return e->newVariant(QVariant(true));
1941 }
1942
1943 void QDeclarativeEnginePrivate::sendQuit()
1944 {
1945     Q_Q(QDeclarativeEngine);
1946     emit q->quit();
1947     if (q->receivers(SIGNAL(quit())) == 0) {
1948         qWarning("Signal QDeclarativeEngine::quit() emitted, but no receivers connected to handle it.");
1949     }
1950 }
1951
1952 static void dumpwarning(const QDeclarativeError &error)
1953 {
1954     qWarning().nospace() << qPrintable(error.toString());
1955 }
1956
1957 static void dumpwarning(const QList<QDeclarativeError> &errors)
1958 {
1959     for (int ii = 0; ii < errors.count(); ++ii)
1960         dumpwarning(errors.at(ii));
1961 }
1962
1963 void QDeclarativeEnginePrivate::warning(const QDeclarativeError &error)
1964 {
1965     Q_Q(QDeclarativeEngine);
1966     q->warnings(QList<QDeclarativeError>() << error);
1967     if (outputWarningsToStdErr)
1968         dumpwarning(error);
1969 }
1970
1971 void QDeclarativeEnginePrivate::warning(const QList<QDeclarativeError> &errors)
1972 {
1973     Q_Q(QDeclarativeEngine);
1974     q->warnings(errors);
1975     if (outputWarningsToStdErr)
1976         dumpwarning(errors);
1977 }
1978
1979 void QDeclarativeEnginePrivate::warning(QDeclarativeEngine *engine, const QDeclarativeError &error)
1980 {
1981     if (engine)
1982         QDeclarativeEnginePrivate::get(engine)->warning(error);
1983     else
1984         dumpwarning(error);
1985 }
1986
1987 void QDeclarativeEnginePrivate::warning(QDeclarativeEngine *engine, const QList<QDeclarativeError> &error)
1988 {
1989     if (engine)
1990         QDeclarativeEnginePrivate::get(engine)->warning(error);
1991     else
1992         dumpwarning(error);
1993 }
1994
1995 void QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate *engine, const QDeclarativeError &error)
1996 {
1997     if (engine)
1998         engine->warning(error);
1999     else
2000         dumpwarning(error);
2001 }
2002
2003 void QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate *engine, const QList<QDeclarativeError> &error)
2004 {
2005     if (engine)
2006         engine->warning(error);
2007     else
2008         dumpwarning(error);
2009 }
2010
2011 /*!
2012 \qmlmethod Qt::quit()
2013 This function causes the QDeclarativeEngine::quit() signal to be emitted.
2014 Within the \l {QML Viewer}, this causes the launcher application to exit;
2015 to quit a C++ application when this method is called, connect the
2016 QDeclarativeEngine::quit() signal to the QCoreApplication::quit() slot.
2017 */
2018
2019 QScriptValue QDeclarativeEnginePrivate::quit(QScriptContext * /*ctxt*/, QScriptEngine *e)
2020 {
2021     QDeclarativeEnginePrivate *qe = get (e);
2022     qe->sendQuit();
2023     return QScriptValue();
2024 }
2025
2026 /*!
2027     \qmlmethod color Qt::tint(color baseColor, color tintColor)
2028     This function allows tinting one color with another.
2029
2030     The tint color should usually be mostly transparent, or you will not be
2031     able to see the underlying color. The below example provides a slight red
2032     tint by having the tint color be pure red which is only 1/16th opaque.
2033
2034     \qml
2035     Item {
2036         Rectangle {
2037             x: 0; width: 80; height: 80
2038             color: "lightsteelblue"
2039         }
2040         Rectangle {
2041             x: 100; width: 80; height: 80
2042             color: Qt.tint("lightsteelblue", "#10FF0000")
2043         }
2044     }
2045     \endqml
2046     \image declarative-rect_tint.png
2047
2048     Tint is most useful when a subtle change is intended to be conveyed due to some event; you can then use tinting to more effectively tune the visible color.
2049 */
2050 QScriptValue QDeclarativeEnginePrivate::tint(QScriptContext *ctxt, QScriptEngine *engine)
2051 {
2052     if(ctxt->argumentCount() != 2)
2053         return ctxt->throwError(QLatin1String("Qt.tint(): Invalid arguments"));
2054     //get color
2055     QVariant v = ctxt->argument(0).toVariant();
2056     QColor color;
2057     if (v.userType() == QVariant::Color)
2058         color = v.value<QColor>();
2059     else if (v.userType() == QVariant::String) {
2060         bool ok;
2061         color = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
2062         if (!ok)
2063             return engine->nullValue();
2064     } else
2065         return engine->nullValue();
2066
2067     //get tint color
2068     v = ctxt->argument(1).toVariant();
2069     QColor tintColor;
2070     if (v.userType() == QVariant::Color)
2071         tintColor = v.value<QColor>();
2072     else if (v.userType() == QVariant::String) {
2073         bool ok;
2074         tintColor = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
2075         if (!ok)
2076             return engine->nullValue();
2077     } else
2078         return engine->nullValue();
2079
2080     //tint
2081     QColor finalColor;
2082     int a = tintColor.alpha();
2083     if (a == 0xFF)
2084         finalColor = tintColor;
2085     else if (a == 0x00)
2086         finalColor = color;
2087     else {
2088         qreal a = tintColor.alphaF();
2089         qreal inv_a = 1.0 - a;
2090
2091         finalColor.setRgbF(tintColor.redF() * a + color.redF() * inv_a,
2092                            tintColor.greenF() * a + color.greenF() * inv_a,
2093                            tintColor.blueF() * a + color.blueF() * inv_a,
2094                            a + inv_a * color.alphaF());
2095     }
2096
2097     return engine->toScriptValue(QVariant::fromValue(finalColor));
2098 }
2099
2100 QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &val)
2101 {
2102     if (variantIsScarceResource(val)) {
2103         return scarceResourceClass->newScarceResource(val);
2104     } else if (val.userType() == qMetaTypeId<QDeclarativeListReference>()) {
2105         QDeclarativeListReferencePrivate *p =
2106             QDeclarativeListReferencePrivate::get((QDeclarativeListReference*)val.constData());
2107         if (p->object) {
2108             return listClass->newList(p->property, p->propertyType);
2109         } else {
2110             return scriptEngine.nullValue();
2111         }
2112     } else if (val.userType() == qMetaTypeId<QList<QObject *> >()) {
2113         const QList<QObject *> &list = *(QList<QObject *>*)val.constData();
2114         QScriptValue rv = scriptEngine.newArray(list.count());
2115         for (int ii = 0; ii < list.count(); ++ii) {
2116             QObject *object = list.at(ii);
2117             rv.setProperty(ii, objectClass->newQObject(object));
2118         }
2119         return rv;
2120     } else if (QDeclarativeValueType *vt = valueTypes[val.userType()]) {
2121         return valueTypeClass->newObject(val, vt);
2122     }
2123
2124     bool objOk;
2125     QObject *obj = QDeclarativeMetaType::toQObject(val, &objOk);
2126     if (objOk) {
2127         return objectClass->newQObject(obj);
2128     } else {
2129         return scriptEngine.toScriptValue(val);
2130     }
2131 }
2132
2133 /*
2134    If the variant is a scarce resource (consumes a large amount of memory, or
2135    only a limited number of them can be held in memory at any given time without
2136    exhausting supply for future use) we need to release the scarce resource
2137    after evaluation of the javascript binding is complete.
2138  */
2139 bool QDeclarativeEnginePrivate::variantIsScarceResource(const QVariant& val)
2140 {
2141     if (val.type() == QVariant::Pixmap) {
2142         return true;
2143     } else if (val.type() == QVariant::Image) {
2144         return true;
2145     }
2146
2147     return false;
2148 }
2149
2150 /*
2151    This function should be called prior to evaluation of any js expression,
2152    so that scarce resources are not freed prematurely (eg, if there is a
2153    nested javascript expression).
2154  */
2155 void QDeclarativeEnginePrivate::referenceScarceResources()
2156 {
2157     scarceResourcesRefCount += 1;
2158 }
2159
2160 /*
2161    This function should be called after evaluation of the js expression is
2162    complete, and so the scarce resources may be freed safely.
2163  */
2164 void QDeclarativeEnginePrivate::dereferenceScarceResources()
2165 {
2166     Q_ASSERT(scarceResourcesRefCount > 0);
2167     scarceResourcesRefCount -= 1;
2168
2169     // if the refcount is zero, then evaluation of the "top level"
2170     // expression must have completed.  We can safely release the
2171     // scarce resources.
2172     if (scarceResourcesRefCount == 0) {
2173         // iterate through the list and release them all.
2174         // note that the actual SRD is owned by the JS engine,
2175         // so we cannot delete the SRD; but we can free the
2176         // memory used by the variant in the SRD.
2177         ScarceResourceData *srd = 0;
2178         while (scarceResources) {
2179             srd = scarceResources; // srd points to the "old" (current) head of the list
2180             scarceResources = srd->next; // srd->next is the "new" head of the list
2181             if (srd->next) srd->next->prev = &scarceResources; // newHead->prev = listptr.
2182             srd->next = 0;
2183             srd->prev = 0;
2184             srd->releaseResource(); // release the old head node.
2185         }
2186     }
2187 }
2188
2189 QVariant QDeclarativeEnginePrivate::scriptValueToVariant(const QScriptValue &val, int hint)
2190 {
2191     QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(val);
2192     if (dc == objectClass)
2193         return QVariant::fromValue(objectClass->toQObject(val));
2194     else if (dc == scarceResourceClass)
2195         return scarceResourceClass->toVariant(val);
2196     else if (dc == valueTypeClass)
2197         return valueTypeClass->toVariant(val);
2198     else if (dc == contextClass)
2199         return QVariant();
2200
2201     // Convert to a QList<QObject*> only if val is an array and we were explicitly hinted
2202     if (hint == qMetaTypeId<QList<QObject *> >() && val.isArray()) {
2203         QList<QObject *> list;
2204         int length = val.property(QLatin1String("length")).toInt32();
2205         for (int ii = 0; ii < length; ++ii) {
2206             QScriptValue arrayItem = val.property(ii);
2207             QObject *d = arrayItem.toQObject();
2208             list << d;
2209         }
2210         return QVariant::fromValue(list);
2211     }
2212
2213     return val.toVariant();
2214 }
2215
2216 /*!
2217   Adds \a path as a directory where the engine searches for
2218   installed modules in a URL-based directory structure.
2219   The \a path may be a local filesystem directory or a URL.
2220
2221   The newly added \a path will be first in the importPathList().
2222
2223   \sa setImportPathList(), {QML Modules}
2224 */
2225 void QDeclarativeEngine::addImportPath(const QString& path)
2226 {
2227     Q_D(QDeclarativeEngine);
2228     d->importDatabase.addImportPath(path);
2229 }
2230
2231 /*!
2232   Returns the list of directories where the engine searches for
2233   installed modules in a URL-based directory structure.
2234
2235   For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
2236   imports \c com.mycompany.Feature will cause the QDeclarativeEngine to look
2237   in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
2238   provided by that module. A \c qmldir file is required for defining the
2239   type version mapping and possibly declarative extensions plugins.
2240
2241   By default, the list contains the directory of the application executable,
2242   paths specified in the \c QML_IMPORT_PATH environment variable,
2243   and the builtin \c ImportsPath from QLibraryInfo.
2244
2245   \sa addImportPath() setImportPathList()
2246 */
2247 QStringList QDeclarativeEngine::importPathList() const
2248 {
2249     Q_D(const QDeclarativeEngine);
2250     return d->importDatabase.importPathList();
2251 }
2252
2253 /*!
2254   Sets \a paths as the list of directories where the engine searches for
2255   installed modules in a URL-based directory structure.
2256
2257   By default, the list contains the directory of the application executable,
2258   paths specified in the \c QML_IMPORT_PATH environment variable,
2259   and the builtin \c ImportsPath from QLibraryInfo.
2260
2261   \sa importPathList() addImportPath()
2262   */
2263 void QDeclarativeEngine::setImportPathList(const QStringList &paths)
2264 {
2265     Q_D(QDeclarativeEngine);
2266     d->importDatabase.setImportPathList(paths);
2267 }
2268
2269
2270 /*!
2271   Adds \a path as a directory where the engine searches for
2272   native plugins for imported modules (referenced in the \c qmldir file).
2273
2274   By default, the list contains only \c .,  i.e. the engine searches
2275   in the directory of the \c qmldir file itself.
2276
2277   The newly added \a path will be first in the pluginPathList().
2278
2279   \sa setPluginPathList()
2280 */
2281 void QDeclarativeEngine::addPluginPath(const QString& path)
2282 {
2283     Q_D(QDeclarativeEngine);
2284     d->importDatabase.addPluginPath(path);
2285 }
2286
2287
2288 /*!
2289   Returns the list of directories where the engine searches for
2290   native plugins for imported modules (referenced in the \c qmldir file).
2291
2292   By default, the list contains only \c .,  i.e. the engine searches
2293   in the directory of the \c qmldir file itself.
2294
2295   \sa addPluginPath() setPluginPathList()
2296 */
2297 QStringList QDeclarativeEngine::pluginPathList() const
2298 {
2299     Q_D(const QDeclarativeEngine);
2300     return d->importDatabase.pluginPathList();
2301 }
2302
2303 /*!
2304   Sets the list of directories where the engine searches for
2305   native plugins for imported modules (referenced in the \c qmldir file)
2306   to \a paths.
2307
2308   By default, the list contains only \c .,  i.e. the engine searches
2309   in the directory of the \c qmldir file itself.
2310
2311   \sa pluginPathList() addPluginPath()
2312   */
2313 void QDeclarativeEngine::setPluginPathList(const QStringList &paths)
2314 {
2315     Q_D(QDeclarativeEngine);
2316     d->importDatabase.setPluginPathList(paths);
2317 }
2318
2319
2320 /*!
2321   Imports the plugin named \a filePath with the \a uri provided.
2322   Returns true if the plugin was successfully imported; otherwise returns false.
2323
2324   On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
2325
2326   The plugin has to be a Qt plugin which implements the QDeclarativeExtensionPlugin interface.
2327 */
2328 bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &uri, QList<QDeclarativeError> *errors)
2329 {
2330     Q_D(QDeclarativeEngine);
2331     return d->importDatabase.importPlugin(filePath, uri, errors);
2332 }
2333
2334 /*!
2335   Imports the plugin named \a filePath with the \a uri provided.
2336   Returns true if the plugin was successfully imported; otherwise returns false.
2337
2338   On failure and if non-null, *\a errorString will be set to a message describing the failure.
2339
2340   The plugin has to be a Qt plugin which implements the QDeclarativeExtensionPlugin interface.
2341 */
2342 bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
2343 {
2344     Q_D(QDeclarativeEngine);
2345     QList<QDeclarativeError> errors;
2346     bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
2347     if (!errors.isEmpty()) {
2348         QString builtError;
2349         for (int i = 0; i < errors.size(); ++i) {
2350             builtError = QString(QLatin1String("%1\n        %2"))
2351                     .arg(builtError)
2352                     .arg(errors.at(i).toString());
2353         }
2354         *errorString = builtError;
2355     }
2356     return retn;
2357 }
2358
2359 /*!
2360   \property QDeclarativeEngine::offlineStoragePath
2361   \brief the directory for storing offline user data
2362
2363   Returns the directory where SQL and other offline
2364   storage is placed.
2365
2366   QDeclarativeWebView and the SQL databases created with openDatabase()
2367   are stored here.
2368
2369   The default is QML/OfflineStorage in the platform-standard
2370   user application data directory.
2371
2372   Note that the path may not currently exist on the filesystem, so
2373   callers wanting to \e create new files at this location should create
2374   it first - see QDir::mkpath().
2375 */
2376 void QDeclarativeEngine::setOfflineStoragePath(const QString& dir)
2377 {
2378     Q_D(QDeclarativeEngine);
2379     d->scriptEngine.offlineStoragePath = dir;
2380 }
2381
2382 QString QDeclarativeEngine::offlineStoragePath() const
2383 {
2384     Q_D(const QDeclarativeEngine);
2385     return d->scriptEngine.offlineStoragePath;
2386 }
2387
2388 static void voidptr_destructor(void *v)
2389 {
2390     void **ptr = (void **)v;
2391     delete ptr;
2392 }
2393
2394 static void *voidptr_constructor(const void *v)
2395 {
2396     if (!v) {
2397         return new void*;
2398     } else {
2399         return new void*(*(void **)v);
2400     }
2401 }
2402
2403 QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(const QMetaObject *mo)
2404 {
2405     Q_Q(QDeclarativeEngine);
2406
2407     if (!mo->superClass()) {
2408         QDeclarativePropertyCache *rv = new QDeclarativePropertyCache(q, mo);
2409         propertyCache.insert(mo, rv);
2410         return rv;
2411     } else {
2412         QDeclarativePropertyCache *super = cache(mo->superClass());
2413         QDeclarativePropertyCache *rv = super->copy();
2414         rv->append(q, mo);
2415         propertyCache.insert(mo, rv);
2416         return rv;
2417     }
2418 }
2419
2420 QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(QDeclarativeType *type, int minorVersion,
2421                                                                   QDeclarativeError &error)
2422 {
2423     QList<QDeclarativeType *> types;
2424
2425     int maxMinorVersion = 0;
2426
2427     const QMetaObject *metaObject = type->metaObject();
2428     while (metaObject) {
2429         QDeclarativeType *t = QDeclarativeMetaType::qmlType(metaObject, type->module(),
2430                                                             type->majorVersion(), minorVersion);
2431         if (t) {
2432             maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
2433             types << t;
2434         } else {
2435             types << 0;
2436         }
2437
2438         metaObject = metaObject->superClass();
2439     }
2440
2441     if (QDeclarativePropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
2442         c->addref();
2443         typePropertyCache.insert(qMakePair(type, minorVersion), c);
2444         return c;
2445     }
2446
2447     QDeclarativePropertyCache *raw = cache(type->metaObject());
2448
2449     bool hasCopied = false;
2450
2451     for (int ii = 0; ii < types.count(); ++ii) {
2452         QDeclarativeType *currentType = types.at(ii);
2453         if (!currentType)
2454             continue;
2455
2456         int rev = currentType->metaObjectRevision();
2457         int moIndex = types.count() - 1 - ii;
2458
2459         if (raw->allowedRevisionCache[moIndex] != rev) {
2460             if (!hasCopied) {
2461                 raw = raw->copy();
2462                 hasCopied = true;
2463             }
2464             raw->allowedRevisionCache[moIndex] = rev;
2465         }
2466     }
2467
2468     // Test revision compatibility - the basic rule is:
2469     //    * Anything that is excluded, cannot overload something that is not excluded *
2470
2471     // Signals override:
2472     //    * other signals and methods of the same name.
2473     //    * properties named on<Signal Name>
2474     //    * automatic <property name>Changed notify signals
2475
2476     // Methods override:
2477     //    * other methods of the same name
2478
2479     // Properties override:
2480     //    * other elements of the same name
2481
2482     bool overloadError = false;
2483     QString overloadName;
2484
2485 #if 0
2486     for (QDeclarativePropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
2487          !overloadError && iter != raw->stringCache.end();
2488          ++iter) {
2489
2490         QDeclarativePropertyCache::Data *d = *iter;
2491         if (raw->isAllowedInRevision(d))
2492             continue; // Not excluded - no problems
2493
2494         // check that a regular "name" overload isn't happening
2495         QDeclarativePropertyCache::Data *current = d;
2496         while (!overloadError && current) {
2497             current = d->overrideData(current);
2498             if (current && raw->isAllowedInRevision(current))
2499                 overloadError = true;
2500         }
2501     }
2502 #endif
2503
2504     if (overloadError) {
2505         if (hasCopied) raw->release();
2506
2507         error.setDescription(QLatin1String("Type ") + QString::fromUtf8(type->qmlTypeName()) + QLatin1String(" ") + QString::number(type->majorVersion()) + QLatin1String(".") + QString::number(minorVersion) + QLatin1String(" contains an illegal property \"") + overloadName + QLatin1String("\".  This is an error in the type's implementation."));
2508         return 0;
2509     }
2510
2511     if (!hasCopied) raw->addref();
2512     typePropertyCache.insert(qMakePair(type, minorVersion), raw);
2513
2514     if (minorVersion != maxMinorVersion) {
2515         raw->addref();
2516         typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
2517     }
2518
2519     return raw;
2520 }
2521
2522 void QDeclarativeEnginePrivate::registerCompositeType(QDeclarativeCompiledData *data)
2523 {
2524     QByteArray name = data->root->className();
2525
2526     QByteArray ptr = name + '*';
2527     QByteArray lst = "QDeclarativeListProperty<" + name + '>';
2528
2529     int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
2530                                            voidptr_constructor);
2531     int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
2532                                            voidptr_constructor);
2533
2534     m_qmlLists.insert(lst_type, ptr_type);
2535     m_compositeTypes.insert(ptr_type, data);
2536     data->addref();
2537 }
2538
2539 bool QDeclarativeEnginePrivate::isList(int t) const
2540 {
2541     return m_qmlLists.contains(t) || QDeclarativeMetaType::isList(t);
2542 }
2543
2544 int QDeclarativeEnginePrivate::listType(int t) const
2545 {
2546     QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
2547     if (iter != m_qmlLists.end())
2548         return *iter;
2549     else
2550         return QDeclarativeMetaType::listType(t);
2551 }
2552
2553 bool QDeclarativeEnginePrivate::isQObject(int t)
2554 {
2555     return m_compositeTypes.contains(t) || QDeclarativeMetaType::isQObject(t);
2556 }
2557
2558 QObject *QDeclarativeEnginePrivate::toQObject(const QVariant &v, bool *ok) const
2559 {
2560     int t = v.userType();
2561     if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
2562         if (ok) *ok = true;
2563         return *(QObject **)(v.constData());
2564     } else {
2565         return QDeclarativeMetaType::toQObject(v, ok);
2566     }
2567 }
2568
2569 QDeclarativeMetaType::TypeCategory QDeclarativeEnginePrivate::typeCategory(int t) const
2570 {
2571     if (m_compositeTypes.contains(t))
2572         return QDeclarativeMetaType::Object;
2573     else if (m_qmlLists.contains(t))
2574         return QDeclarativeMetaType::List;
2575     else
2576         return QDeclarativeMetaType::typeCategory(t);
2577 }
2578
2579 const QMetaObject *QDeclarativeEnginePrivate::rawMetaObjectForType(int t) const
2580 {
2581     QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
2582     if (iter != m_compositeTypes.end()) {
2583         return (*iter)->root;
2584     } else {
2585         QDeclarativeType *type = QDeclarativeMetaType::qmlType(t);
2586         return type?type->baseMetaObject():0;
2587     }
2588 }
2589
2590 const QMetaObject *QDeclarativeEnginePrivate::metaObjectForType(int t) const
2591 {
2592     QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
2593     if (iter != m_compositeTypes.end()) {
2594         return (*iter)->root;
2595     } else {
2596         QDeclarativeType *type = QDeclarativeMetaType::qmlType(t);
2597         return type?type->metaObject():0;
2598     }
2599 }
2600
2601 bool QDeclarative_isFileCaseCorrect(const QString &fileName)
2602 {
2603 #if defined(Q_OS_MAC) || defined(Q_OS_WIN32)
2604     QFileInfo info(fileName);
2605
2606     QString absolute = info.absoluteFilePath();
2607
2608 #if defined(Q_OS_MAC)
2609     QString canonical = info.canonicalFilePath();
2610 #elif defined(Q_OS_WIN32)
2611     wchar_t buffer[1024];
2612
2613     DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
2614     if (rv == 0 || rv >= 1024) return true;
2615     rv = ::GetLongPathName(buffer, buffer, 1024);
2616     if (rv == 0 || rv >= 1024) return true;
2617
2618     QString canonical((QChar *)buffer);
2619 #endif
2620
2621     int absoluteLength = absolute.length();
2622     int canonicalLength = canonical.length();
2623
2624     int length = qMin(absoluteLength, canonicalLength);
2625     for (int ii = 0; ii < length; ++ii) {
2626         const QChar &a = absolute.at(absoluteLength - 1 - ii);
2627         const QChar &c = canonical.at(canonicalLength - 1 - ii);
2628
2629         if (a.toLower() != c.toLower())
2630             return true;
2631         if (a != c)
2632             return false;
2633     }
2634 #else
2635     Q_UNUSED(fileName)
2636 #endif
2637     return true;
2638 }
2639
2640 QT_END_NAMESPACE