Augment Documentation
[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 static_cast<QDeclarativeImageProvider::ImageType>(-1);
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     return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QRectF(x, y, w, h)));
1744 }
1745
1746 /*!
1747 \qmlmethod point Qt::point(int x, int y)
1748 Returns a Point with the specified \c x and \c y coordinates.
1749 */
1750 QScriptValue QDeclarativeEnginePrivate::point(QScriptContext *ctxt, QScriptEngine *engine)
1751 {
1752     if(ctxt->argumentCount() != 2)
1753         return ctxt->throwError(QLatin1String("Qt.point(): Invalid arguments"));
1754     qsreal x = ctxt->argument(0).toNumber();
1755     qsreal y = ctxt->argument(1).toNumber();
1756     return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QPointF(x, y)));
1757 }
1758
1759 /*!
1760 \qmlmethod Qt::size(int width, int height)
1761 Returns a Size with the specified \c width and \c height.
1762 */
1763 QScriptValue QDeclarativeEnginePrivate::size(QScriptContext *ctxt, QScriptEngine *engine)
1764 {
1765     if(ctxt->argumentCount() != 2)
1766         return ctxt->throwError(QLatin1String("Qt.size(): Invalid arguments"));
1767     qsreal w = ctxt->argument(0).toNumber();
1768     qsreal h = ctxt->argument(1).toNumber();
1769     return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QSizeF(w, h)));
1770 }
1771
1772 /*!
1773 \qmlmethod color Qt::lighter(color baseColor, real factor)
1774 Returns a color lighter than \c baseColor by the \c factor provided.
1775
1776 If the factor is greater than 1.0, this functions returns a lighter color.
1777 Setting factor to 1.5 returns a color that is 50% brighter. If the factor is less than 1.0,
1778 the return color is darker, but we recommend using the Qt.darker() function for this purpose.
1779 If the factor is 0 or negative, the return value is unspecified.
1780
1781 The function converts the current RGB color to HSV, multiplies the value (V) component
1782 by factor and converts the color back to RGB.
1783
1784 If \c factor is not supplied, returns a color 50% lighter than \c baseColor (factor 1.5).
1785 */
1786 QScriptValue QDeclarativeEnginePrivate::lighter(QScriptContext *ctxt, QScriptEngine *engine)
1787 {
1788     if(ctxt->argumentCount() != 1 && ctxt->argumentCount() != 2)
1789         return ctxt->throwError(QLatin1String("Qt.lighter(): Invalid arguments"));
1790     QVariant v = ctxt->argument(0).toVariant();
1791     QColor color;
1792     if (v.userType() == QVariant::Color)
1793         color = v.value<QColor>();
1794     else if (v.userType() == QVariant::String) {
1795         bool ok;
1796         color = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
1797         if (!ok)
1798             return engine->nullValue();
1799     } else
1800         return engine->nullValue();
1801     qsreal factor = 1.5;
1802     if (ctxt->argumentCount() == 2)
1803         factor = ctxt->argument(1).toNumber();
1804     color = color.lighter(int(qRound(factor*100.)));
1805     return engine->toScriptValue(QVariant::fromValue(color));
1806 }
1807
1808 /*!
1809 \qmlmethod color Qt::darker(color baseColor, real factor)
1810 Returns a color darker than \c baseColor by the \c factor provided.
1811
1812 If the factor is greater than 1.0, this function returns a darker color.
1813 Setting factor to 3.0 returns a color that has one-third the brightness.
1814 If the factor is less than 1.0, the return color is lighter, but we recommend using
1815 the Qt.lighter() function for this purpose. If the factor is 0 or negative, the return
1816 value is unspecified.
1817
1818 The function converts the current RGB color to HSV, divides the value (V) component
1819 by factor and converts the color back to RGB.
1820
1821 If \c factor is not supplied, returns a color 50% darker than \c baseColor (factor 2.0).
1822 */
1823 QScriptValue QDeclarativeEnginePrivate::darker(QScriptContext *ctxt, QScriptEngine *engine)
1824 {
1825     if(ctxt->argumentCount() != 1 && ctxt->argumentCount() != 2)
1826         return ctxt->throwError(QLatin1String("Qt.darker(): Invalid arguments"));
1827     QVariant v = ctxt->argument(0).toVariant();
1828     QColor color;
1829     if (v.userType() == QVariant::Color)
1830         color = v.value<QColor>();
1831     else if (v.userType() == QVariant::String) {
1832         bool ok;
1833         color = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
1834         if (!ok)
1835             return engine->nullValue();
1836     } else
1837         return engine->nullValue();
1838     qsreal factor = 2.0;
1839     if (ctxt->argumentCount() == 2)
1840         factor = ctxt->argument(1).toNumber();
1841     color = color.darker(int(qRound(factor*100.)));
1842     return engine->toScriptValue(QVariant::fromValue(color));
1843 }
1844
1845 /*!
1846 \qmlmethod bool Qt::openUrlExternally(url target)
1847 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.
1848 */
1849 QScriptValue QDeclarativeEnginePrivate::desktopOpenUrl(QScriptContext *ctxt, QScriptEngine *e)
1850 {
1851     if(ctxt->argumentCount() < 1)
1852         return QScriptValue(e, false);
1853     bool ret = false;
1854 #ifndef QT_NO_DESKTOPSERVICES
1855     ret = QDesktopServices::openUrl(QDeclarativeScriptEngine::get(e)->resolvedUrl(ctxt, QUrl(ctxt->argument(0).toString())));
1856 #endif
1857     return QScriptValue(e, ret);
1858 }
1859
1860 /*!
1861 \qmlmethod list<string> Qt::fontFamilies()
1862 Returns a list of the font families available to the application.
1863 */
1864
1865 QScriptValue QDeclarativeEnginePrivate::fontFamilies(QScriptContext *ctxt, QScriptEngine *e)
1866 {
1867     if(ctxt->argumentCount() != 0)
1868         return ctxt->throwError(QLatin1String("Qt.fontFamilies(): Invalid arguments"));
1869
1870     QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(e);
1871     QFontDatabase database;
1872     return p->scriptValueFromVariant(database.families());
1873 }
1874
1875 /*!
1876 \qmlmethod string Qt::md5(data)
1877 Returns a hex string of the md5 hash of \c data.
1878 */
1879 QScriptValue QDeclarativeEnginePrivate::md5(QScriptContext *ctxt, QScriptEngine *)
1880 {
1881     if (ctxt->argumentCount() != 1)
1882         return ctxt->throwError(QLatin1String("Qt.md5(): Invalid arguments"));
1883
1884     QByteArray data = ctxt->argument(0).toString().toUtf8();
1885     QByteArray result = QCryptographicHash::hash(data, QCryptographicHash::Md5);
1886
1887     return QScriptValue(QLatin1String(result.toHex()));
1888 }
1889
1890 /*!
1891 \qmlmethod string Qt::btoa(data)
1892 Binary to ASCII - this function returns a base64 encoding of \c data.
1893 */
1894 QScriptValue QDeclarativeEnginePrivate::btoa(QScriptContext *ctxt, QScriptEngine *)
1895 {
1896     if (ctxt->argumentCount() != 1) 
1897         return ctxt->throwError(QLatin1String("Qt.btoa(): Invalid arguments"));
1898
1899     QByteArray data = ctxt->argument(0).toString().toUtf8();
1900
1901     return QScriptValue(QLatin1String(data.toBase64()));
1902 }
1903
1904 /*!
1905 \qmlmethod string Qt::atob(data)
1906 ASCII to binary - this function returns a base64 decoding of \c data.
1907 */
1908
1909 QScriptValue QDeclarativeEnginePrivate::atob(QScriptContext *ctxt, QScriptEngine *)
1910 {
1911     if (ctxt->argumentCount() != 1) 
1912         return ctxt->throwError(QLatin1String("Qt.atob(): Invalid arguments"));
1913
1914     QByteArray data = ctxt->argument(0).toString().toUtf8();
1915
1916     return QScriptValue(QLatin1String(QByteArray::fromBase64(data)));
1917 }
1918
1919 QScriptValue QDeclarativeEnginePrivate::consoleLog(QScriptContext *ctxt, QScriptEngine *e)
1920 {
1921     if(ctxt->argumentCount() < 1)
1922         return e->newVariant(QVariant(false));
1923
1924     QByteArray msg;
1925
1926     for (int i=0; i<ctxt->argumentCount(); ++i) {
1927         if (!msg.isEmpty()) msg += ' ';
1928         msg += ctxt->argument(i).toString().toLocal8Bit();
1929         // does not support firebug "%[a-z]" formatting, since firebug really
1930         // does just ignore the format letter, which makes it pointless.
1931     }
1932
1933     qDebug("%s",msg.constData());
1934
1935     return e->newVariant(QVariant(true));
1936 }
1937
1938 void QDeclarativeEnginePrivate::sendQuit()
1939 {
1940     Q_Q(QDeclarativeEngine);
1941     emit q->quit();
1942     if (q->receivers(SIGNAL(quit())) == 0) {
1943         qWarning("Signal QDeclarativeEngine::quit() emitted, but no receivers connected to handle it.");
1944     }
1945 }
1946
1947 static void dumpwarning(const QDeclarativeError &error)
1948 {
1949     qWarning().nospace() << qPrintable(error.toString());
1950 }
1951
1952 static void dumpwarning(const QList<QDeclarativeError> &errors)
1953 {
1954     for (int ii = 0; ii < errors.count(); ++ii)
1955         dumpwarning(errors.at(ii));
1956 }
1957
1958 void QDeclarativeEnginePrivate::warning(const QDeclarativeError &error)
1959 {
1960     Q_Q(QDeclarativeEngine);
1961     q->warnings(QList<QDeclarativeError>() << error);
1962     if (outputWarningsToStdErr)
1963         dumpwarning(error);
1964 }
1965
1966 void QDeclarativeEnginePrivate::warning(const QList<QDeclarativeError> &errors)
1967 {
1968     Q_Q(QDeclarativeEngine);
1969     q->warnings(errors);
1970     if (outputWarningsToStdErr)
1971         dumpwarning(errors);
1972 }
1973
1974 void QDeclarativeEnginePrivate::warning(QDeclarativeEngine *engine, const QDeclarativeError &error)
1975 {
1976     if (engine)
1977         QDeclarativeEnginePrivate::get(engine)->warning(error);
1978     else
1979         dumpwarning(error);
1980 }
1981
1982 void QDeclarativeEnginePrivate::warning(QDeclarativeEngine *engine, const QList<QDeclarativeError> &error)
1983 {
1984     if (engine)
1985         QDeclarativeEnginePrivate::get(engine)->warning(error);
1986     else
1987         dumpwarning(error);
1988 }
1989
1990 void QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate *engine, const QDeclarativeError &error)
1991 {
1992     if (engine)
1993         engine->warning(error);
1994     else
1995         dumpwarning(error);
1996 }
1997
1998 void QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate *engine, const QList<QDeclarativeError> &error)
1999 {
2000     if (engine)
2001         engine->warning(error);
2002     else
2003         dumpwarning(error);
2004 }
2005
2006 /*!
2007 \qmlmethod Qt::quit()
2008 This function causes the QDeclarativeEngine::quit() signal to be emitted.
2009 Within the \l {QML Viewer}, this causes the launcher application to exit;
2010 to quit a C++ application when this method is called, connect the
2011 QDeclarativeEngine::quit() signal to the QCoreApplication::quit() slot.
2012 */
2013
2014 QScriptValue QDeclarativeEnginePrivate::quit(QScriptContext * /*ctxt*/, QScriptEngine *e)
2015 {
2016     QDeclarativeEnginePrivate *qe = get (e);
2017     qe->sendQuit();
2018     return QScriptValue();
2019 }
2020
2021 /*!
2022     \qmlmethod color Qt::tint(color baseColor, color tintColor)
2023     This function allows tinting one color with another.
2024
2025     The tint color should usually be mostly transparent, or you will not be
2026     able to see the underlying color. The below example provides a slight red
2027     tint by having the tint color be pure red which is only 1/16th opaque.
2028
2029     \qml
2030     Item {
2031         Rectangle {
2032             x: 0; width: 80; height: 80
2033             color: "lightsteelblue"
2034         }
2035         Rectangle {
2036             x: 100; width: 80; height: 80
2037             color: Qt.tint("lightsteelblue", "#10FF0000")
2038         }
2039     }
2040     \endqml
2041     \image declarative-rect_tint.png
2042
2043     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.
2044 */
2045 QScriptValue QDeclarativeEnginePrivate::tint(QScriptContext *ctxt, QScriptEngine *engine)
2046 {
2047     if(ctxt->argumentCount() != 2)
2048         return ctxt->throwError(QLatin1String("Qt.tint(): Invalid arguments"));
2049     //get color
2050     QVariant v = ctxt->argument(0).toVariant();
2051     QColor color;
2052     if (v.userType() == QVariant::Color)
2053         color = v.value<QColor>();
2054     else if (v.userType() == QVariant::String) {
2055         bool ok;
2056         color = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
2057         if (!ok)
2058             return engine->nullValue();
2059     } else
2060         return engine->nullValue();
2061
2062     //get tint color
2063     v = ctxt->argument(1).toVariant();
2064     QColor tintColor;
2065     if (v.userType() == QVariant::Color)
2066         tintColor = v.value<QColor>();
2067     else if (v.userType() == QVariant::String) {
2068         bool ok;
2069         tintColor = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
2070         if (!ok)
2071             return engine->nullValue();
2072     } else
2073         return engine->nullValue();
2074
2075     //tint
2076     QColor finalColor;
2077     int a = tintColor.alpha();
2078     if (a == 0xFF)
2079         finalColor = tintColor;
2080     else if (a == 0x00)
2081         finalColor = color;
2082     else {
2083         qreal a = tintColor.alphaF();
2084         qreal inv_a = 1.0 - a;
2085
2086         finalColor.setRgbF(tintColor.redF() * a + color.redF() * inv_a,
2087                            tintColor.greenF() * a + color.greenF() * inv_a,
2088                            tintColor.blueF() * a + color.blueF() * inv_a,
2089                            a + inv_a * color.alphaF());
2090     }
2091
2092     return engine->toScriptValue(QVariant::fromValue(finalColor));
2093 }
2094
2095 QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &val)
2096 {
2097     if (variantIsScarceResource(val)) {
2098         return scarceResourceClass->newScarceResource(val);
2099     } else if (val.userType() == qMetaTypeId<QDeclarativeListReference>()) {
2100         QDeclarativeListReferencePrivate *p =
2101             QDeclarativeListReferencePrivate::get((QDeclarativeListReference*)val.constData());
2102         if (p->object) {
2103             return listClass->newList(p->property, p->propertyType);
2104         } else {
2105             return scriptEngine.nullValue();
2106         }
2107     } else if (val.userType() == qMetaTypeId<QList<QObject *> >()) {
2108         const QList<QObject *> &list = *(QList<QObject *>*)val.constData();
2109         QScriptValue rv = scriptEngine.newArray(list.count());
2110         for (int ii = 0; ii < list.count(); ++ii) {
2111             QObject *object = list.at(ii);
2112             rv.setProperty(ii, objectClass->newQObject(object));
2113         }
2114         return rv;
2115     } else if (QDeclarativeValueType *vt = valueTypes[val.userType()]) {
2116         return valueTypeClass->newObject(val, vt);
2117     }
2118
2119     bool objOk;
2120     QObject *obj = QDeclarativeMetaType::toQObject(val, &objOk);
2121     if (objOk) {
2122         return objectClass->newQObject(obj);
2123     } else {
2124         return scriptEngine.toScriptValue(val);
2125     }
2126 }
2127
2128 /*
2129    If the variant is a scarce resource (consumes a large amount of memory, or
2130    only a limited number of them can be held in memory at any given time without
2131    exhausting supply for future use) we need to release the scarce resource
2132    after evaluation of the javascript binding is complete.
2133  */
2134 bool QDeclarativeEnginePrivate::variantIsScarceResource(const QVariant& val)
2135 {
2136     if (val.type() == QVariant::Pixmap) {
2137         return true;
2138     } else if (val.type() == QVariant::Image) {
2139         return true;
2140     }
2141
2142     return false;
2143 }
2144
2145 /*
2146    This function should be called prior to evaluation of any js expression,
2147    so that scarce resources are not freed prematurely (eg, if there is a
2148    nested javascript expression).
2149  */
2150 void QDeclarativeEnginePrivate::referenceScarceResources()
2151 {
2152     scarceResourcesRefCount += 1;
2153 }
2154
2155 /*
2156    This function should be called after evaluation of the js expression is
2157    complete, and so the scarce resources may be freed safely.
2158  */
2159 void QDeclarativeEnginePrivate::dereferenceScarceResources()
2160 {
2161     Q_ASSERT(scarceResourcesRefCount > 0);
2162     scarceResourcesRefCount -= 1;
2163
2164     // if the refcount is zero, then evaluation of the "top level"
2165     // expression must have completed.  We can safely release the
2166     // scarce resources.
2167     if (scarceResourcesRefCount == 0) {
2168         // iterate through the list and release them all.
2169         // note that the actual SRD is owned by the JS engine,
2170         // so we cannot delete the SRD; but we can free the
2171         // memory used by the variant in the SRD.
2172         ScarceResourceData *srd = 0;
2173         while (scarceResources) {
2174             srd = scarceResources; // srd points to the "old" (current) head of the list
2175             scarceResources = srd->next; // srd->next is the "new" head of the list
2176             if (srd->next) srd->next->prev = &scarceResources; // newHead->prev = listptr.
2177             srd->next = 0;
2178             srd->prev = 0;
2179             srd->releaseResource(); // release the old head node.
2180         }
2181     }
2182 }
2183
2184 QVariant QDeclarativeEnginePrivate::scriptValueToVariant(const QScriptValue &val, int hint)
2185 {
2186     QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(val);
2187     if (dc == objectClass)
2188         return QVariant::fromValue(objectClass->toQObject(val));
2189     else if (dc == scarceResourceClass)
2190         return scarceResourceClass->toVariant(val);
2191     else if (dc == valueTypeClass)
2192         return valueTypeClass->toVariant(val);
2193     else if (dc == contextClass)
2194         return QVariant();
2195
2196     // Convert to a QList<QObject*> only if val is an array and we were explicitly hinted
2197     if (hint == qMetaTypeId<QList<QObject *> >() && val.isArray()) {
2198         QList<QObject *> list;
2199         int length = val.property(QLatin1String("length")).toInt32();
2200         for (int ii = 0; ii < length; ++ii) {
2201             QScriptValue arrayItem = val.property(ii);
2202             QObject *d = arrayItem.toQObject();
2203             list << d;
2204         }
2205         return QVariant::fromValue(list);
2206     }
2207
2208     return val.toVariant();
2209 }
2210
2211 /*!
2212   Adds \a path as a directory where the engine searches for
2213   installed modules in a URL-based directory structure.
2214   The \a path may be a local filesystem directory or a URL.
2215
2216   The newly added \a path will be first in the importPathList().
2217
2218   \sa setImportPathList(), {QML Modules}
2219 */
2220 void QDeclarativeEngine::addImportPath(const QString& path)
2221 {
2222     Q_D(QDeclarativeEngine);
2223     d->importDatabase.addImportPath(path);
2224 }
2225
2226 /*!
2227   Returns the list of directories where the engine searches for
2228   installed modules in a URL-based directory structure.
2229
2230   For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
2231   imports \c com.mycompany.Feature will cause the QDeclarativeEngine to look
2232   in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
2233   provided by that module. A \c qmldir file is required for defining the
2234   type version mapping and possibly declarative extensions plugins.
2235
2236   By default, the list contains the directory of the application executable,
2237   paths specified in the \c QML_IMPORT_PATH environment variable,
2238   and the builtin \c ImportsPath from QLibraryInfo.
2239
2240   \sa addImportPath() setImportPathList()
2241 */
2242 QStringList QDeclarativeEngine::importPathList() const
2243 {
2244     Q_D(const QDeclarativeEngine);
2245     return d->importDatabase.importPathList();
2246 }
2247
2248 /*!
2249   Sets \a paths as the list of directories where the engine searches for
2250   installed modules in a URL-based directory structure.
2251
2252   By default, the list contains the directory of the application executable,
2253   paths specified in the \c QML_IMPORT_PATH environment variable,
2254   and the builtin \c ImportsPath from QLibraryInfo.
2255
2256   \sa importPathList() addImportPath()
2257   */
2258 void QDeclarativeEngine::setImportPathList(const QStringList &paths)
2259 {
2260     Q_D(QDeclarativeEngine);
2261     d->importDatabase.setImportPathList(paths);
2262 }
2263
2264
2265 /*!
2266   Adds \a path as a directory where the engine searches for
2267   native plugins for imported modules (referenced in the \c qmldir file).
2268
2269   By default, the list contains only \c .,  i.e. the engine searches
2270   in the directory of the \c qmldir file itself.
2271
2272   The newly added \a path will be first in the pluginPathList().
2273
2274   \sa setPluginPathList()
2275 */
2276 void QDeclarativeEngine::addPluginPath(const QString& path)
2277 {
2278     Q_D(QDeclarativeEngine);
2279     d->importDatabase.addPluginPath(path);
2280 }
2281
2282
2283 /*!
2284   Returns the list of directories where the engine searches for
2285   native plugins for imported modules (referenced in the \c qmldir file).
2286
2287   By default, the list contains only \c .,  i.e. the engine searches
2288   in the directory of the \c qmldir file itself.
2289
2290   \sa addPluginPath() setPluginPathList()
2291 */
2292 QStringList QDeclarativeEngine::pluginPathList() const
2293 {
2294     Q_D(const QDeclarativeEngine);
2295     return d->importDatabase.pluginPathList();
2296 }
2297
2298 /*!
2299   Sets the list of directories where the engine searches for
2300   native plugins for imported modules (referenced in the \c qmldir file)
2301   to \a paths.
2302
2303   By default, the list contains only \c .,  i.e. the engine searches
2304   in the directory of the \c qmldir file itself.
2305
2306   \sa pluginPathList() addPluginPath()
2307   */
2308 void QDeclarativeEngine::setPluginPathList(const QStringList &paths)
2309 {
2310     Q_D(QDeclarativeEngine);
2311     d->importDatabase.setPluginPathList(paths);
2312 }
2313
2314
2315 /*!
2316   Imports the plugin named \a filePath with the \a uri provided.
2317   Returns true if the plugin was successfully imported; otherwise returns false.
2318
2319   On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
2320
2321   The plugin has to be a Qt plugin which implements the QDeclarativeExtensionPlugin interface.
2322 */
2323 bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &uri, QList<QDeclarativeError> *errors)
2324 {
2325     Q_D(QDeclarativeEngine);
2326     return d->importDatabase.importPlugin(filePath, uri, errors);
2327 }
2328
2329 /*!
2330   Imports the plugin named \a filePath with the \a uri provided.
2331   Returns true if the plugin was successfully imported; otherwise returns false.
2332
2333   On failure and if non-null, *\a errorString will be set to a message describing the failure.
2334
2335   The plugin has to be a Qt plugin which implements the QDeclarativeExtensionPlugin interface.
2336 */
2337 bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
2338 {
2339     Q_D(QDeclarativeEngine);
2340     QList<QDeclarativeError> errors;
2341     bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
2342     if (!errors.isEmpty()) {
2343         QString builtError;
2344         for (int i = 0; i < errors.size(); ++i) {
2345             builtError = QString(QLatin1String("%1\n        %2"))
2346                     .arg(builtError)
2347                     .arg(errors.at(i).toString());
2348         }
2349         *errorString = builtError;
2350     }
2351     return retn;
2352 }
2353
2354 /*!
2355   \property QDeclarativeEngine::offlineStoragePath
2356   \brief the directory for storing offline user data
2357
2358   Returns the directory where SQL and other offline
2359   storage is placed.
2360
2361   QDeclarativeWebView and the SQL databases created with openDatabase()
2362   are stored here.
2363
2364   The default is QML/OfflineStorage in the platform-standard
2365   user application data directory.
2366
2367   Note that the path may not currently exist on the filesystem, so
2368   callers wanting to \e create new files at this location should create
2369   it first - see QDir::mkpath().
2370 */
2371 void QDeclarativeEngine::setOfflineStoragePath(const QString& dir)
2372 {
2373     Q_D(QDeclarativeEngine);
2374     d->scriptEngine.offlineStoragePath = dir;
2375 }
2376
2377 QString QDeclarativeEngine::offlineStoragePath() const
2378 {
2379     Q_D(const QDeclarativeEngine);
2380     return d->scriptEngine.offlineStoragePath;
2381 }
2382
2383 static void voidptr_destructor(void *v)
2384 {
2385     void **ptr = (void **)v;
2386     delete ptr;
2387 }
2388
2389 static void *voidptr_constructor(const void *v)
2390 {
2391     if (!v) {
2392         return new void*;
2393     } else {
2394         return new void*(*(void **)v);
2395     }
2396 }
2397
2398 QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(const QMetaObject *mo)
2399 {
2400     Q_Q(QDeclarativeEngine);
2401
2402     if (!mo->superClass()) {
2403         QDeclarativePropertyCache *rv = new QDeclarativePropertyCache(q, mo);
2404         propertyCache.insert(mo, rv);
2405         return rv;
2406     } else {
2407         QDeclarativePropertyCache *super = cache(mo->superClass());
2408         QDeclarativePropertyCache *rv = super->copy();
2409         rv->append(q, mo);
2410         propertyCache.insert(mo, rv);
2411         return rv;
2412     }
2413 }
2414
2415 QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(QDeclarativeType *type, int minorVersion, 
2416                                                                   QDeclarativeError &error)
2417 {
2418     QList<QDeclarativeType *> types;
2419
2420     int maxMinorVersion = 0;
2421
2422     const QMetaObject *metaObject = type->metaObject();
2423     while (metaObject) {
2424         QDeclarativeType *t = QDeclarativeMetaType::qmlType(metaObject, type->module(), 
2425                                                             type->majorVersion(), minorVersion);
2426         if (t) {
2427             maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
2428             types << t;
2429         } else {
2430             types << 0;
2431         }
2432
2433         metaObject = metaObject->superClass();
2434     }
2435
2436     if (QDeclarativePropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
2437         c->addref();
2438         typePropertyCache.insert(qMakePair(type, minorVersion), c);
2439         return c;
2440     }
2441
2442     QDeclarativePropertyCache *raw = cache(type->metaObject());
2443
2444     bool hasCopied = false;
2445
2446     for (int ii = 0; ii < types.count(); ++ii) {
2447         QDeclarativeType *currentType = types.at(ii);
2448         if (!currentType)
2449             continue;
2450
2451         int rev = currentType->metaObjectRevision();
2452         int moIndex = types.count() - 1 - ii;
2453
2454         if (raw->allowedRevisionCache[moIndex] != rev) {
2455             if (!hasCopied) {
2456                 raw = raw->copy();
2457                 hasCopied = true;
2458             }
2459             raw->allowedRevisionCache[moIndex] = rev;
2460         }
2461     }
2462
2463     // Test revision compatibility - the basic rule is:
2464     //    * Anything that is excluded, cannot overload something that is not excluded *
2465
2466     // Signals override:
2467     //    * other signals and methods of the same name.
2468     //    * properties named on<Signal Name> 
2469     //    * automatic <property name>Changed notify signals
2470
2471     // Methods override:
2472     //    * other methods of the same name
2473
2474     // Properties override:
2475     //    * other elements of the same name
2476
2477     bool overloadError = false;
2478     QString overloadName;
2479
2480 #if 0
2481     for (QDeclarativePropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
2482          !overloadError && iter != raw->stringCache.end();
2483          ++iter) {
2484
2485         QDeclarativePropertyCache::Data *d = *iter;
2486         if (raw->isAllowedInRevision(d))
2487             continue; // Not excluded - no problems
2488
2489         // check that a regular "name" overload isn't happening
2490         QDeclarativePropertyCache::Data *current = d;
2491         while (!overloadError && current) {
2492             current = d->overrideData(current);
2493             if (current && raw->isAllowedInRevision(current)) 
2494                 overloadError = true;
2495         }
2496     }
2497 #endif
2498
2499     if (overloadError) {
2500         if (hasCopied) raw->release();
2501             
2502         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."));
2503         return 0;
2504     }
2505
2506     if (!hasCopied) raw->addref();
2507     typePropertyCache.insert(qMakePair(type, minorVersion), raw);
2508
2509     if (minorVersion != maxMinorVersion) {
2510         raw->addref();
2511         typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
2512     }
2513
2514     return raw;
2515 }
2516
2517 void QDeclarativeEnginePrivate::registerCompositeType(QDeclarativeCompiledData *data)
2518 {
2519     QByteArray name = data->root->className();
2520
2521     QByteArray ptr = name + '*';
2522     QByteArray lst = "QDeclarativeListProperty<" + name + '>';
2523
2524     int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
2525                                            voidptr_constructor);
2526     int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
2527                                            voidptr_constructor);
2528
2529     m_qmlLists.insert(lst_type, ptr_type);
2530     m_compositeTypes.insert(ptr_type, data);
2531     data->addref();
2532 }
2533
2534 bool QDeclarativeEnginePrivate::isList(int t) const
2535 {
2536     return m_qmlLists.contains(t) || QDeclarativeMetaType::isList(t);
2537 }
2538
2539 int QDeclarativeEnginePrivate::listType(int t) const
2540 {
2541     QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
2542     if (iter != m_qmlLists.end())
2543         return *iter;
2544     else
2545         return QDeclarativeMetaType::listType(t);
2546 }
2547
2548 bool QDeclarativeEnginePrivate::isQObject(int t)
2549 {
2550     return m_compositeTypes.contains(t) || QDeclarativeMetaType::isQObject(t);
2551 }
2552
2553 QObject *QDeclarativeEnginePrivate::toQObject(const QVariant &v, bool *ok) const
2554 {
2555     int t = v.userType();
2556     if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
2557         if (ok) *ok = true;
2558         return *(QObject **)(v.constData());
2559     } else {
2560         return QDeclarativeMetaType::toQObject(v, ok);
2561     }
2562 }
2563
2564 QDeclarativeMetaType::TypeCategory QDeclarativeEnginePrivate::typeCategory(int t) const
2565 {
2566     if (m_compositeTypes.contains(t))
2567         return QDeclarativeMetaType::Object;
2568     else if (m_qmlLists.contains(t))
2569         return QDeclarativeMetaType::List;
2570     else
2571         return QDeclarativeMetaType::typeCategory(t);
2572 }
2573
2574 const QMetaObject *QDeclarativeEnginePrivate::rawMetaObjectForType(int t) const
2575 {
2576     QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
2577     if (iter != m_compositeTypes.end()) {
2578         return (*iter)->root;
2579     } else {
2580         QDeclarativeType *type = QDeclarativeMetaType::qmlType(t);
2581         return type?type->baseMetaObject():0;
2582     }
2583 }
2584
2585 const QMetaObject *QDeclarativeEnginePrivate::metaObjectForType(int t) const
2586 {
2587     QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
2588     if (iter != m_compositeTypes.end()) {
2589         return (*iter)->root;
2590     } else {
2591         QDeclarativeType *type = QDeclarativeMetaType::qmlType(t);
2592         return type?type->metaObject():0;
2593     }
2594 }
2595
2596 bool QDeclarative_isFileCaseCorrect(const QString &fileName)
2597 {
2598 #if defined(Q_OS_MAC) || defined(Q_OS_WIN32)
2599     QFileInfo info(fileName);
2600
2601     QString absolute = info.absoluteFilePath();
2602
2603 #if defined(Q_OS_MAC)
2604     QString canonical = info.canonicalFilePath();
2605 #elif defined(Q_OS_WIN32)
2606     wchar_t buffer[1024];
2607
2608     DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
2609     if (rv == 0 || rv >= 1024) return true;
2610     rv = ::GetLongPathName(buffer, buffer, 1024);
2611     if (rv == 0 || rv >= 1024) return true;
2612
2613     QString canonical((QChar *)buffer);
2614 #endif
2615
2616     int absoluteLength = absolute.length();
2617     int canonicalLength = canonical.length();
2618
2619     int length = qMin(absoluteLength, canonicalLength);
2620     for (int ii = 0; ii < length; ++ii) {
2621         const QChar &a = absolute.at(absoluteLength - 1 - ii);
2622         const QChar &c = canonical.at(canonicalLength - 1 - ii);
2623
2624         if (a.toLower() != c.toLower())
2625             return true;
2626         if (a != c)
2627             return false;
2628     }
2629 #else
2630     Q_UNUSED(fileName)
2631 #endif
2632     return true;
2633 }
2634
2635 QT_END_NAMESPACE