Merge branch 'master' into qtquick2
[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 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "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     // if we are the parent of any of the qobject module api instances,
667     // we need to remove them from our internal list, in order to prevent
668     // a segfault in engine private dtor.
669     QList<QDeclarativeMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
670     QObject *currQObjectApi = 0;
671     QDeclarativeMetaType::ModuleApiInstance *currInstance = 0;
672     foreach (const QDeclarativeMetaType::ModuleApi &key, keys) {
673         currInstance = d->moduleApiInstances.value(key);
674         currQObjectApi = currInstance->qobjectApi;
675         if (this->children().contains(currQObjectApi)) {
676             delete currQObjectApi;
677             delete currInstance;
678             d->moduleApiInstances.remove(key);
679         }
680     }
681 }
682
683 /*! \fn void QDeclarativeEngine::quit()
684     This signal is emitted when the QML loaded by the engine would like to quit.
685  */
686
687 /*! \fn void QDeclarativeEngine::warnings(const QList<QDeclarativeError> &warnings)
688     This signal is emitted when \a warnings messages are generated by QML.
689  */
690
691 /*!
692   Clears the engine's internal component cache.
693
694   Normally the QDeclarativeEngine caches components loaded from qml
695   files.  This method clears this cache and forces the component to be
696   reloaded.
697  */
698 void QDeclarativeEngine::clearComponentCache()
699 {
700     Q_D(QDeclarativeEngine);
701     d->typeLoader.clearCache();
702 }
703
704 /*!
705   Returns the engine's root context.
706
707   The root context is automatically created by the QDeclarativeEngine.
708   Data that should be available to all QML component instances
709   instantiated by the engine should be put in the root context.
710
711   Additional data that should only be available to a subset of
712   component instances should be added to sub-contexts parented to the
713   root context.
714 */
715 QDeclarativeContext *QDeclarativeEngine::rootContext() const
716 {
717     Q_D(const QDeclarativeEngine);
718     return d->rootContext;
719 }
720
721 /*!
722   Sets the \a factory to use for creating QNetworkAccessManager(s).
723
724   QNetworkAccessManager is used for all network access by QML.  By
725   implementing a factory it is possible to create custom
726   QNetworkAccessManager with specialized caching, proxy and cookie
727   support.
728
729   The factory must be set before executing the engine.
730 */
731 void QDeclarativeEngine::setNetworkAccessManagerFactory(QDeclarativeNetworkAccessManagerFactory *factory)
732 {
733     Q_D(QDeclarativeEngine);
734     QMutexLocker locker(&d->mutex);
735     d->networkAccessManagerFactory = factory;
736 }
737
738 /*!
739   Returns the current QDeclarativeNetworkAccessManagerFactory.
740
741   \sa setNetworkAccessManagerFactory()
742 */
743 QDeclarativeNetworkAccessManagerFactory *QDeclarativeEngine::networkAccessManagerFactory() const
744 {
745     Q_D(const QDeclarativeEngine);
746     return d->networkAccessManagerFactory;
747 }
748
749 QNetworkAccessManager *QDeclarativeEnginePrivate::createNetworkAccessManager(QObject *parent) const
750 {
751     QMutexLocker locker(&mutex);
752     QNetworkAccessManager *nam;
753     if (networkAccessManagerFactory) {
754         nam = networkAccessManagerFactory->create(parent);
755     } else {
756         nam = new QNetworkAccessManager(parent);
757     }
758
759     return nam;
760 }
761
762 QNetworkAccessManager *QDeclarativeEnginePrivate::getNetworkAccessManager() const
763 {
764     Q_Q(const QDeclarativeEngine);
765     if (!networkAccessManager)
766         networkAccessManager = createNetworkAccessManager(const_cast<QDeclarativeEngine*>(q));
767     return networkAccessManager;
768 }
769
770 /*!
771   Returns a common QNetworkAccessManager which can be used by any QML
772   element instantiated by this engine.
773
774   If a QDeclarativeNetworkAccessManagerFactory has been set and a
775   QNetworkAccessManager has not yet been created, the
776   QDeclarativeNetworkAccessManagerFactory will be used to create the
777   QNetworkAccessManager; otherwise the returned QNetworkAccessManager
778   will have no proxy or cache set.
779
780   \sa setNetworkAccessManagerFactory()
781 */
782 QNetworkAccessManager *QDeclarativeEngine::networkAccessManager() const
783 {
784     Q_D(const QDeclarativeEngine);
785     return d->getNetworkAccessManager();
786 }
787
788 /*!
789
790   Sets the \a provider to use for images requested via the \e
791   image: url scheme, with host \a providerId. The QDeclarativeEngine
792   takes ownership of \a provider.
793
794   Image providers enable support for pixmap and threaded image
795   requests. See the QDeclarativeImageProvider documentation for details on
796   implementing and using image providers.
797
798   All required image providers should be added to the engine before any
799   QML sources files are loaded.
800
801   \sa removeImageProvider()
802 */
803 void QDeclarativeEngine::addImageProvider(const QString &providerId, QDeclarativeImageProvider *provider)
804 {
805     Q_D(QDeclarativeEngine);
806     QMutexLocker locker(&d->mutex);
807     d->imageProviders.insert(providerId.toLower(), QSharedPointer<QDeclarativeImageProvider>(provider));
808 }
809
810 /*!
811   Returns the QDeclarativeImageProvider set for \a providerId.
812 */
813 QDeclarativeImageProvider *QDeclarativeEngine::imageProvider(const QString &providerId) const
814 {
815     Q_D(const QDeclarativeEngine);
816     QMutexLocker locker(&d->mutex);
817     return d->imageProviders.value(providerId).data();
818 }
819
820 /*!
821   Removes the QDeclarativeImageProvider for \a providerId.
822
823   Returns the provider if it was found; otherwise returns 0.
824
825   \sa addImageProvider()
826 */
827 void QDeclarativeEngine::removeImageProvider(const QString &providerId)
828 {
829     Q_D(QDeclarativeEngine);
830     QMutexLocker locker(&d->mutex);
831     d->imageProviders.take(providerId);
832 }
833
834 QDeclarativeImageProvider::ImageType QDeclarativeEnginePrivate::getImageProviderType(const QUrl &url)
835 {
836     QMutexLocker locker(&mutex);
837     QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
838     locker.unlock();
839     if (provider)
840         return provider->imageType();
841     return QDeclarativeImageProvider::Invalid;
842 }
843
844 QSGTexture *QDeclarativeEnginePrivate::getTextureFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
845 {
846     QMutexLocker locker(&mutex);
847     QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
848     locker.unlock();
849     if (provider) {
850         QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
851         return provider->requestTexture(imageId, size, req_size);
852     }
853     return 0;
854 }
855
856 QImage QDeclarativeEnginePrivate::getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
857 {
858     QMutexLocker locker(&mutex);
859     QImage image;
860     QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
861     locker.unlock();
862     if (provider) {
863         QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
864         image = provider->requestImage(imageId, size, req_size);
865     }
866     return image;
867 }
868
869 QPixmap QDeclarativeEnginePrivate::getPixmapFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
870 {
871     QMutexLocker locker(&mutex);
872     QPixmap pixmap;
873     QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
874     locker.unlock();
875     if (provider) {
876         QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
877         pixmap = provider->requestPixmap(imageId, size, req_size);
878     }
879     return pixmap;
880 }
881
882 /*!
883   Return the base URL for this engine.  The base URL is only used to
884   resolve components when a relative URL is passed to the
885   QDeclarativeComponent constructor.
886
887   If a base URL has not been explicitly set, this method returns the
888   application's current working directory.
889
890   \sa setBaseUrl()
891 */
892 QUrl QDeclarativeEngine::baseUrl() const
893 {
894     Q_D(const QDeclarativeEngine);
895     if (d->baseUrl.isEmpty()) {
896         return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
897     } else {
898         return d->baseUrl;
899     }
900 }
901
902 /*!
903   Set the  base URL for this engine to \a url.
904
905   \sa baseUrl()
906 */
907 void QDeclarativeEngine::setBaseUrl(const QUrl &url)
908 {
909     Q_D(QDeclarativeEngine);
910     d->baseUrl = url;
911 }
912
913 /*!
914   Returns true if warning messages will be output to stderr in addition
915   to being emitted by the warnings() signal, otherwise false.
916
917   The default value is true.
918 */
919 bool QDeclarativeEngine::outputWarningsToStandardError() const
920 {
921     Q_D(const QDeclarativeEngine);
922     return d->outputWarningsToStdErr;
923 }
924
925 /*!
926   Set whether warning messages will be output to stderr to \a enabled.
927
928   If \a enabled is true, any warning messages generated by QML will be
929   output to stderr and emitted by the warnings() signal.  If \a enabled
930   is false, on the warnings() signal will be emitted.  This allows
931   applications to handle warning output themselves.
932
933   The default value is true.
934 */
935 void QDeclarativeEngine::setOutputWarningsToStandardError(bool enabled)
936 {
937     Q_D(QDeclarativeEngine);
938     d->outputWarningsToStdErr = enabled;
939 }
940
941 /*!
942   Returns the QDeclarativeContext for the \a object, or 0 if no
943   context has been set.
944
945   When the QDeclarativeEngine instantiates a QObject, the context is
946   set automatically.
947   */
948 QDeclarativeContext *QDeclarativeEngine::contextForObject(const QObject *object)
949 {
950     if(!object)
951         return 0;
952
953     QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
954
955     QDeclarativeData *data =
956         static_cast<QDeclarativeData *>(priv->declarativeData);
957
958     if (!data)
959         return 0;
960     else if (data->outerContext)
961         return data->outerContext->asQDeclarativeContext();
962     else
963         return 0;
964 }
965
966 /*!
967   Sets the QDeclarativeContext for the \a object to \a context.
968   If the \a object already has a context, a warning is
969   output, but the context is not changed.
970
971   When the QDeclarativeEngine instantiates a QObject, the context is
972   set automatically.
973  */
974 void QDeclarativeEngine::setContextForObject(QObject *object, QDeclarativeContext *context)
975 {
976     if (!object || !context)
977         return;
978
979     QDeclarativeData *data = QDeclarativeData::get(object, true);
980     if (data->context) {
981         qWarning("QDeclarativeEngine::setContextForObject(): Object already has a QDeclarativeContext");
982         return;
983     }
984
985     QDeclarativeContextData *contextData = QDeclarativeContextData::get(context);
986     contextData->addObject(object);
987 }
988
989 /*!
990   \enum QDeclarativeEngine::ObjectOwnership
991
992   Ownership controls whether or not QML automatically destroys the
993   QObject when the object is garbage collected by the JavaScript
994   engine.  The two ownership options are:
995
996   \value CppOwnership The object is owned by C++ code, and will
997   never be deleted by QML.  The JavaScript destroy() method cannot be
998   used on objects with CppOwnership.  This option is similar to
999   QScriptEngine::QtOwnership.
1000
1001   \value JavaScriptOwnership The object is owned by JavaScript.
1002   When the object is returned to QML as the return value of a method
1003   call or property access, QML will delete the object if there are no
1004   remaining JavaScript references to it and it has no
1005   QObject::parent().  This option is similar to
1006   QScriptEngine::ScriptOwnership.
1007
1008   Generally an application doesn't need to set an object's ownership
1009   explicitly.  QML uses a heuristic to set the default object
1010   ownership.  By default, an object that is created by QML has
1011   JavaScriptOwnership.  The exception to this are the root objects
1012   created by calling QDeclarativeCompnent::create() or
1013   QDeclarativeComponent::beginCreate() which have CppOwnership by
1014   default.  The ownership of these root-level objects is considered to
1015   have been transferred to the C++ caller.
1016
1017   Objects not-created by QML have CppOwnership by default.  The
1018   exception to this is objects returned from a C++ method call.  The
1019   ownership of these objects is passed to JavaScript.
1020
1021   Calling setObjectOwnership() overrides the default ownership
1022   heuristic used by QML.
1023 */
1024
1025 /*!
1026   Sets the \a ownership of \a object.
1027 */
1028 void QDeclarativeEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
1029 {
1030     if (!object)
1031         return;
1032
1033     QDeclarativeData *ddata = QDeclarativeData::get(object, true);
1034     if (!ddata)
1035         return;
1036
1037     ddata->indestructible = (ownership == CppOwnership)?true:false;
1038     ddata->explicitIndestructibleSet = true;
1039 }
1040
1041 /*!
1042   Returns the ownership of \a object.
1043 */
1044 QDeclarativeEngine::ObjectOwnership QDeclarativeEngine::objectOwnership(QObject *object)
1045 {
1046     if (!object)
1047         return CppOwnership;
1048
1049     QDeclarativeData *ddata = QDeclarativeData::get(object, false);
1050     if (!ddata)
1051         return CppOwnership;
1052     else
1053         return ddata->indestructible?CppOwnership:JavaScriptOwnership;
1054 }
1055
1056 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
1057 {
1058     QDeclarativeData *data = QDeclarativeData::get(object);
1059
1060     if (data && data->deferredComponent) {
1061         if (QDeclarativeDebugService::isDebuggingEnabled()) {
1062             QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Creating);
1063             QDeclarativeType *type = QDeclarativeMetaType::qmlType(object->metaObject());
1064             QString typeName = type ? QLatin1String(type->qmlTypeName()) : QString::fromLatin1(object->metaObject()->className());
1065             QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Creating, typeName);
1066             if (data->outerContext)
1067                 QDeclarativeDebugTrace::rangeLocation(QDeclarativeDebugTrace::Creating, data->outerContext->url, data->lineNumber);
1068         }
1069         QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(data->context->engine);
1070
1071         QDeclarativeComponentPrivate::ConstructionState state;
1072         QDeclarativeComponentPrivate::beginDeferred(ep, object, &state);
1073
1074         data->deferredComponent->release();
1075         data->deferredComponent = 0;
1076
1077         QDeclarativeComponentPrivate::complete(ep, &state);
1078         QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Creating);
1079     }
1080 }
1081
1082 QDeclarativeContext *qmlContext(const QObject *obj)
1083 {
1084     return QDeclarativeEngine::contextForObject(obj);
1085 }
1086
1087 QDeclarativeEngine *qmlEngine(const QObject *obj)
1088 {
1089     QDeclarativeContext *context = QDeclarativeEngine::contextForObject(obj);
1090     return context?context->engine():0;
1091 }
1092
1093 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1094 {
1095     QDeclarativeData *data = QDeclarativeData::get(object);
1096     if (!data)
1097         return 0; // Attached properties are only on objects created by QML
1098
1099     QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1100     if (rv || !create)
1101         return rv;
1102
1103     QDeclarativeAttachedPropertiesFunc pf = QDeclarativeMetaType::attachedPropertiesFuncById(id);
1104     if (!pf)
1105         return 0;
1106
1107     rv = pf(const_cast<QObject *>(object));
1108
1109     if (rv)
1110         data->attachedProperties()->insert(id, rv);
1111
1112     return rv;
1113 }
1114
1115 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1116                                      const QMetaObject *attachedMetaObject, bool create)
1117 {
1118     if (*idCache == -1)
1119         *idCache = QDeclarativeMetaType::attachedPropertiesFuncId(attachedMetaObject);
1120
1121     if (*idCache == -1 || !object)
1122         return 0;
1123
1124     return qmlAttachedPropertiesObjectById(*idCache, object, create);
1125 }
1126
1127 class QDeclarativeDataExtended {
1128 public:
1129     QDeclarativeDataExtended();
1130     ~QDeclarativeDataExtended();
1131
1132     QHash<int, QObject *> attachedProperties;
1133     QDeclarativeNotifier objectNameNotifier;
1134 };
1135
1136 QDeclarativeDataExtended::QDeclarativeDataExtended()
1137 {
1138 }
1139
1140 QDeclarativeDataExtended::~QDeclarativeDataExtended()
1141 {
1142 }
1143
1144 QDeclarativeNotifier *QDeclarativeData::objectNameNotifier() const
1145 {
1146     if (!extendedData) extendedData = new QDeclarativeDataExtended;
1147     return &extendedData->objectNameNotifier;
1148 }
1149
1150 QHash<int, QObject *> *QDeclarativeData::attachedProperties() const
1151 {
1152     if (!extendedData) extendedData = new QDeclarativeDataExtended;
1153     return &extendedData->attachedProperties;
1154 }
1155
1156 void QDeclarativeData::destroyed(QObject *object)
1157 {
1158     if (deferredComponent)
1159         deferredComponent->release();
1160
1161     if (nextContextObject)
1162         nextContextObject->prevContextObject = prevContextObject;
1163     if (prevContextObject)
1164         *prevContextObject = nextContextObject;
1165
1166     QDeclarativeAbstractBinding *binding = bindings;
1167     while (binding) {
1168         QDeclarativeAbstractBinding *next = binding->m_nextBinding;
1169         binding->m_prevBinding = 0;
1170         binding->m_nextBinding = 0;
1171         binding->destroy();
1172         binding = next;
1173     }
1174
1175     if (bindingBits)
1176         free(bindingBits);
1177
1178     if (propertyCache)
1179         propertyCache->release();
1180
1181     if (ownContext && context)
1182         context->destroy();
1183
1184     while (guards) {
1185         QDeclarativeGuard<QObject> *guard = guards;
1186         *guard = (QObject *)0;
1187         guard->objectDestroyed(object);
1188     }
1189
1190     if (scriptValue)
1191         delete scriptValue;
1192
1193     if (extendedData)
1194         delete extendedData;
1195
1196     if (ownMemory)
1197         delete this;
1198 }
1199
1200 void QDeclarativeData::parentChanged(QObject *, QObject *parent)
1201 {
1202     if (!parent && scriptValue) { delete scriptValue; scriptValue = 0; }
1203 }
1204
1205 void QDeclarativeData::objectNameChanged(QObject *)
1206 {
1207     if (extendedData) objectNameNotifier()->notify();
1208 }
1209
1210 bool QDeclarativeData::hasBindingBit(int bit) const
1211 {
1212     if (bindingBitsSize > bit)
1213         return bindingBits[bit / 32] & (1 << (bit % 32));
1214     else
1215         return false;
1216 }
1217
1218 void QDeclarativeData::clearBindingBit(int bit)
1219 {
1220     if (bindingBitsSize > bit)
1221         bindingBits[bit / 32] &= ~(1 << (bit % 32));
1222 }
1223
1224 void QDeclarativeData::setBindingBit(QObject *obj, int bit)
1225 {
1226     if (bindingBitsSize <= bit) {
1227         int props = obj->metaObject()->propertyCount();
1228         Q_ASSERT(bit < props);
1229
1230         int arraySize = (props + 31) / 32;
1231         int oldArraySize = bindingBitsSize / 32;
1232
1233         bindingBits = (quint32 *)realloc(bindingBits,
1234                                          arraySize * sizeof(quint32));
1235
1236         memset(bindingBits + oldArraySize,
1237                0x00,
1238                sizeof(quint32) * (arraySize - oldArraySize));
1239
1240         bindingBitsSize = arraySize * 32;
1241     }
1242
1243     bindingBits[bit / 32] |= (1 << (bit % 32));
1244 }
1245
1246 /*!
1247     Creates a QScriptValue allowing you to use \a object in QML script.
1248     \a engine is the QDeclarativeEngine it is to be created in.
1249
1250     The QScriptValue returned is a QtScript Object, not a QtScript QObject, due
1251     to the special needs of QML requiring more functionality than a standard
1252     QtScript QObject.
1253 */
1254 QScriptValue QDeclarativeEnginePrivate::qmlScriptObject(QObject* object,
1255                                                QDeclarativeEngine* engine)
1256 {
1257     QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine);
1258     return enginePriv->objectClass->newQObject(object);
1259 }
1260
1261 /*!
1262     Returns the QDeclarativeContext for the executing QScript \a ctxt.
1263 */
1264 QDeclarativeContextData *QDeclarativeEnginePrivate::getContext(QScriptContext *ctxt)
1265 {
1266     QScriptValue scopeNode = QScriptDeclarativeClass::scopeChainValue(ctxt, -3);
1267     Q_ASSERT(scopeNode.isValid());
1268     Q_ASSERT(QScriptDeclarativeClass::scriptClass(scopeNode) == contextClass);
1269     return contextClass->contextFromValue(scopeNode);
1270 }
1271
1272 /*!
1273     Returns the QUrl associated with the script \a ctxt for the case that there is
1274     no QDeclarativeContext.
1275 */
1276 QUrl QDeclarativeEnginePrivate::getUrl(QScriptContext *ctxt)
1277 {
1278     QScriptValue scopeNode = QScriptDeclarativeClass::scopeChainValue(ctxt, -3);
1279     Q_ASSERT(scopeNode.isValid());
1280     Q_ASSERT(QScriptDeclarativeClass::scriptClass(scopeNode) == contextClass);
1281     return contextClass->urlFromValue(scopeNode);
1282 }
1283
1284 QString QDeclarativeEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
1285 {
1286     if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
1287         if (url.authority().isEmpty())
1288             return QLatin1Char(':') + url.path();
1289         return QString();
1290     }
1291     return url.toLocalFile();
1292 }
1293
1294 /*!
1295 \qmlmethod object Qt::createComponent(url)
1296
1297 Returns a \l Component object created using the QML file at the specified \a url,
1298 or \c null if an empty string was given.
1299
1300 The returned component's \l Component::status property indicates whether the
1301 component was successfully created. If the status is \c Component.Error,
1302 see \l Component::errorString() for an error description.
1303
1304 Call \l {Component::createObject()}{Component.createObject()} on the returned
1305 component to create an object instance of the component.
1306
1307 For example:
1308
1309 \snippet doc/src/snippets/declarative/createComponent-simple.qml 0
1310
1311 See \l {Dynamic Object Management in QML} for more information on using this function.
1312
1313 To create a QML object from an arbitrary string of QML (instead of a file),
1314 use \l{QML:Qt::createQmlObject()}{Qt.createQmlObject()}.
1315 */
1316
1317 QScriptValue QDeclarativeEnginePrivate::createComponent(QScriptContext *ctxt, QScriptEngine *engine)
1318 {
1319     QDeclarativeEnginePrivate *activeEnginePriv =
1320         static_cast<QDeclarativeScriptEngine*>(engine)->p;
1321     QDeclarativeEngine* activeEngine = activeEnginePriv->q_func();
1322
1323     if(ctxt->argumentCount() != 1) {
1324         return ctxt->throwError(QLatin1String("Qt.createComponent(): Invalid arguments"));
1325     } else {
1326
1327         QString arg = ctxt->argument(0).toString();
1328         if (arg.isEmpty())
1329             return engine->nullValue();
1330         QUrl url = QDeclarativeScriptEngine::get(engine)->resolvedUrl(ctxt, QUrl(arg));
1331         QDeclarativeContextData* context = activeEnginePriv->getContext(ctxt);
1332         QDeclarativeComponent *c = new QDeclarativeComponent(activeEngine, url, activeEngine);
1333         QDeclarativeComponentPrivate::get(c)->creationContext = context;
1334         QDeclarativeData::get(c, true)->setImplicitDestructible();
1335         return activeEnginePriv->objectClass->newQObject(c, qMetaTypeId<QDeclarativeComponent*>());
1336     }
1337 }
1338
1339 /*!
1340 \qmlmethod object Qt::createQmlObject(string qml, object parent, string filepath)
1341
1342 Returns a new object created from the given \a string of QML which will have the specified \a parent,
1343 or \c null if there was an error in creating the object.
1344
1345 If \a filepath is specified, it will be used for error reporting for the created object.
1346
1347 Example (where \c parentItem is the id of an existing QML item):
1348
1349 \snippet doc/src/snippets/declarative/createQmlObject.qml 0
1350
1351 In the case of an error, a QtScript Error object is thrown. This object has an additional property,
1352 \c qmlErrors, which is an array of the errors encountered.
1353 Each object in this array has the members \c lineNumber, \c columnNumber, \c fileName and \c message.
1354 For example, if the above snippet had misspelled color as 'colro' then the array would contain an object like the following:
1355 { "lineNumber" : 1, "columnNumber" : 32, "fileName" : "dynamicSnippet1", "message" : "Cannot assign to non-existent property \"colro\""}.
1356
1357 Note that this function returns immediately, and therefore may not work if
1358 the \a qml string loads new components (that is, external QML files that have not yet been loaded).
1359 If this is the case, consider using \l{QML:Qt::createComponent()}{Qt.createComponent()} instead.
1360
1361 See \l {Dynamic Object Management in QML} for more information on using this function.
1362 */
1363
1364 QScriptValue QDeclarativeEnginePrivate::createQmlObject(QScriptContext *ctxt, QScriptEngine *engine)
1365 {
1366     QDeclarativeEnginePrivate *activeEnginePriv =
1367         static_cast<QDeclarativeScriptEngine*>(engine)->p;
1368     QDeclarativeEngine* activeEngine = activeEnginePriv->q_func();
1369
1370     if(ctxt->argumentCount() < 2 || ctxt->argumentCount() > 3)
1371         return ctxt->throwError(QLatin1String("Qt.createQmlObject(): Invalid arguments"));
1372
1373     QDeclarativeContextData* context = activeEnginePriv->getContext(ctxt);
1374     Q_ASSERT(context);
1375
1376     QString qml = ctxt->argument(0).toString();
1377     if (qml.isEmpty())
1378         return engine->nullValue();
1379
1380     QUrl url;
1381     if(ctxt->argumentCount() > 2)
1382         url = QUrl(ctxt->argument(2).toString());
1383     else
1384         url = QUrl(QLatin1String("inline"));
1385
1386     if (url.isValid() && url.isRelative())
1387         url = context->resolvedUrl(url);
1388
1389     QObject *parentArg = activeEnginePriv->objectClass->toQObject(ctxt->argument(1));
1390     if(!parentArg)
1391         return ctxt->throwError(QLatin1String("Qt.createQmlObject(): Missing parent object"));
1392
1393     QDeclarativeComponent component(activeEngine);
1394     component.setData(qml.toUtf8(), url);
1395
1396     if(component.isError()) {
1397         QList<QDeclarativeError> errors = component.errors();
1398         QString errstr = QLatin1String("Qt.createQmlObject() failed to create object: ");
1399         QScriptValue arr = ctxt->engine()->newArray(errors.length());
1400         int i = 0;
1401         foreach (const QDeclarativeError &error, errors){
1402             errstr += QLatin1String("\n    ") + error.toString();
1403             QScriptValue qmlErrObject = ctxt->engine()->newObject();
1404             qmlErrObject.setProperty(QLatin1String("lineNumber"), QScriptValue(error.line()));
1405             qmlErrObject.setProperty(QLatin1String("columnNumber"), QScriptValue(error.column()));
1406             qmlErrObject.setProperty(QLatin1String("fileName"), QScriptValue(error.url().toString()));
1407             qmlErrObject.setProperty(QLatin1String("message"), QScriptValue(error.description()));
1408             arr.setProperty(i++, qmlErrObject);
1409         }
1410         QScriptValue err = ctxt->throwError(errstr);
1411         err.setProperty(QLatin1String("qmlErrors"),arr);
1412         return err;
1413     }
1414
1415     if (!component.isReady())
1416         return ctxt->throwError(QLatin1String("Qt.createQmlObject(): Component is not ready"));
1417
1418     QObject *obj = component.beginCreate(context->asQDeclarativeContext());
1419     if(obj)
1420         QDeclarativeData::get(obj, true)->setImplicitDestructible();
1421     component.completeCreate();
1422
1423     if(component.isError()) {
1424         QList<QDeclarativeError> errors = component.errors();
1425         QString errstr = QLatin1String("Qt.createQmlObject() failed to create object: ");
1426         QScriptValue arr = ctxt->engine()->newArray(errors.length());
1427         int i = 0;
1428         foreach (const QDeclarativeError &error, errors){
1429             errstr += QLatin1String("\n    ") + error.toString();
1430             QScriptValue qmlErrObject = ctxt->engine()->newObject();
1431             qmlErrObject.setProperty(QLatin1String("lineNumber"), QScriptValue(error.line()));
1432             qmlErrObject.setProperty(QLatin1String("columnNumber"), QScriptValue(error.column()));
1433             qmlErrObject.setProperty(QLatin1String("fileName"), QScriptValue(error.url().toString()));
1434             qmlErrObject.setProperty(QLatin1String("message"), QScriptValue(error.description()));
1435             arr.setProperty(i++, qmlErrObject);
1436         }
1437         QScriptValue err = ctxt->throwError(errstr);
1438         err.setProperty(QLatin1String("qmlErrors"),arr);
1439         return err;
1440     }
1441
1442     Q_ASSERT(obj);
1443
1444     obj->setParent(parentArg);
1445
1446     QList<QDeclarativePrivate::AutoParentFunction> functions = QDeclarativeMetaType::parentFunctions();
1447     for (int ii = 0; ii < functions.count(); ++ii) {
1448         if (QDeclarativePrivate::Parented == functions.at(ii)(obj, parentArg))
1449             break;
1450     }
1451
1452     QDeclarativeData::get(obj, true)->setImplicitDestructible();
1453     return activeEnginePriv->objectClass->newQObject(obj, QMetaType::QObjectStar);
1454 }
1455
1456 /*!
1457 \qmlmethod bool Qt::isQtObject(object)
1458 Returns true if \c object is a valid reference to a Qt or QML object, otherwise false.
1459 */
1460 QScriptValue QDeclarativeEnginePrivate::isQtObject(QScriptContext *ctxt, QScriptEngine *engine)
1461 {
1462     if (ctxt->argumentCount() == 0)
1463         return QScriptValue(engine, false);
1464
1465     return QScriptValue(engine, 0 != ctxt->argument(0).toQObject());
1466 }
1467
1468 /*!
1469 \qmlmethod Qt::vector3d(real x, real y, real z)
1470 Returns a Vector3D with the specified \c x, \c y and \c z.
1471 */
1472 QScriptValue QDeclarativeEnginePrivate::vector3d(QScriptContext *ctxt, QScriptEngine *engine)
1473 {
1474     if(ctxt->argumentCount() != 3)
1475         return ctxt->throwError(QLatin1String("Qt.vector(): Invalid arguments"));
1476     qsreal x = ctxt->argument(0).toNumber();
1477     qsreal y = ctxt->argument(1).toNumber();
1478     qsreal z = ctxt->argument(2).toNumber();
1479     return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QVector3D(x, y, z)));
1480 }
1481
1482 /*!
1483 \qmlmethod string Qt::formatDate(datetime date, variant format)
1484
1485 Returns a string representation of \c date, optionally formatted according
1486 to \c format.
1487
1488 The \a date parameter may be a JavaScript \c Date object, a \l{date}{date}
1489 property, a QDate, or QDateTime value. The \a format parameter may be any of
1490 the possible format values as described for
1491 \l{QML:Qt::formatDateTime()}{Qt.formatDateTime()}.
1492
1493 If \a format is not specified, \a date is formatted using
1494 \l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}.
1495 */
1496 #ifndef QT_NO_DATESTRING
1497 QScriptValue QDeclarativeEnginePrivate::formatDate(QScriptContext*ctxt, QScriptEngine*engine)
1498 {
1499     int argCount = ctxt->argumentCount();
1500     if(argCount == 0 || argCount > 2)
1501         return ctxt->throwError(QLatin1String("Qt.formatDate(): Invalid arguments"));
1502
1503     QDate date = ctxt->argument(0).toDateTime().date();
1504     Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
1505     if (argCount == 2) {
1506         QScriptValue formatArg = ctxt->argument(1);
1507         if (formatArg.isString()) {
1508             QString format = formatArg.toString();
1509             return engine->newVariant(QVariant::fromValue(date.toString(format)));
1510         } else if (formatArg.isNumber()) {
1511             enumFormat = Qt::DateFormat(formatArg.toUInt32());
1512         } else {
1513             return ctxt->throwError(QLatin1String("Qt.formatDate(): Invalid date format"));
1514         }
1515     }
1516     return engine->newVariant(QVariant::fromValue(date.toString(enumFormat)));
1517 }
1518
1519 /*!
1520 \qmlmethod string Qt::formatTime(datetime time, variant format)
1521
1522 Returns a string representation of \c time, optionally formatted according to
1523 \c format.
1524
1525 The \a time parameter may be a JavaScript \c Date object, a QTime, or QDateTime
1526 value. The \a format parameter may be any of the possible format values as
1527 described for \l{QML:Qt::formatDateTime()}{Qt.formatDateTime()}.
1528
1529 If \a format is not specified, \a time is formatted using
1530 \l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}.
1531 */
1532 QScriptValue QDeclarativeEnginePrivate::formatTime(QScriptContext*ctxt, QScriptEngine*engine)
1533 {
1534     int argCount = ctxt->argumentCount();
1535     if(argCount == 0 || argCount > 2)
1536         return ctxt->throwError(QLatin1String("Qt.formatTime(): Invalid arguments"));
1537
1538     QTime time;
1539     QScriptValue sv = ctxt->argument(0);
1540     if (sv.isDate())
1541         time = sv.toDateTime().time();
1542     else if (sv.toVariant().type() == QVariant::Time)
1543         time = sv.toVariant().toTime();
1544
1545     Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
1546     if (argCount == 2) {
1547         QScriptValue formatArg = ctxt->argument(1);
1548         if (formatArg.isString()) {
1549             QString format = formatArg.toString();
1550             return engine->newVariant(QVariant::fromValue(time.toString(format)));
1551         } else if (formatArg.isNumber()) {
1552             enumFormat = Qt::DateFormat(formatArg.toUInt32());
1553         } else {
1554             return ctxt->throwError(QLatin1String("Qt.formatTime(): Invalid time format"));
1555         }
1556     }
1557     return engine->newVariant(QVariant::fromValue(time.toString(enumFormat)));
1558 }
1559
1560 /*!
1561 \qmlmethod string Qt::formatDateTime(datetime dateTime, variant format)
1562
1563 Returns a string representation of \c datetime, optionally formatted according to
1564 \c format.
1565
1566 The \a date parameter may be a JavaScript \c Date object, a \l{date}{date}
1567 property, a QDate, QTime, or QDateTime value.
1568
1569 If \a format is not provided, \a dateTime is formatted using
1570 \l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}. Otherwise,
1571 \a format should be either.
1572
1573 \list
1574 \o One of the Qt::DateFormat enumeration values, such as
1575    \c Qt.DefaultLocaleShortDate or \c Qt.ISODate
1576 \o A string that specifies the format of the returned string, as detailed below.
1577 \endlist
1578
1579 If \a format specifies a format string, it should use the following expressions
1580 to specify the date:
1581
1582     \table
1583     \header \i Expression \i Output
1584     \row \i d \i the day as number without a leading zero (1 to 31)
1585     \row \i dd \i the day as number with a leading zero (01 to 31)
1586     \row \i ddd
1587             \i the abbreviated localized day name (e.g. 'Mon' to 'Sun').
1588             Uses QDate::shortDayName().
1589     \row \i dddd
1590             \i the long localized day name (e.g. 'Monday' to 'Qt::Sunday').
1591             Uses QDate::longDayName().
1592     \row \i M \i the month as number without a leading zero (1-12)
1593     \row \i MM \i the month as number with a leading zero (01-12)
1594     \row \i MMM
1595             \i the abbreviated localized month name (e.g. 'Jan' to 'Dec').
1596             Uses QDate::shortMonthName().
1597     \row \i MMMM
1598             \i the long localized month name (e.g. 'January' to 'December').
1599             Uses QDate::longMonthName().
1600     \row \i yy \i the year as two digit number (00-99)
1601     \row \i yyyy \i the year as four digit number
1602     \endtable
1603
1604 In addition the following expressions can be used to specify the time:
1605
1606     \table
1607     \header \i Expression \i Output
1608     \row \i h
1609          \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
1610     \row \i hh
1611          \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
1612     \row \i m \i the minute without a leading zero (0 to 59)
1613     \row \i mm \i the minute with a leading zero (00 to 59)
1614     \row \i s \i the second without a leading zero (0 to 59)
1615     \row \i ss \i the second with a leading zero (00 to 59)
1616     \row \i z \i the milliseconds without leading zeroes (0 to 999)
1617     \row \i zzz \i the milliseconds with leading zeroes (000 to 999)
1618     \row \i AP
1619             \i use AM/PM display. \e AP will be replaced by either "AM" or "PM".
1620     \row \i ap
1621             \i use am/pm display. \e ap will be replaced by either "am" or "pm".
1622     \endtable
1623
1624     All other input characters will be ignored. Any sequence of characters that
1625     are enclosed in single quotes will be treated as text and not be used as an
1626     expression. Two consecutive single quotes ("''") are replaced by a single quote
1627     in the output.
1628
1629 For example, if the following date/time value was specified:
1630
1631     \code
1632     // 21 May 2001 14:13:09
1633     var dateTime = new Date(2001, 5, 21, 14, 13, 09)
1634     \endcode
1635
1636 This \a dateTime value could be passed to \c Qt.formatDateTime(),
1637 \l {QML:Qt::formatDate()}{Qt.formatDate()} or \l {QML:Qt::formatTime()}{Qt.formatTime()}
1638 with the \a format values below to produce the following results:
1639
1640     \table
1641     \header \i Format \i Result
1642     \row \i "dd.MM.yyyy"      \i 21.05.2001
1643     \row \i "ddd MMMM d yy"   \i Tue May 21 01
1644     \row \i "hh:mm:ss.zzz"    \i 14:13:09.042
1645     \row \i "h:m:s ap"        \i 2:13:9 pm
1646     \endtable
1647 */
1648 QScriptValue QDeclarativeEnginePrivate::formatDateTime(QScriptContext*ctxt, QScriptEngine*engine)
1649 {
1650     int argCount = ctxt->argumentCount();
1651     if(argCount == 0 || argCount > 2)
1652         return ctxt->throwError(QLatin1String("Qt.formatDateTime(): Invalid arguments"));
1653
1654     QDateTime date = ctxt->argument(0).toDateTime();
1655     Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
1656     if (argCount == 2) {
1657         QScriptValue formatArg = ctxt->argument(1);
1658         if (formatArg.isString()) {
1659             QString format = formatArg.toString();
1660             return engine->newVariant(QVariant::fromValue(date.toString(format)));
1661         } else if (formatArg.isNumber()) {
1662             enumFormat = Qt::DateFormat(formatArg.toUInt32());
1663         } else {
1664             return ctxt->throwError(QLatin1String("Qt.formatDateTime(): Invalid datetime format"));
1665         }
1666     }
1667     return engine->newVariant(QVariant::fromValue(date.toString(enumFormat)));
1668 }
1669 #endif // QT_NO_DATESTRING
1670
1671 /*!
1672 \qmlmethod color Qt::rgba(real red, real green, real blue, real alpha)
1673
1674 Returns a color with the specified \c red, \c green, \c blue and \c alpha components.
1675 All components should be in the range 0-1 inclusive.
1676 */
1677 QScriptValue QDeclarativeEnginePrivate::rgba(QScriptContext *ctxt, QScriptEngine *engine)
1678 {
1679     int argCount = ctxt->argumentCount();
1680     if(argCount < 3 || argCount > 4)
1681         return ctxt->throwError(QLatin1String("Qt.rgba(): Invalid arguments"));
1682     qsreal r = ctxt->argument(0).toNumber();
1683     qsreal g = ctxt->argument(1).toNumber();
1684     qsreal b = ctxt->argument(2).toNumber();
1685     qsreal a = (argCount == 4) ? ctxt->argument(3).toNumber() : 1;
1686
1687     if (r < 0.0) r=0.0;
1688     if (r > 1.0) r=1.0;
1689     if (g < 0.0) g=0.0;
1690     if (g > 1.0) g=1.0;
1691     if (b < 0.0) b=0.0;
1692     if (b > 1.0) b=1.0;
1693     if (a < 0.0) a=0.0;
1694     if (a > 1.0) a=1.0;
1695
1696     return engine->toScriptValue(QVariant::fromValue(QColor::fromRgbF(r, g, b, a)));
1697 }
1698
1699 /*!
1700 \qmlmethod color Qt::hsla(real hue, real saturation, real lightness, real alpha)
1701
1702 Returns a color with the specified \c hue, \c saturation, \c lightness and \c alpha components.
1703 All components should be in the range 0-1 inclusive.
1704 */
1705 QScriptValue QDeclarativeEnginePrivate::hsla(QScriptContext *ctxt, QScriptEngine *engine)
1706 {
1707     int argCount = ctxt->argumentCount();
1708     if(argCount < 3 || argCount > 4)
1709         return ctxt->throwError(QLatin1String("Qt.hsla(): Invalid arguments"));
1710     qsreal h = ctxt->argument(0).toNumber();
1711     qsreal s = ctxt->argument(1).toNumber();
1712     qsreal l = ctxt->argument(2).toNumber();
1713     qsreal a = (argCount == 4) ? ctxt->argument(3).toNumber() : 1;
1714
1715     if (h < 0.0) h=0.0;
1716     if (h > 1.0) h=1.0;
1717     if (s < 0.0) s=0.0;
1718     if (s > 1.0) s=1.0;
1719     if (l < 0.0) l=0.0;
1720     if (l > 1.0) l=1.0;
1721     if (a < 0.0) a=0.0;
1722     if (a > 1.0) a=1.0;
1723
1724     return engine->toScriptValue(QVariant::fromValue(QColor::fromHslF(h, s, l, a)));
1725 }
1726
1727 /*!
1728 \qmlmethod rect Qt::rect(int x, int y, int width, int height)
1729
1730 Returns a \c rect with the top-left corner at \c x, \c y and the specified \c width and \c height.
1731
1732 The returned object has \c x, \c y, \c width and \c height attributes with the given values.
1733 */
1734 QScriptValue QDeclarativeEnginePrivate::rect(QScriptContext *ctxt, QScriptEngine *engine)
1735 {
1736     if(ctxt->argumentCount() != 4)
1737         return ctxt->throwError(QLatin1String("Qt.rect(): Invalid arguments"));
1738
1739     qsreal x = ctxt->argument(0).toNumber();
1740     qsreal y = ctxt->argument(1).toNumber();
1741     qsreal w = ctxt->argument(2).toNumber();
1742     qsreal h = ctxt->argument(3).toNumber();
1743
1744     return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QRectF(x, y, w, h)));
1745 }
1746
1747 /*!
1748 \qmlmethod point Qt::point(int x, int y)
1749 Returns a Point with the specified \c x and \c y coordinates.
1750 */
1751 QScriptValue QDeclarativeEnginePrivate::point(QScriptContext *ctxt, QScriptEngine *engine)
1752 {
1753     if(ctxt->argumentCount() != 2)
1754         return ctxt->throwError(QLatin1String("Qt.point(): Invalid arguments"));
1755     qsreal x = ctxt->argument(0).toNumber();
1756     qsreal y = ctxt->argument(1).toNumber();
1757     return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QPointF(x, y)));
1758 }
1759
1760 /*!
1761 \qmlmethod Qt::size(int width, int height)
1762 Returns a Size with the specified \c width and \c height.
1763 */
1764 QScriptValue QDeclarativeEnginePrivate::size(QScriptContext *ctxt, QScriptEngine *engine)
1765 {
1766     if(ctxt->argumentCount() != 2)
1767         return ctxt->throwError(QLatin1String("Qt.size(): Invalid arguments"));
1768     qsreal w = ctxt->argument(0).toNumber();
1769     qsreal h = ctxt->argument(1).toNumber();
1770     return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QSizeF(w, h)));
1771 }
1772
1773 /*!
1774 \qmlmethod color Qt::lighter(color baseColor, real factor)
1775 Returns a color lighter than \c baseColor by the \c factor provided.
1776
1777 If the factor is greater than 1.0, this functions returns a lighter color.
1778 Setting factor to 1.5 returns a color that is 50% brighter. If the factor is less than 1.0,
1779 the return color is darker, but we recommend using the Qt.darker() function for this purpose.
1780 If the factor is 0 or negative, the return value is unspecified.
1781
1782 The function converts the current RGB color to HSV, multiplies the value (V) component
1783 by factor and converts the color back to RGB.
1784
1785 If \c factor is not supplied, returns a color 50% lighter than \c baseColor (factor 1.5).
1786 */
1787 QScriptValue QDeclarativeEnginePrivate::lighter(QScriptContext *ctxt, QScriptEngine *engine)
1788 {
1789     if(ctxt->argumentCount() != 1 && ctxt->argumentCount() != 2)
1790         return ctxt->throwError(QLatin1String("Qt.lighter(): Invalid arguments"));
1791     QVariant v = ctxt->argument(0).toVariant();
1792     QColor color;
1793     if (v.userType() == QVariant::Color)
1794         color = v.value<QColor>();
1795     else if (v.userType() == QVariant::String) {
1796         bool ok;
1797         color = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
1798         if (!ok)
1799             return engine->nullValue();
1800     } else
1801         return engine->nullValue();
1802     qsreal factor = 1.5;
1803     if (ctxt->argumentCount() == 2)
1804         factor = ctxt->argument(1).toNumber();
1805     color = color.lighter(int(qRound(factor*100.)));
1806     return engine->toScriptValue(QVariant::fromValue(color));
1807 }
1808
1809 /*!
1810 \qmlmethod color Qt::darker(color baseColor, real factor)
1811 Returns a color darker than \c baseColor by the \c factor provided.
1812
1813 If the factor is greater than 1.0, this function returns a darker color.
1814 Setting factor to 3.0 returns a color that has one-third the brightness.
1815 If the factor is less than 1.0, the return color is lighter, but we recommend using
1816 the Qt.lighter() function for this purpose. If the factor is 0 or negative, the return
1817 value is unspecified.
1818
1819 The function converts the current RGB color to HSV, divides the value (V) component
1820 by factor and converts the color back to RGB.
1821
1822 If \c factor is not supplied, returns a color 50% darker than \c baseColor (factor 2.0).
1823 */
1824 QScriptValue QDeclarativeEnginePrivate::darker(QScriptContext *ctxt, QScriptEngine *engine)
1825 {
1826     if(ctxt->argumentCount() != 1 && ctxt->argumentCount() != 2)
1827         return ctxt->throwError(QLatin1String("Qt.darker(): Invalid arguments"));
1828     QVariant v = ctxt->argument(0).toVariant();
1829     QColor color;
1830     if (v.userType() == QVariant::Color)
1831         color = v.value<QColor>();
1832     else if (v.userType() == QVariant::String) {
1833         bool ok;
1834         color = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
1835         if (!ok)
1836             return engine->nullValue();
1837     } else
1838         return engine->nullValue();
1839     qsreal factor = 2.0;
1840     if (ctxt->argumentCount() == 2)
1841         factor = ctxt->argument(1).toNumber();
1842     color = color.darker(int(qRound(factor*100.)));
1843     return engine->toScriptValue(QVariant::fromValue(color));
1844 }
1845
1846 /*!
1847 \qmlmethod bool Qt::openUrlExternally(url target)
1848 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.
1849 */
1850 QScriptValue QDeclarativeEnginePrivate::desktopOpenUrl(QScriptContext *ctxt, QScriptEngine *e)
1851 {
1852     if(ctxt->argumentCount() < 1)
1853         return QScriptValue(e, false);
1854     bool ret = false;
1855 #ifndef QT_NO_DESKTOPSERVICES
1856     ret = QDesktopServices::openUrl(QDeclarativeScriptEngine::get(e)->resolvedUrl(ctxt, QUrl(ctxt->argument(0).toString())));
1857 #endif
1858     return QScriptValue(e, ret);
1859 }
1860
1861 /*!
1862 \qmlmethod list<string> Qt::fontFamilies()
1863 Returns a list of the font families available to the application.
1864 */
1865
1866 QScriptValue QDeclarativeEnginePrivate::fontFamilies(QScriptContext *ctxt, QScriptEngine *e)
1867 {
1868     if(ctxt->argumentCount() != 0)
1869         return ctxt->throwError(QLatin1String("Qt.fontFamilies(): Invalid arguments"));
1870
1871     QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(e);
1872     QFontDatabase database;
1873     return p->scriptValueFromVariant(database.families());
1874 }
1875
1876 /*!
1877 \qmlmethod string Qt::md5(data)
1878 Returns a hex string of the md5 hash of \c data.
1879 */
1880 QScriptValue QDeclarativeEnginePrivate::md5(QScriptContext *ctxt, QScriptEngine *)
1881 {
1882     if (ctxt->argumentCount() != 1)
1883         return ctxt->throwError(QLatin1String("Qt.md5(): Invalid arguments"));
1884
1885     QByteArray data = ctxt->argument(0).toString().toUtf8();
1886     QByteArray result = QCryptographicHash::hash(data, QCryptographicHash::Md5);
1887
1888     return QScriptValue(QLatin1String(result.toHex()));
1889 }
1890
1891 /*!
1892 \qmlmethod string Qt::btoa(data)
1893 Binary to ASCII - this function returns a base64 encoding of \c data.
1894 */
1895 QScriptValue QDeclarativeEnginePrivate::btoa(QScriptContext *ctxt, QScriptEngine *)
1896 {
1897     if (ctxt->argumentCount() != 1)
1898         return ctxt->throwError(QLatin1String("Qt.btoa(): Invalid arguments"));
1899
1900     QByteArray data = ctxt->argument(0).toString().toUtf8();
1901
1902     return QScriptValue(QLatin1String(data.toBase64()));
1903 }
1904
1905 /*!
1906 \qmlmethod string Qt::atob(data)
1907 ASCII to binary - this function returns a base64 decoding of \c data.
1908 */
1909
1910 QScriptValue QDeclarativeEnginePrivate::atob(QScriptContext *ctxt, QScriptEngine *)
1911 {
1912     if (ctxt->argumentCount() != 1)
1913         return ctxt->throwError(QLatin1String("Qt.atob(): Invalid arguments"));
1914
1915     QByteArray data = ctxt->argument(0).toString().toUtf8();
1916
1917     return QScriptValue(QLatin1String(QByteArray::fromBase64(data)));
1918 }
1919
1920 QScriptValue QDeclarativeEnginePrivate::consoleLog(QScriptContext *ctxt, QScriptEngine *e)
1921 {
1922     if(ctxt->argumentCount() < 1)
1923         return e->newVariant(QVariant(false));
1924
1925     QByteArray msg;
1926
1927     for (int i=0; i<ctxt->argumentCount(); ++i) {
1928         if (!msg.isEmpty()) msg += ' ';
1929         msg += ctxt->argument(i).toString().toLocal8Bit();
1930         // does not support firebug "%[a-z]" formatting, since firebug really
1931         // does just ignore the format letter, which makes it pointless.
1932     }
1933
1934     qDebug("%s",msg.constData());
1935
1936     return e->newVariant(QVariant(true));
1937 }
1938
1939 void QDeclarativeEnginePrivate::sendQuit()
1940 {
1941     Q_Q(QDeclarativeEngine);
1942     emit q->quit();
1943     if (q->receivers(SIGNAL(quit())) == 0) {
1944         qWarning("Signal QDeclarativeEngine::quit() emitted, but no receivers connected to handle it.");
1945     }
1946 }
1947
1948 static void dumpwarning(const QDeclarativeError &error)
1949 {
1950     qWarning().nospace() << qPrintable(error.toString());
1951 }
1952
1953 static void dumpwarning(const QList<QDeclarativeError> &errors)
1954 {
1955     for (int ii = 0; ii < errors.count(); ++ii)
1956         dumpwarning(errors.at(ii));
1957 }
1958
1959 void QDeclarativeEnginePrivate::warning(const QDeclarativeError &error)
1960 {
1961     Q_Q(QDeclarativeEngine);
1962     q->warnings(QList<QDeclarativeError>() << error);
1963     if (outputWarningsToStdErr)
1964         dumpwarning(error);
1965 }
1966
1967 void QDeclarativeEnginePrivate::warning(const QList<QDeclarativeError> &errors)
1968 {
1969     Q_Q(QDeclarativeEngine);
1970     q->warnings(errors);
1971     if (outputWarningsToStdErr)
1972         dumpwarning(errors);
1973 }
1974
1975 void QDeclarativeEnginePrivate::warning(QDeclarativeEngine *engine, const QDeclarativeError &error)
1976 {
1977     if (engine)
1978         QDeclarativeEnginePrivate::get(engine)->warning(error);
1979     else
1980         dumpwarning(error);
1981 }
1982
1983 void QDeclarativeEnginePrivate::warning(QDeclarativeEngine *engine, const QList<QDeclarativeError> &error)
1984 {
1985     if (engine)
1986         QDeclarativeEnginePrivate::get(engine)->warning(error);
1987     else
1988         dumpwarning(error);
1989 }
1990
1991 void QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate *engine, const QDeclarativeError &error)
1992 {
1993     if (engine)
1994         engine->warning(error);
1995     else
1996         dumpwarning(error);
1997 }
1998
1999 void QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate *engine, const QList<QDeclarativeError> &error)
2000 {
2001     if (engine)
2002         engine->warning(error);
2003     else
2004         dumpwarning(error);
2005 }
2006
2007 /*!
2008 \qmlmethod Qt::quit()
2009 This function causes the QDeclarativeEngine::quit() signal to be emitted.
2010 Within the \l {QML Viewer}, this causes the launcher application to exit;
2011 to quit a C++ application when this method is called, connect the
2012 QDeclarativeEngine::quit() signal to the QCoreApplication::quit() slot.
2013 */
2014
2015 QScriptValue QDeclarativeEnginePrivate::quit(QScriptContext * /*ctxt*/, QScriptEngine *e)
2016 {
2017     QDeclarativeEnginePrivate *qe = get (e);
2018     qe->sendQuit();
2019     return QScriptValue();
2020 }
2021
2022 /*!
2023     \qmlmethod color Qt::tint(color baseColor, color tintColor)
2024     This function allows tinting one color with another.
2025
2026     The tint color should usually be mostly transparent, or you will not be
2027     able to see the underlying color. The below example provides a slight red
2028     tint by having the tint color be pure red which is only 1/16th opaque.
2029
2030     \qml
2031     Item {
2032         Rectangle {
2033             x: 0; width: 80; height: 80
2034             color: "lightsteelblue"
2035         }
2036         Rectangle {
2037             x: 100; width: 80; height: 80
2038             color: Qt.tint("lightsteelblue", "#10FF0000")
2039         }
2040     }
2041     \endqml
2042     \image declarative-rect_tint.png
2043
2044     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.
2045 */
2046 QScriptValue QDeclarativeEnginePrivate::tint(QScriptContext *ctxt, QScriptEngine *engine)
2047 {
2048     if(ctxt->argumentCount() != 2)
2049         return ctxt->throwError(QLatin1String("Qt.tint(): Invalid arguments"));
2050     //get color
2051     QVariant v = ctxt->argument(0).toVariant();
2052     QColor color;
2053     if (v.userType() == QVariant::Color)
2054         color = v.value<QColor>();
2055     else if (v.userType() == QVariant::String) {
2056         bool ok;
2057         color = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
2058         if (!ok)
2059             return engine->nullValue();
2060     } else
2061         return engine->nullValue();
2062
2063     //get tint color
2064     v = ctxt->argument(1).toVariant();
2065     QColor tintColor;
2066     if (v.userType() == QVariant::Color)
2067         tintColor = v.value<QColor>();
2068     else if (v.userType() == QVariant::String) {
2069         bool ok;
2070         tintColor = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
2071         if (!ok)
2072             return engine->nullValue();
2073     } else
2074         return engine->nullValue();
2075
2076     //tint
2077     QColor finalColor;
2078     int a = tintColor.alpha();
2079     if (a == 0xFF)
2080         finalColor = tintColor;
2081     else if (a == 0x00)
2082         finalColor = color;
2083     else {
2084         qreal a = tintColor.alphaF();
2085         qreal inv_a = 1.0 - a;
2086
2087         finalColor.setRgbF(tintColor.redF() * a + color.redF() * inv_a,
2088                            tintColor.greenF() * a + color.greenF() * inv_a,
2089                            tintColor.blueF() * a + color.blueF() * inv_a,
2090                            a + inv_a * color.alphaF());
2091     }
2092
2093     return engine->toScriptValue(QVariant::fromValue(finalColor));
2094 }
2095
2096 QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &val)
2097 {
2098     if (variantIsScarceResource(val)) {
2099         return scarceResourceClass->newScarceResource(val);
2100     } else if (val.userType() == qMetaTypeId<QDeclarativeListReference>()) {
2101         QDeclarativeListReferencePrivate *p =
2102             QDeclarativeListReferencePrivate::get((QDeclarativeListReference*)val.constData());
2103         if (p->object) {
2104             return listClass->newList(p->property, p->propertyType);
2105         } else {
2106             return scriptEngine.nullValue();
2107         }
2108     } else if (val.userType() == qMetaTypeId<QList<QObject *> >()) {
2109         const QList<QObject *> &list = *(QList<QObject *>*)val.constData();
2110         QScriptValue rv = scriptEngine.newArray(list.count());
2111         for (int ii = 0; ii < list.count(); ++ii) {
2112             QObject *object = list.at(ii);
2113             rv.setProperty(ii, objectClass->newQObject(object));
2114         }
2115         return rv;
2116     } else if (QDeclarativeValueType *vt = valueTypes[val.userType()]) {
2117         return valueTypeClass->newObject(val, vt);
2118     }
2119
2120     bool objOk;
2121     QObject *obj = QDeclarativeMetaType::toQObject(val, &objOk);
2122     if (objOk) {
2123         return objectClass->newQObject(obj);
2124     } else {
2125         return scriptEngine.toScriptValue(val);
2126     }
2127 }
2128
2129 /*
2130    If the variant is a scarce resource (consumes a large amount of memory, or
2131    only a limited number of them can be held in memory at any given time without
2132    exhausting supply for future use) we need to release the scarce resource
2133    after evaluation of the javascript binding is complete.
2134  */
2135 bool QDeclarativeEnginePrivate::variantIsScarceResource(const QVariant& val)
2136 {
2137     if (val.type() == QVariant::Pixmap) {
2138         return true;
2139     } else if (val.type() == QVariant::Image) {
2140         return true;
2141     }
2142
2143     return false;
2144 }
2145
2146 /*
2147    This function should be called prior to evaluation of any js expression,
2148    so that scarce resources are not freed prematurely (eg, if there is a
2149    nested javascript expression).
2150  */
2151 void QDeclarativeEnginePrivate::referenceScarceResources()
2152 {
2153     scarceResourcesRefCount += 1;
2154 }
2155
2156 /*
2157    This function should be called after evaluation of the js expression is
2158    complete, and so the scarce resources may be freed safely.
2159  */
2160 void QDeclarativeEnginePrivate::dereferenceScarceResources()
2161 {
2162     Q_ASSERT(scarceResourcesRefCount > 0);
2163     scarceResourcesRefCount -= 1;
2164
2165     // if the refcount is zero, then evaluation of the "top level"
2166     // expression must have completed.  We can safely release the
2167     // scarce resources.
2168     if (scarceResourcesRefCount == 0) {
2169         // iterate through the list and release them all.
2170         // note that the actual SRD is owned by the JS engine,
2171         // so we cannot delete the SRD; but we can free the
2172         // memory used by the variant in the SRD.
2173         ScarceResourceData *srd = 0;
2174         while (scarceResources) {
2175             srd = scarceResources; // srd points to the "old" (current) head of the list
2176             scarceResources = srd->next; // srd->next is the "new" head of the list
2177             if (srd->next) srd->next->prev = &scarceResources; // newHead->prev = listptr.
2178             srd->next = 0;
2179             srd->prev = 0;
2180             srd->releaseResource(); // release the old head node.
2181         }
2182     }
2183 }
2184
2185 QVariant QDeclarativeEnginePrivate::scriptValueToVariant(const QScriptValue &val, int hint)
2186 {
2187     QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(val);
2188     if (dc == objectClass)
2189         return QVariant::fromValue(objectClass->toQObject(val));
2190     else if (dc == scarceResourceClass)
2191         return scarceResourceClass->toVariant(val);
2192     else if (dc == valueTypeClass)
2193         return valueTypeClass->toVariant(val);
2194     else if (dc == contextClass)
2195         return QVariant();
2196
2197     // Convert to a QList<QObject*> only if val is an array and we were explicitly hinted
2198     if (hint == qMetaTypeId<QList<QObject *> >() && val.isArray()) {
2199         QList<QObject *> list;
2200         int length = val.property(QLatin1String("length")).toInt32();
2201         for (int ii = 0; ii < length; ++ii) {
2202             QScriptValue arrayItem = val.property(ii);
2203             QObject *d = arrayItem.toQObject();
2204             list << d;
2205         }
2206         return QVariant::fromValue(list);
2207     }
2208
2209     return val.toVariant();
2210 }
2211
2212 /*!
2213   Adds \a path as a directory where the engine searches for
2214   installed modules in a URL-based directory structure.
2215   The \a path may be a local filesystem directory or a URL.
2216
2217   The newly added \a path will be first in the importPathList().
2218
2219   \sa setImportPathList(), {QML Modules}
2220 */
2221 void QDeclarativeEngine::addImportPath(const QString& path)
2222 {
2223     Q_D(QDeclarativeEngine);
2224     d->importDatabase.addImportPath(path);
2225 }
2226
2227 /*!
2228   Returns the list of directories where the engine searches for
2229   installed modules in a URL-based directory structure.
2230
2231   For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
2232   imports \c com.mycompany.Feature will cause the QDeclarativeEngine to look
2233   in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
2234   provided by that module. A \c qmldir file is required for defining the
2235   type version mapping and possibly declarative extensions plugins.
2236
2237   By default, the list contains the directory of the application executable,
2238   paths specified in the \c QML_IMPORT_PATH environment variable,
2239   and the builtin \c ImportsPath from QLibraryInfo.
2240
2241   \sa addImportPath() setImportPathList()
2242 */
2243 QStringList QDeclarativeEngine::importPathList() const
2244 {
2245     Q_D(const QDeclarativeEngine);
2246     return d->importDatabase.importPathList();
2247 }
2248
2249 /*!
2250   Sets \a paths as the list of directories where the engine searches for
2251   installed modules in a URL-based directory structure.
2252
2253   By default, the list contains the directory of the application executable,
2254   paths specified in the \c QML_IMPORT_PATH environment variable,
2255   and the builtin \c ImportsPath from QLibraryInfo.
2256
2257   \sa importPathList() addImportPath()
2258   */
2259 void QDeclarativeEngine::setImportPathList(const QStringList &paths)
2260 {
2261     Q_D(QDeclarativeEngine);
2262     d->importDatabase.setImportPathList(paths);
2263 }
2264
2265
2266 /*!
2267   Adds \a path as a directory where the engine searches for
2268   native plugins for imported modules (referenced in the \c qmldir file).
2269
2270   By default, the list contains only \c .,  i.e. the engine searches
2271   in the directory of the \c qmldir file itself.
2272
2273   The newly added \a path will be first in the pluginPathList().
2274
2275   \sa setPluginPathList()
2276 */
2277 void QDeclarativeEngine::addPluginPath(const QString& path)
2278 {
2279     Q_D(QDeclarativeEngine);
2280     d->importDatabase.addPluginPath(path);
2281 }
2282
2283
2284 /*!
2285   Returns the list of directories where the engine searches for
2286   native plugins for imported modules (referenced in the \c qmldir file).
2287
2288   By default, the list contains only \c .,  i.e. the engine searches
2289   in the directory of the \c qmldir file itself.
2290
2291   \sa addPluginPath() setPluginPathList()
2292 */
2293 QStringList QDeclarativeEngine::pluginPathList() const
2294 {
2295     Q_D(const QDeclarativeEngine);
2296     return d->importDatabase.pluginPathList();
2297 }
2298
2299 /*!
2300   Sets the list of directories where the engine searches for
2301   native plugins for imported modules (referenced in the \c qmldir file)
2302   to \a paths.
2303
2304   By default, the list contains only \c .,  i.e. the engine searches
2305   in the directory of the \c qmldir file itself.
2306
2307   \sa pluginPathList() addPluginPath()
2308   */
2309 void QDeclarativeEngine::setPluginPathList(const QStringList &paths)
2310 {
2311     Q_D(QDeclarativeEngine);
2312     d->importDatabase.setPluginPathList(paths);
2313 }
2314
2315
2316 /*!
2317   Imports the plugin named \a filePath with the \a uri provided.
2318   Returns true if the plugin was successfully imported; otherwise returns false.
2319
2320   On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
2321
2322   The plugin has to be a Qt plugin which implements the QDeclarativeExtensionPlugin interface.
2323 */
2324 bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &uri, QList<QDeclarativeError> *errors)
2325 {
2326     Q_D(QDeclarativeEngine);
2327     return d->importDatabase.importPlugin(filePath, uri, errors);
2328 }
2329
2330 /*!
2331   Imports the plugin named \a filePath with the \a uri provided.
2332   Returns true if the plugin was successfully imported; otherwise returns false.
2333
2334   On failure and if non-null, *\a errorString will be set to a message describing the failure.
2335
2336   The plugin has to be a Qt plugin which implements the QDeclarativeExtensionPlugin interface.
2337 */
2338 bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
2339 {
2340     Q_D(QDeclarativeEngine);
2341     QList<QDeclarativeError> errors;
2342     bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
2343     if (!errors.isEmpty()) {
2344         QString builtError;
2345         for (int i = 0; i < errors.size(); ++i) {
2346             builtError = QString(QLatin1String("%1\n        %2"))
2347                     .arg(builtError)
2348                     .arg(errors.at(i).toString());
2349         }
2350         *errorString = builtError;
2351     }
2352     return retn;
2353 }
2354
2355 /*!
2356   \property QDeclarativeEngine::offlineStoragePath
2357   \brief the directory for storing offline user data
2358
2359   Returns the directory where SQL and other offline
2360   storage is placed.
2361
2362   QDeclarativeWebView and the SQL databases created with openDatabase()
2363   are stored here.
2364
2365   The default is QML/OfflineStorage in the platform-standard
2366   user application data directory.
2367
2368   Note that the path may not currently exist on the filesystem, so
2369   callers wanting to \e create new files at this location should create
2370   it first - see QDir::mkpath().
2371 */
2372 void QDeclarativeEngine::setOfflineStoragePath(const QString& dir)
2373 {
2374     Q_D(QDeclarativeEngine);
2375     d->scriptEngine.offlineStoragePath = dir;
2376 }
2377
2378 QString QDeclarativeEngine::offlineStoragePath() const
2379 {
2380     Q_D(const QDeclarativeEngine);
2381     return d->scriptEngine.offlineStoragePath;
2382 }
2383
2384 static void voidptr_destructor(void *v)
2385 {
2386     void **ptr = (void **)v;
2387     delete ptr;
2388 }
2389
2390 static void *voidptr_constructor(const void *v)
2391 {
2392     if (!v) {
2393         return new void*;
2394     } else {
2395         return new void*(*(void **)v);
2396     }
2397 }
2398
2399 QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(const QMetaObject *mo)
2400 {
2401     Q_Q(QDeclarativeEngine);
2402
2403     if (!mo->superClass()) {
2404         QDeclarativePropertyCache *rv = new QDeclarativePropertyCache(q, mo);
2405         propertyCache.insert(mo, rv);
2406         return rv;
2407     } else {
2408         QDeclarativePropertyCache *super = cache(mo->superClass());
2409         QDeclarativePropertyCache *rv = super->copy();
2410         rv->append(q, mo);
2411         propertyCache.insert(mo, rv);
2412         return rv;
2413     }
2414 }
2415
2416 QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(QDeclarativeType *type, int minorVersion,
2417                                                                   QDeclarativeError &error)
2418 {
2419     QList<QDeclarativeType *> types;
2420
2421     int maxMinorVersion = 0;
2422
2423     const QMetaObject *metaObject = type->metaObject();
2424     while (metaObject) {
2425         QDeclarativeType *t = QDeclarativeMetaType::qmlType(metaObject, type->module(),
2426                                                             type->majorVersion(), minorVersion);
2427         if (t) {
2428             maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
2429             types << t;
2430         } else {
2431             types << 0;
2432         }
2433
2434         metaObject = metaObject->superClass();
2435     }
2436
2437     if (QDeclarativePropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
2438         c->addref();
2439         typePropertyCache.insert(qMakePair(type, minorVersion), c);
2440         return c;
2441     }
2442
2443     QDeclarativePropertyCache *raw = cache(type->metaObject());
2444
2445     bool hasCopied = false;
2446
2447     for (int ii = 0; ii < types.count(); ++ii) {
2448         QDeclarativeType *currentType = types.at(ii);
2449         if (!currentType)
2450             continue;
2451
2452         int rev = currentType->metaObjectRevision();
2453         int moIndex = types.count() - 1 - ii;
2454
2455         if (raw->allowedRevisionCache[moIndex] != rev) {
2456             if (!hasCopied) {
2457                 raw = raw->copy();
2458                 hasCopied = true;
2459             }
2460             raw->allowedRevisionCache[moIndex] = rev;
2461         }
2462     }
2463
2464     // Test revision compatibility - the basic rule is:
2465     //    * Anything that is excluded, cannot overload something that is not excluded *
2466
2467     // Signals override:
2468     //    * other signals and methods of the same name.
2469     //    * properties named on<Signal Name>
2470     //    * automatic <property name>Changed notify signals
2471
2472     // Methods override:
2473     //    * other methods of the same name
2474
2475     // Properties override:
2476     //    * other elements of the same name
2477
2478     bool overloadError = false;
2479     QString overloadName;
2480
2481 #if 0
2482     for (QDeclarativePropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
2483          !overloadError && iter != raw->stringCache.end();
2484          ++iter) {
2485
2486         QDeclarativePropertyCache::Data *d = *iter;
2487         if (raw->isAllowedInRevision(d))
2488             continue; // Not excluded - no problems
2489
2490         // check that a regular "name" overload isn't happening
2491         QDeclarativePropertyCache::Data *current = d;
2492         while (!overloadError && current) {
2493             current = d->overrideData(current);
2494             if (current && raw->isAllowedInRevision(current))
2495                 overloadError = true;
2496         }
2497     }
2498 #endif
2499
2500     if (overloadError) {
2501         if (hasCopied) raw->release();
2502
2503         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."));
2504         return 0;
2505     }
2506
2507     if (!hasCopied) raw->addref();
2508     typePropertyCache.insert(qMakePair(type, minorVersion), raw);
2509
2510     if (minorVersion != maxMinorVersion) {
2511         raw->addref();
2512         typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
2513     }
2514
2515     return raw;
2516 }
2517
2518 void QDeclarativeEnginePrivate::registerCompositeType(QDeclarativeCompiledData *data)
2519 {
2520     QByteArray name = data->root->className();
2521
2522     QByteArray ptr = name + '*';
2523     QByteArray lst = "QDeclarativeListProperty<" + name + '>';
2524
2525     int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
2526                                            voidptr_constructor);
2527     int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
2528                                            voidptr_constructor);
2529
2530     m_qmlLists.insert(lst_type, ptr_type);
2531     m_compositeTypes.insert(ptr_type, data);
2532     data->addref();
2533 }
2534
2535 bool QDeclarativeEnginePrivate::isList(int t) const
2536 {
2537     return m_qmlLists.contains(t) || QDeclarativeMetaType::isList(t);
2538 }
2539
2540 int QDeclarativeEnginePrivate::listType(int t) const
2541 {
2542     QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
2543     if (iter != m_qmlLists.end())
2544         return *iter;
2545     else
2546         return QDeclarativeMetaType::listType(t);
2547 }
2548
2549 bool QDeclarativeEnginePrivate::isQObject(int t)
2550 {
2551     return m_compositeTypes.contains(t) || QDeclarativeMetaType::isQObject(t);
2552 }
2553
2554 QObject *QDeclarativeEnginePrivate::toQObject(const QVariant &v, bool *ok) const
2555 {
2556     int t = v.userType();
2557     if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
2558         if (ok) *ok = true;
2559         return *(QObject **)(v.constData());
2560     } else {
2561         return QDeclarativeMetaType::toQObject(v, ok);
2562     }
2563 }
2564
2565 QDeclarativeMetaType::TypeCategory QDeclarativeEnginePrivate::typeCategory(int t) const
2566 {
2567     if (m_compositeTypes.contains(t))
2568         return QDeclarativeMetaType::Object;
2569     else if (m_qmlLists.contains(t))
2570         return QDeclarativeMetaType::List;
2571     else
2572         return QDeclarativeMetaType::typeCategory(t);
2573 }
2574
2575 const QMetaObject *QDeclarativeEnginePrivate::rawMetaObjectForType(int t) const
2576 {
2577     QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
2578     if (iter != m_compositeTypes.end()) {
2579         return (*iter)->root;
2580     } else {
2581         QDeclarativeType *type = QDeclarativeMetaType::qmlType(t);
2582         return type?type->baseMetaObject():0;
2583     }
2584 }
2585
2586 const QMetaObject *QDeclarativeEnginePrivate::metaObjectForType(int t) const
2587 {
2588     QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
2589     if (iter != m_compositeTypes.end()) {
2590         return (*iter)->root;
2591     } else {
2592         QDeclarativeType *type = QDeclarativeMetaType::qmlType(t);
2593         return type?type->metaObject():0;
2594     }
2595 }
2596
2597 bool QDeclarative_isFileCaseCorrect(const QString &fileName)
2598 {
2599 #if defined(Q_OS_MAC) || defined(Q_OS_WIN32)
2600     QFileInfo info(fileName);
2601
2602     QString absolute = info.absoluteFilePath();
2603
2604 #if defined(Q_OS_MAC)
2605     QString canonical = info.canonicalFilePath();
2606 #elif defined(Q_OS_WIN32)
2607     wchar_t buffer[1024];
2608
2609     DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
2610     if (rv == 0 || rv >= 1024) return true;
2611     rv = ::GetLongPathName(buffer, buffer, 1024);
2612     if (rv == 0 || rv >= 1024) return true;
2613
2614     QString canonical((QChar *)buffer);
2615 #endif
2616
2617     int absoluteLength = absolute.length();
2618     int canonicalLength = canonical.length();
2619
2620     int length = qMin(absoluteLength, canonicalLength);
2621     for (int ii = 0; ii < length; ++ii) {
2622         const QChar &a = absolute.at(absoluteLength - 1 - ii);
2623         const QChar &c = canonical.at(canonicalLength - 1 - ii);
2624
2625         if (a.toLower() != c.toLower())
2626             return true;
2627         if (a != c)
2628             return false;
2629     }
2630 #else
2631     Q_UNUSED(fileName)
2632 #endif
2633     return true;
2634 }
2635
2636 QT_END_NAMESPACE