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