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