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