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