doc: Added missing qdoc text
[profile/ivi/qtdeclarative.git] / src / qml / qml / qqmlengine.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qqmlengine_p.h"
43 #include "qqmlengine.h"
44 #include "qqmlcomponentattached_p.h"
45
46 #include "qqmlcontext_p.h"
47 #include "qqmlcompiler_p.h"
48 #include "qqml.h"
49 #include "qqmlcontext.h"
50 #include "qqmlexpression.h"
51 #include "qqmlcomponent.h"
52 #include "qqmlvme_p.h"
53 #include <private/qqmlenginedebugservice_p.h>
54 #include "qqmlstringconverters_p.h"
55 #include "qqmlxmlhttprequest_p.h"
56 #include "qqmlscriptstring.h"
57 #include "qqmlglobal_p.h"
58 #include "qquicklistmodel_p.h"
59 #include "qquickworkerscript_p.h"
60 #include "qqmlcomponent_p.h"
61 #include "qqmlnetworkaccessmanagerfactory.h"
62 #include "qqmldirparser_p.h"
63 #include "qqmlextensioninterface.h"
64 #include "qqmllist_p.h"
65 #include "qqmltypenamecache_p.h"
66 #include "qqmlnotifier_p.h"
67 #include <private/qqmlprofilerservice_p.h>
68 #include <private/qv8debugservice_p.h>
69 #include <private/qdebugmessageservice_p.h>
70 #include "qqmlincubator.h"
71 #include <private/qv8profilerservice_p.h>
72 #include <private/qqmlboundsignal_p.h>
73
74 #include <QtCore/qstandardpaths.h>
75 #include <QtCore/qsettings.h>
76
77 #include <QtCore/qmetaobject.h>
78 #include <QNetworkAccessManager>
79 #include <QDebug>
80 #include <QtCore/qcoreapplication.h>
81 #include <QtCore/qdir.h>
82 #include <QtCore/qmutex.h>
83 #include <QtCore/qthread.h>
84 #include <private/qthread_p.h>
85 #include <QtNetwork/qnetworkconfigmanager.h>
86
87 #include <private/qobject_p.h>
88 #include <private/qmetaobject_p.h>
89
90 #include <private/qqmllocale_p.h>
91
92 #ifdef Q_OS_WIN // for %APPDATA%
93 #include <qt_windows.h>
94 #include <qlibrary.h>
95 #include <windows.h>
96
97 #define CSIDL_APPDATA           0x001a  // <username>\Application Data
98 #endif
99
100 Q_DECLARE_METATYPE(QQmlProperty)
101
102 QT_BEGIN_NAMESPACE
103
104 void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
105 {
106     QQmlEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
107     QQmlValueTypeFactory::registerBaseTypes(uri, versionMajor, versionMinor);
108 }
109
110 /*!
111   \qmlclass QtObject QObject
112   \ingroup qml-utility-elements
113   \since 4.7
114   \brief The QtObject element is the most basic element in QML.
115
116   The QtObject element is a non-visual element which contains only the
117   objectName property.
118
119   It can be useful to create a QtObject if you need an extremely
120   lightweight element to enclose a set of custom properties:
121
122   \snippet doc/snippets/qml/qtobject.qml 0
123
124   It can also be useful for C++ integration, as it is just a plain
125   QObject. See the QObject documentation for further details.
126 */
127 /*!
128   \qmlproperty string QtObject::objectName
129   This property holds the QObject::objectName for this specific object instance.
130
131   This allows a C++ application to locate an item within a QML component
132   using the QObject::findChild() method. For example, the following C++
133   application locates the child \l Rectangle item and dynamically changes its
134   \c color value:
135
136     \qml
137     // MyRect.qml
138
139     import QtQuick 2.0
140
141     Item {
142         width: 200; height: 200
143
144         Rectangle {
145             anchors.fill: parent
146             color: "red"
147             objectName: "myRect"
148         }
149     }
150     \endqml
151
152     \code
153     // main.cpp
154
155     QQuickView view;
156     view.setSource(QUrl::fromLocalFile("MyRect.qml"));
157     view.show();
158
159     QQuickItem *item = view.rootObject()->findChild<QQuickItem*>("myRect");
160     if (item)
161         item->setProperty("color", QColor(Qt::yellow));
162     \endcode
163 */
164
165 bool QQmlEnginePrivate::qml_debugging_enabled = false;
166
167 void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
168 {
169     qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
170     qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
171     qmlRegisterType<QQuickListElement>(uri, versionMajor, versionMinor,"ListElement");
172     qmlRegisterCustomType<QQuickListModel>(uri, versionMajor, versionMinor,"ListModel", new QQuickListModelParser);
173     qmlRegisterType<QQuickWorkerScript>(uri,versionMajor,versionMinor,"WorkerScript");
174 }
175
176 void QQmlEnginePrivate::defineModule()
177 {
178     registerBaseTypes("QtQuick", 2, 0);
179     qmlRegisterUncreatableType<QQmlLocale>("QtQuick",2,0,"Locale",QQmlEngine::tr("Locale cannot be instantiated.  Use Qt.locale()"));
180 }
181
182
183 /*!
184     \class QQmlImageProviderBase
185     \brief The QQmlImageProviderBase class is used to register image providers in the QML engine.
186     \mainclass
187
188     Image providers must be registered with the QML engine.  The only information the QML
189     engine knows about image providers is the type of image data they provide.  To use an
190     image provider to acquire image data, you must cast the QQmlImageProviderBase pointer
191     to a QQuickImageProvider pointer.
192
193     \sa QQuickImageProvider, QQuickTextureFactory
194 */
195
196 /*!
197     \enum QQmlImageProviderBase::ImageType
198
199     Defines the type of image supported by this image provider.
200
201     \value Image The Image Provider provides QImage images.
202         The QQuickImageProvider::requestImage() method will be called for all image requests.
203     \value Pixmap The Image Provider provides QPixmap images.
204         The QQuickImageProvider::requestPixmap() method will be called for all image requests.
205     \value Texture The Image Provider provides QSGTextureProvider based images.
206         The QQuickImageProvider::requestTexture() method will be called for all image requests. \omitvalue
207 */
208
209 /*!
210     \enum QQmlImageProviderBase::Flag
211
212     Defines specific requirements or features of this image provider.
213
214     \value ForceAsynchronousImageLoading Ensures that image requests to the provider are
215         run in a separate thread, which allows the provider to spend as much time as needed
216         on producing the image without blocking the main thread.
217 */
218
219 /*! \internal */
220 QQmlImageProviderBase::QQmlImageProviderBase()
221 {
222 }
223
224 /*! \internal */
225 QQmlImageProviderBase::~QQmlImageProviderBase()
226 {
227 }
228
229
230 /*!
231 \qmlclass Qt QQmlEnginePrivate
232   \ingroup qml-utility-elements
233 \brief The QML global Qt object provides useful enums and functions from Qt.
234
235 \keyword QmlGlobalQtObject
236
237 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
238
239 The \c Qt object is a global object with utility functions, properties and enums.
240
241 It is not instantiable; to use it, call the members of the global \c Qt object directly.
242 For example:
243
244 \qml
245 import QtQuick 2.0
246
247 Text {
248     color: Qt.rgba(1, 0, 0, 1)
249     text: Qt.md5("hello, world")
250 }
251 \endqml
252
253
254 \section1 Enums
255
256 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
257 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
258
259
260 \section1 Types
261 The Qt object also contains helper functions for creating objects of specific
262 data types. This is primarily useful when setting the properties of an item
263 when the property has one of the following types:
264
265 \list
266 \li \c color - use \l{Qt::rgba()}{Qt.rgba()}, \l{Qt::hsla()}{Qt.hsla()}, \l{Qt::darker()}{Qt.darker()}, \l{Qt::lighter()}{Qt.lighter()} or \l{Qt::tint()}{Qt.tint()}
267 \li \c rect - use \l{Qt::rect()}{Qt.rect()}
268 \li \c point - use \l{Qt::point()}{Qt.point()}
269 \li \c size - use \l{Qt::size()}{Qt.size()}
270 \li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
271 \endlist
272
273 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
274
275 \section1 Date/Time Formatters
276
277 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
278
279 \list
280     \li \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
281     \li \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
282     \li \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
283 \endlist
284
285 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
286
287
288 \section1 Dynamic Object Creation
289 The following functions on the global object allow you to dynamically create QML
290 items from files or strings. See \l{Dynamic Object Management in QML} for an overview
291 of their use.
292
293 \list
294     \li \l{Qt::createComponent()}{object Qt.createComponent(url)}
295     \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
296 \endlist
297
298
299 \section1 Other Functions
300
301 The following functions are also on the Qt object.
302
303 \list
304     \li \l{Qt::quit()}{Qt.quit()}
305     \li \l{Qt::md5()}{Qt.md5(string)}
306     \li \l{Qt::btoa()}{string Qt.btoa(string)}
307     \li \l{Qt::atob()}{string Qt.atob(string)}
308     \li \l{Qt::binding()}{object Qt.binding(function)}
309     \li \l{Qt::locale()}{object Qt.locale()}
310     \li \l{Qt::resolvedUrl()}{string Qt.resolvedUrl(string)}
311     \li \l{Qt::openUrlExternally()}{Qt.openUrlExternally(string)}
312     \li \l{Qt::fontFamilies()}{list<string> Qt.fontFamilies()}
313 \endlist
314 */
315
316 /*!
317     \qmlproperty object Qt::application
318     \since QtQuick 1.1
319
320     The \c application object provides access to global application state
321     properties shared by many QML components.
322
323     Its properties are:
324
325     \table
326     \row
327     \li \c application.active
328     \li
329     This read-only property indicates whether the application is the top-most and focused
330     application, and the user is able to interact with the application. The property
331     is false when the application is in the background, the device keylock or screen
332     saver is active, the screen backlight is turned off, or the global system dialog
333     is being displayed on top of the application. It can be used for stopping and
334     pausing animations, timers and active processing of data in order to save device
335     battery power and free device memory and processor load when the application is not
336     active.
337
338     \row
339     \li \c application.layoutDirection
340     \li
341     This read-only property can be used to query the default layout direction of the
342     application. On system start-up, the default layout direction depends on the
343     application's language. The property has a value of \c Qt.RightToLeft in locales
344     where text and graphic elements are read from right to left, and \c Qt.LeftToRight
345     where the reading direction flows from left to right. You can bind to this
346     property to customize your application layouts to support both layout directions.
347
348     Possible values are:
349
350     \list
351     \li Qt.LeftToRight - Text and graphics elements should be positioned
352                         from left to right.
353     \li Qt.RightToLeft - Text and graphics elements should be positioned
354                         from right to left.
355     \endlist
356
357     \endtable
358
359     The following example uses the \c application object to indicate
360     whether the application is currently active:
361
362     \snippet doc/snippets/qml/application.qml document
363 */
364
365 /*!
366     \qmlproperty object Qt::inputMethod
367     \since QtQuick 2.0
368
369     The \c inputMethod object allows access to application's QInputMethod object
370     and all its properties and slots. See the QInputMethod documentation for
371     further details.
372 */
373
374
375 /*!
376 \qmlmethod object Qt::include(string url, jsobject callback)
377
378 Includes another JavaScript file. This method can only be used from within JavaScript files,
379 and not regular QML files.
380
381 This imports all functions from \a url into the current script's namespace.
382
383 Qt.include() returns an object that describes the status of the operation.  The object has
384 a single property, \c {status}, that is set to one of the following values:
385
386 \table
387 \header \li Symbol \li Value \li Description
388 \row \li result.OK \li 0 \li The include completed successfully.
389 \row \li result.LOADING \li 1 \li Data is being loaded from the network.
390 \row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
391 \row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
392 An additional \c exception property will be set in this case.
393 \endtable
394
395 The \c status property will be updated as the operation progresses.
396
397 If provided, \a callback is invoked when the operation completes.  The callback is passed
398 the same object as is returned from the Qt.include() call.
399 */
400 // Qt.include() is implemented in qv8include.cpp
401
402
403 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
404 : propertyCapture(0), rootContext(0), isDebugging(false),
405   outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
406   cleanup(0), erroredBindings(0), inProgressCreations(0),
407   workerScriptEngine(0), activeVME(0),
408   networkAccessManager(0), networkAccessManagerFactory(0),
409   scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
410   incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
411 {
412 }
413
414 QQmlEnginePrivate::~QQmlEnginePrivate()
415 {
416     if (inProgressCreations)
417         qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
418
419     while (cleanup) {
420         QQmlCleanup *c = cleanup;
421         cleanup = c->next;
422         if (cleanup) cleanup->prev = &cleanup;
423         c->next = 0;
424         c->prev = 0;
425         c->clear();
426     }
427
428     doDeleteInEngineThread();
429
430     if (incubationController) incubationController->d = 0;
431     incubationController = 0;
432
433     delete rootContext;
434     rootContext = 0;
435
436     for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
437         (*iter)->release();
438     for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
439         (*iter)->release();
440     for(QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
441         delete (*iter)->qobjectApi;
442         delete *iter;
443     }
444 }
445
446 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
447 {
448     QObjectPrivate *p = QObjectPrivate::get(o);
449     if (p->declarativeData) {
450         QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
451         if (d->ownContext && d->context) {
452             d->context->destroy();
453             d->context = 0;
454         }
455
456         // Mark this object as in the process of deletion to
457         // prevent it resolving in bindings
458         QQmlData::markAsDeleted(o);
459     }
460 }
461
462 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
463 {
464     static_cast<QQmlData *>(d)->destroyed(o);
465 }
466
467 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
468 {
469     static_cast<QQmlData *>(d)->parentChanged(o, p);
470 }
471
472 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **a)
473 {
474     QQmlData *ddata = QQmlData::get(object, false);
475     if (!ddata) return; // Probably being deleted
476
477     // In general, QML only supports QObject's that live on the same thread as the QQmlEngine
478     // that they're exposed to.  However, to make writing "worker objects" that calculate data
479     // in a separate thread easier, QML allows a QObject that lives in the same thread as the
480     // QQmlEngine to emit signals from a different thread.  These signals are then automatically
481     // marshalled back onto the QObject's thread and handled by QML from there.  This is tested
482     // by the qqmlecmascript::threadSignal() autotest.
483     if (ddata->notifyList &&
484         QThread::currentThreadId() != QObjectPrivate::get(object)->threadData->threadId) {
485
486         QMetaMethod m = object->metaObject()->method(index);
487         QList<QByteArray> parameterTypes = m.parameterTypes();
488
489         int *types = (int *)malloc((parameterTypes.count() + 1) * sizeof(int));
490         void **args = (void **) malloc((parameterTypes.count() + 1) *sizeof(void *));
491
492         types[0] = 0; // return type
493         args[0] = 0; // return value
494
495         for (int ii = 0; ii < parameterTypes.count(); ++ii) {
496             const QByteArray &typeName = parameterTypes.at(ii);
497             if (typeName.endsWith('*'))
498                 types[ii + 1] = QMetaType::VoidStar;
499             else
500                 types[ii + 1] = QMetaType::type(typeName);
501
502             if (!types[ii + 1]) {
503                 qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
504                          "(Make sure '%s' is registered using qRegisterMetaType().)",
505                          typeName.constData(), typeName.constData());
506                 free(types);
507                 free(args);
508                 return;
509             }
510
511             args[ii + 1] = QMetaType::create(types[ii + 1], a[ii + 1]);
512         }
513
514         QMetaCallEvent *ev = new QMetaCallEvent(index, 0, 0, object, index,
515                                                 parameterTypes.count() + 1, types, args);
516         QCoreApplication::postEvent(object, ev);
517
518     } else {
519         QQmlNotifierEndpoint *ep = ddata->notify(index);
520         if (ep) QQmlNotifier::emitNotify(ep, a);
521     }
522 }
523
524 int QQmlData::receivers(QAbstractDeclarativeData *d, const QObject *, int index)
525 {
526     return static_cast<QQmlData *>(d)->endpointCount(index);
527 }
528
529 int QQmlData::endpointCount(int index)
530 {
531     int count = 0;
532     QQmlNotifierEndpoint *ep = notify(index);
533     if (!ep)
534         return count;
535     ++count;
536     while (ep->next) {
537         ++count;
538         ep = ep->next;
539     }
540     return count;
541 }
542
543 void QQmlData::markAsDeleted(QObject *o)
544 {
545     QQmlData::setQueuedForDeletion(o);
546
547     QObjectPrivate *p = QObjectPrivate::get(o);
548     for (QList<QObject *>::iterator it = p->children.begin(), end = p->children.end(); it != end; ++it) {
549         QQmlData::markAsDeleted(*it);
550     }
551 }
552
553 void QQmlData::setQueuedForDeletion(QObject *object)
554 {
555     if (object) {
556         if (QObjectPrivate *priv = QObjectPrivate::get(object)) {
557             if (!priv->wasDeleted && priv->declarativeData) {
558                 QQmlData *ddata = QQmlData::get(object, false);
559                 if (ddata->ownContext && ddata->context)
560                     ddata->context->emitDestruction();
561                 ddata->isQueuedForDeletion = true;
562             }
563         }
564     }
565 }
566
567 void QQmlEnginePrivate::init()
568 {
569     Q_Q(QQmlEngine);
570
571     static bool firstTime = true;
572     if (firstTime) {
573         qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component");
574
575         QQmlData::init();
576         firstTime = false;
577     }
578
579     qRegisterMetaType<QVariant>("QVariant");
580     qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
581     qRegisterMetaType<QJSValue>("QJSValue");
582     qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
583     qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
584     qRegisterMetaType<QList<int> >("QList<int>");
585     qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
586
587     v8engine()->setEngine(q);
588
589     rootContext = new QQmlContext(q,true);
590
591     if (QCoreApplication::instance()->thread() == q->thread() &&
592         QQmlEngineDebugService::isDebuggingEnabled()) {
593         isDebugging = true;
594         QQmlEngineDebugService::instance()->addEngine(q);
595         QV8DebugService::initialize(v8engine());
596         QV8ProfilerService::initialize();
597         QQmlProfilerService::initialize();
598         QDebugMessageService::instance();
599     }
600
601     QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
602     if (!dataLocation.isEmpty())
603         offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator())
604                            + QDir::separator() + QLatin1String("QML")
605                            + QDir::separator() + QLatin1String("OfflineStorage");
606 }
607
608 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
609 {
610     Q_Q(QQmlEngine);
611     if (!workerScriptEngine)
612         workerScriptEngine = new QQuickWorkerScriptEngine(q);
613     return workerScriptEngine;
614 }
615
616 /*!
617   \class QQmlEngine
618   \since 5.0
619   \inmodule QtQml
620   \brief The QQmlEngine class provides an environment for instantiating QML components.
621   \mainclass
622
623   Each QML component is instantiated in a QQmlContext.
624   QQmlContext's are essential for passing data to QML
625   components.  In QML, contexts are arranged hierarchically and this
626   hierarchy is managed by the QQmlEngine.
627
628   Prior to creating any QML components, an application must have
629   created a QQmlEngine to gain access to a QML context.  The
630   following example shows how to create a simple Text item.
631
632   \code
633   QQmlEngine engine;
634   QQmlComponent component(&engine);
635   component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
636   QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
637
638   //add item to view, etc
639   ...
640   \endcode
641
642   In this case, the Text item will be created in the engine's
643   \l {QQmlEngine::rootContext()}{root context}.
644
645   Note that the QtQuick 1 version is called QDeclarativeEngine.
646
647   \sa QQmlComponent, QQmlContext
648 */
649
650 /*!
651   Create a new QQmlEngine with the given \a parent.
652 */
653 QQmlEngine::QQmlEngine(QObject *parent)
654 : QJSEngine(*new QQmlEnginePrivate(this), parent)
655 {
656     Q_D(QQmlEngine);
657     d->init();
658 }
659
660 /*!
661   Destroys the QQmlEngine.
662
663   Any QQmlContext's created on this engine will be
664   invalidated, but not destroyed (unless they are parented to the
665   QQmlEngine object).
666 */
667 QQmlEngine::~QQmlEngine()
668 {
669     Q_D(QQmlEngine);
670     if (d->isDebugging) {
671         QQmlEngineDebugService::instance()->remEngine(this);
672     }
673
674     // Emit onDestruction signals for the root context before
675     // we destroy the contexts, engine, Module APIs etc. that
676     // may be required to handle the destruction signal.
677     QQmlContextData::get(rootContext())->emitDestruction();
678
679     // if we are the parent of any of the qobject module api instances,
680     // we need to remove them from our internal list, in order to prevent
681     // a segfault in engine private dtor.
682     QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
683     QObject *currQObjectApi = 0;
684     QQmlMetaType::ModuleApiInstance *currInstance = 0;
685     foreach (const QQmlMetaType::ModuleApi &key, keys) {
686         currInstance = d->moduleApiInstances.value(key);
687         currQObjectApi = currInstance->qobjectApi;
688         if (this->children().contains(currQObjectApi)) {
689             delete currQObjectApi;
690             delete currInstance;
691             d->moduleApiInstances.remove(key);
692         }
693     }
694
695     if (d->incubationController)
696         d->incubationController->d = 0;
697 }
698
699 /*! \fn void QQmlEngine::quit()
700     This signal is emitted when the QML loaded by the engine would like to quit.
701  */
702
703 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
704     This signal is emitted when \a warnings messages are generated by QML.
705  */
706
707 /*!
708   Clears the engine's internal component cache.
709
710   This function causes the property metadata of all components previously
711   loaded by the engine to be destroyed.  All previously loaded components and
712   the property bindings for all extant objects created from those components will
713   cease to function.
714
715   This function returns the engine to a state where it does not contain any loaded
716   component data.  This may be useful in order to reload a smaller subset of the
717   previous component set, or to load a new version of a previously loaded component.
718
719   Once the component cache has been cleared, components must be loaded before
720   any new objects can be created.
721
722   \sa trimComponentCache()
723  */
724 void QQmlEngine::clearComponentCache()
725 {
726     Q_D(QQmlEngine);
727     d->clearCache();
728 }
729
730 /*!
731   Trims the engine's internal component cache.
732
733   This function causes the property metadata of any loaded components which are
734   not currently in use to be destroyed.
735
736   A component is considered to be in use if there are any extant instances of
737   the component itself, any instances of other components that use the component,
738   or any objects instantiated by any of those components.
739
740   \sa clearComponentCache()
741  */
742 void QQmlEngine::trimComponentCache()
743 {
744     Q_D(QQmlEngine);
745     d->trimCache();
746 }
747
748 /*!
749   Returns the engine's root context.
750
751   The root context is automatically created by the QQmlEngine.
752   Data that should be available to all QML component instances
753   instantiated by the engine should be put in the root context.
754
755   Additional data that should only be available to a subset of
756   component instances should be added to sub-contexts parented to the
757   root context.
758 */
759 QQmlContext *QQmlEngine::rootContext() const
760 {
761     Q_D(const QQmlEngine);
762     return d->rootContext;
763 }
764
765 /*!
766   Sets the \a factory to use for creating QNetworkAccessManager(s).
767
768   QNetworkAccessManager is used for all network access by QML.  By
769   implementing a factory it is possible to create custom
770   QNetworkAccessManager with specialized caching, proxy and cookie
771   support.
772
773   The factory must be set before executing the engine.
774 */
775 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
776 {
777     Q_D(QQmlEngine);
778     QMutexLocker locker(&d->mutex);
779     d->networkAccessManagerFactory = factory;
780 }
781
782 /*!
783   Returns the current QQmlNetworkAccessManagerFactory.
784
785   \sa setNetworkAccessManagerFactory()
786 */
787 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
788 {
789     Q_D(const QQmlEngine);
790     return d->networkAccessManagerFactory;
791 }
792
793 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
794 {
795     if (activeVME) {
796         activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
797     } else {
798         void *args[] = { 0 };
799         QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
800     }
801 }
802
803 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
804 {
805     QMutexLocker locker(&mutex);
806     QNetworkAccessManager *nam;
807     if (networkAccessManagerFactory) {
808         nam = networkAccessManagerFactory->create(parent);
809     } else {
810         nam = new QNetworkAccessManager(parent);
811     }
812
813     return nam;
814 }
815
816 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
817 {
818     Q_Q(const QQmlEngine);
819     if (!networkAccessManager)
820         networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
821     return networkAccessManager;
822 }
823
824 /*!
825   Returns a common QNetworkAccessManager which can be used by any QML
826   element instantiated by this engine.
827
828   If a QQmlNetworkAccessManagerFactory has been set and a
829   QNetworkAccessManager has not yet been created, the
830   QQmlNetworkAccessManagerFactory will be used to create the
831   QNetworkAccessManager; otherwise the returned QNetworkAccessManager
832   will have no proxy or cache set.
833
834   \sa setNetworkAccessManagerFactory()
835 */
836 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
837 {
838     Q_D(const QQmlEngine);
839     return d->getNetworkAccessManager();
840 }
841
842 /*!
843
844   Sets the \a provider to use for images requested via the \e
845   image: url scheme, with host \a providerId. The QQmlEngine
846   takes ownership of \a provider.
847
848   Image providers enable support for pixmap and threaded image
849   requests. See the QQuickImageProvider documentation for details on
850   implementing and using image providers.
851
852   All required image providers should be added to the engine before any
853   QML sources files are loaded.
854
855   \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
856 */
857 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
858 {
859     Q_D(QQmlEngine);
860     QMutexLocker locker(&d->mutex);
861     d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
862 }
863
864 /*!
865   Returns the image provider set for \a providerId.
866
867   Returns the provider if it was found; otherwise returns 0.
868
869   \sa QQuickImageProvider
870 */
871 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
872 {
873     Q_D(const QQmlEngine);
874     QMutexLocker locker(&d->mutex);
875     return d->imageProviders.value(providerId).data();
876 }
877
878 /*!
879   Removes the image provider for \a providerId.
880
881   \sa addImageProvider(), QQuickImageProvider
882 */
883 void QQmlEngine::removeImageProvider(const QString &providerId)
884 {
885     Q_D(QQmlEngine);
886     QMutexLocker locker(&d->mutex);
887     d->imageProviders.take(providerId);
888 }
889
890 /*!
891   Return the base URL for this engine.  The base URL is only used to
892   resolve components when a relative URL is passed to the
893   QQmlComponent constructor.
894
895   If a base URL has not been explicitly set, this method returns the
896   application's current working directory.
897
898   \sa setBaseUrl()
899 */
900 QUrl QQmlEngine::baseUrl() const
901 {
902     Q_D(const QQmlEngine);
903     if (d->baseUrl.isEmpty()) {
904         return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
905     } else {
906         return d->baseUrl;
907     }
908 }
909
910 /*!
911   Set the  base URL for this engine to \a url.
912
913   \sa baseUrl()
914 */
915 void QQmlEngine::setBaseUrl(const QUrl &url)
916 {
917     Q_D(QQmlEngine);
918     d->baseUrl = url;
919 }
920
921 /*!
922   Returns true if warning messages will be output to stderr in addition
923   to being emitted by the warnings() signal, otherwise false.
924
925   The default value is true.
926 */
927 bool QQmlEngine::outputWarningsToStandardError() const
928 {
929     Q_D(const QQmlEngine);
930     return d->outputWarningsToStdErr;
931 }
932
933 /*!
934   Set whether warning messages will be output to stderr to \a enabled.
935
936   If \a enabled is true, any warning messages generated by QML will be
937   output to stderr and emitted by the warnings() signal.  If \a enabled
938   is false, on the warnings() signal will be emitted.  This allows
939   applications to handle warning output themselves.
940
941   The default value is true.
942 */
943 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
944 {
945     Q_D(QQmlEngine);
946     d->outputWarningsToStdErr = enabled;
947 }
948
949 /*!
950   Attempt to free unused memory.
951 */
952 void QQmlEngine::collectGarbage()
953 {
954     QV8Engine::gc();
955 }
956
957 /*!
958   Returns the QQmlContext for the \a object, or 0 if no
959   context has been set.
960
961   When the QQmlEngine instantiates a QObject, the context is
962   set automatically.
963   */
964 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
965 {
966     if(!object)
967         return 0;
968
969     QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
970
971     QQmlData *data =
972         static_cast<QQmlData *>(priv->declarativeData);
973
974     if (!data)
975         return 0;
976     else if (data->outerContext)
977         return data->outerContext->asQQmlContext();
978     else
979         return 0;
980 }
981
982 /*!
983   Sets the QQmlContext for the \a object to \a context.
984   If the \a object already has a context, a warning is
985   output, but the context is not changed.
986
987   When the QQmlEngine instantiates a QObject, the context is
988   set automatically.
989  */
990 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
991 {
992     if (!object || !context)
993         return;
994
995     QQmlData *data = QQmlData::get(object, true);
996     if (data->context) {
997         qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
998         return;
999     }
1000
1001     QQmlContextData *contextData = QQmlContextData::get(context);
1002     contextData->addObject(object);
1003 }
1004
1005 /*!
1006   \enum QQmlEngine::ObjectOwnership
1007
1008   Ownership controls whether or not QML automatically destroys the
1009   QObject when the object is garbage collected by the JavaScript
1010   engine.  The two ownership options are:
1011
1012   \value CppOwnership The object is owned by C++ code, and will
1013   never be deleted by QML.  The JavaScript destroy() method cannot be
1014   used on objects with CppOwnership.  This option is similar to
1015   QScriptEngine::QtOwnership.
1016
1017   \value JavaScriptOwnership The object is owned by JavaScript.
1018   When the object is returned to QML as the return value of a method
1019   call or property access, QML will track it, and delete the object
1020   if there are no remaining JavaScript references to it and it has no
1021   QObject::parent().  An object tracked by one QQmlEngine
1022   will be deleted during that QQmlEngine's destructor, and thus
1023   JavaScript references between objects with JavaScriptOwnership from
1024   two different engines will not be valid after the deletion of one of
1025   those engines.  This option is similar to QScriptEngine::ScriptOwnership.
1026
1027   Generally an application doesn't need to set an object's ownership
1028   explicitly.  QML uses a heuristic to set the default object
1029   ownership.  By default, an object that is created by QML has
1030   JavaScriptOwnership.  The exception to this are the root objects
1031   created by calling QQmlComponent::create() or
1032   QQmlComponent::beginCreate() which have CppOwnership by
1033   default.  The ownership of these root-level objects is considered to
1034   have been transferred to the C++ caller.
1035
1036   Objects not-created by QML have CppOwnership by default.  The
1037   exception to this is objects returned from a C++ method call.  The
1038   ownership of these objects is passed to JavaScript.
1039
1040   Calling setObjectOwnership() overrides the default ownership
1041   heuristic used by QML.
1042 */
1043
1044 /*!
1045   Sets the \a ownership of \a object.
1046 */
1047 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
1048 {
1049     if (!object)
1050         return;
1051
1052     QQmlData *ddata = QQmlData::get(object, true);
1053     if (!ddata)
1054         return;
1055
1056     ddata->indestructible = (ownership == CppOwnership)?true:false;
1057     ddata->explicitIndestructibleSet = true;
1058 }
1059
1060 /*!
1061   Returns the ownership of \a object.
1062 */
1063 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
1064 {
1065     if (!object)
1066         return CppOwnership;
1067
1068     QQmlData *ddata = QQmlData::get(object, false);
1069     if (!ddata)
1070         return CppOwnership;
1071     else
1072         return ddata->indestructible?CppOwnership:JavaScriptOwnership;
1073 }
1074
1075 bool QQmlEngine::event(QEvent *e)
1076 {
1077     Q_D(QQmlEngine);
1078     if (e->type() == QEvent::User)
1079         d->doDeleteInEngineThread();
1080
1081     return QJSEngine::event(e);
1082 }
1083
1084 void QQmlEnginePrivate::doDeleteInEngineThread()
1085 {
1086     QFieldList<Deletable, &Deletable::next> list;
1087     mutex.lock();
1088     list.copyAndClear(toDeleteInEngineThread);
1089     mutex.unlock();
1090
1091     while (Deletable *d = list.takeFirst())
1092         delete d;
1093 }
1094
1095 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
1096 {
1097     QQmlData *data = QQmlData::get(object);
1098
1099     if (data && data->compiledData && data->deferredIdx) {
1100         QQmlObjectCreatingProfiler prof;
1101         if (prof.enabled) {
1102             QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
1103             prof.setTypeName(type ? type->qmlTypeName()
1104                                   : QString::fromUtf8(object->metaObject()->className()));
1105             if (data->outerContext)
1106                 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
1107         }
1108         QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
1109
1110         QQmlComponentPrivate::ConstructionState state;
1111         QQmlComponentPrivate::beginDeferred(ep, object, &state);
1112
1113         // Release the reference for the deferral action (we still have one from construction)
1114         data->compiledData->release();
1115         data->compiledData = 0;
1116
1117         QQmlComponentPrivate::complete(ep, &state);
1118     }
1119 }
1120
1121 QQmlContext *qmlContext(const QObject *obj)
1122 {
1123     return QQmlEngine::contextForObject(obj);
1124 }
1125
1126 QQmlEngine *qmlEngine(const QObject *obj)
1127 {
1128     QQmlData *data = QQmlData::get(obj, false);
1129     if (!data || !data->context)
1130         return 0;
1131     return data->context->engine;
1132 }
1133
1134 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1135 {
1136     QQmlData *data = QQmlData::get(object);
1137     if (!data)
1138         return 0; // Attached properties are only on objects created by QML
1139
1140     QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1141     if (rv || !create)
1142         return rv;
1143
1144     QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1145     if (!pf)
1146         return 0;
1147
1148     rv = pf(const_cast<QObject *>(object));
1149
1150     if (rv)
1151         data->attachedProperties()->insert(id, rv);
1152
1153     return rv;
1154 }
1155
1156 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1157                                      const QMetaObject *attachedMetaObject, bool create)
1158 {
1159     if (*idCache == -1)
1160         *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1161
1162     if (*idCache == -1 || !object)
1163         return 0;
1164
1165     return qmlAttachedPropertiesObjectById(*idCache, object, create);
1166 }
1167
1168 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1169 {
1170 #ifndef QQML_NO_DEBUG_PROTOCOL
1171     if (!QQmlEnginePrivate::qml_debugging_enabled
1172             && printWarning) {
1173         qDebug("QML debugging is enabled. Only use this in a safe environment.");
1174     }
1175     QQmlEnginePrivate::qml_debugging_enabled = true;
1176 #endif
1177 }
1178
1179
1180 class QQmlDataExtended {
1181 public:
1182     QQmlDataExtended();
1183     ~QQmlDataExtended();
1184
1185     QHash<int, QObject *> attachedProperties;
1186 };
1187
1188 QQmlDataExtended::QQmlDataExtended()
1189 {
1190 }
1191
1192 QQmlDataExtended::~QQmlDataExtended()
1193 {
1194 }
1195
1196 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1197 {
1198     if (endpoint->next)
1199         layout(endpoint->next);
1200
1201     int index = endpoint->sourceSignal;
1202     index = qMin(index, 0xFFFF - 1);
1203
1204     endpoint->next = notifies[index];
1205     if (endpoint->next) endpoint->next->prev = &endpoint->next;
1206     endpoint->prev = &notifies[index];
1207     notifies[index] = endpoint;
1208 }
1209
1210 void QQmlData::NotifyList::layout()
1211 {
1212     Q_ASSERT(maximumTodoIndex >= notifiesSize);
1213
1214     if (todo) {
1215         QQmlNotifierEndpoint **old = notifies;
1216         const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1217         notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1218         const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1219                                sizeof(QQmlNotifierEndpoint*);
1220         memset(notifies + notifiesSize, 0, memsetSize);
1221
1222         if (notifies != old) {
1223             for (int ii = 0; ii < notifiesSize; ++ii)
1224                 if (notifies[ii])
1225                     notifies[ii]->prev = &notifies[ii];
1226         }
1227
1228         notifiesSize = maximumTodoIndex + 1;
1229
1230         layout(todo);
1231     }
1232
1233     maximumTodoIndex = 0;
1234     todo = 0;
1235 }
1236
1237 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1238 {
1239     if (!notifyList) {
1240         notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1241         notifyList->connectionMask = 0;
1242         notifyList->maximumTodoIndex = 0;
1243         notifyList->notifiesSize = 0;
1244         notifyList->todo = 0;
1245         notifyList->notifies = 0;
1246     }
1247
1248     Q_ASSERT(!endpoint->isConnected());
1249
1250     index = qMin(index, 0xFFFF - 1);
1251     notifyList->connectionMask |= (1ULL << quint64(index % 64));
1252
1253     if (index < notifyList->notifiesSize) {
1254
1255         endpoint->next = notifyList->notifies[index];
1256         if (endpoint->next) endpoint->next->prev = &endpoint->next;
1257         endpoint->prev = &notifyList->notifies[index];
1258         notifyList->notifies[index] = endpoint;
1259
1260     } else {
1261         notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1262
1263         endpoint->next = notifyList->todo;
1264         if (endpoint->next) endpoint->next->prev = &endpoint->next;
1265         endpoint->prev = &notifyList->todo;
1266         notifyList->todo = endpoint;
1267     }
1268 }
1269
1270 bool QQml_isSignalConnected(QObject *obj, int signal_index, int index)
1271 {
1272     QQmlData *data = QQmlData::get(obj);
1273     return QObjectPrivate::get(obj)->isSignalConnected(signal_index) || (data && data->signalHasEndpoint(index));
1274 }
1275
1276 /*
1277     index MUST be the index returned by QMetaMethod::index()
1278     This is different than the index returned by QObjectPrivate::signalIndex()
1279 */
1280 bool QQmlData::signalHasEndpoint(int index)
1281 {
1282     return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
1283 }
1284
1285 QHash<int, QObject *> *QQmlData::attachedProperties() const
1286 {
1287     if (!extendedData) extendedData = new QQmlDataExtended;
1288     return &extendedData->attachedProperties;
1289 }
1290
1291 void QQmlData::destroyed(QObject *object)
1292 {
1293     if (nextContextObject)
1294         nextContextObject->prevContextObject = prevContextObject;
1295     if (prevContextObject)
1296         *prevContextObject = nextContextObject;
1297
1298     QQmlAbstractBinding *binding = bindings;
1299     while (binding) {
1300         QQmlAbstractBinding *next = binding->m_nextBinding;
1301         binding->m_prevBinding = 0;
1302         binding->m_nextBinding = 0;
1303         binding->destroy();
1304         binding = next;
1305     }
1306
1307     if (compiledData) {
1308         compiledData->release();
1309         compiledData = 0;
1310     }
1311
1312     QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1313     while (signalHandler) {
1314         if (signalHandler->isEvaluating()) {
1315             // The object is being deleted during signal handler evaluation.
1316             // This will cause a crash due to invalid memory access when the
1317             // evaluation has completed.
1318             // Abort with a friendly message instead.
1319             QString locationString;
1320             QQmlBoundSignalExpression *expr = signalHandler->expression();
1321             if (expr) {
1322                 QString fileName = expr->sourceFile();
1323                 if (fileName.isEmpty())
1324                     fileName = QStringLiteral("<Unknown File>");
1325                 locationString.append(fileName);
1326                 locationString.append(QString::fromLatin1(":%0: ").arg(expr->lineNumber()));
1327                 QString source = expr->expression();
1328                 if (source.size() > 100) {
1329                     source.truncate(96);
1330                     source.append(QStringLiteral(" ..."));
1331                 }
1332                 locationString.append(source);
1333             } else {
1334                 locationString = QStringLiteral("<Unknown Location>");
1335             }
1336             qFatal("Object %p destroyed while one of its QML signal handlers is in progress.\n"
1337                    "Most likely the object was deleted synchronously (use QObject::deleteLater() "
1338                    "instead), or the application is running a nested event loop.\n"
1339                    "This behavior is NOT supported!\n"
1340                    "%s", object, qPrintable(locationString));
1341         }
1342
1343         QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1344         signalHandler->m_prevSignal = 0;
1345         signalHandler->m_nextSignal = 0;
1346         delete signalHandler;
1347         signalHandler = next;
1348     }
1349
1350     if (bindingBits)
1351         free(bindingBits);
1352
1353     if (propertyCache)
1354         propertyCache->release();
1355
1356     if (ownContext && context)
1357         context->destroy();
1358
1359     while (guards) {
1360         QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1361         *guard = (QObject *)0;
1362         guard->objectDestroyed(object);
1363     }
1364
1365     if (notifyList) {
1366         while (notifyList->todo)
1367             notifyList->todo->disconnect();
1368         for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1369             while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1370                 ep->disconnect();
1371         }
1372         free(notifyList->notifies);
1373         free(notifyList);
1374         notifyList = 0;
1375     }
1376
1377     if (extendedData)
1378         delete extendedData;
1379
1380     // Dispose the handle.
1381     // We don't simply clear it (and wait for next gc cycle to dispose
1382     // via the weak qobject reference callback) as this affects the
1383     // outcomes of v8's gc statistical analysis heuristics, which can
1384     // cause unnecessary growth of the old pointer space js heap area.
1385     qPersistentDispose(v8object);
1386
1387     if (ownMemory)
1388         delete this;
1389 }
1390
1391 void QQmlData::parentChanged(QObject *object, QObject *parent)
1392 {
1393     Q_UNUSED(object);
1394     Q_UNUSED(parent);
1395 }
1396
1397 bool QQmlData::hasBindingBit(int bit) const
1398 {
1399     if (bindingBitsSize > bit)
1400         return bindingBits[bit / 32] & (1 << (bit % 32));
1401     else
1402         return false;
1403 }
1404
1405 void QQmlData::clearBindingBit(int bit)
1406 {
1407     if (bindingBitsSize > bit)
1408         bindingBits[bit / 32] &= ~(1 << (bit % 32));
1409 }
1410
1411 void QQmlData::setBindingBit(QObject *obj, int bit)
1412 {
1413     if (bindingBitsSize <= bit) {
1414         int props = obj->metaObject()->propertyCount();
1415         Q_ASSERT(bit < props);
1416
1417         int arraySize = (props + 31) / 32;
1418         int oldArraySize = bindingBitsSize / 32;
1419
1420         bindingBits = (quint32 *)realloc(bindingBits,
1421                                          arraySize * sizeof(quint32));
1422
1423         memset(bindingBits + oldArraySize,
1424                0x00,
1425                sizeof(quint32) * (arraySize - oldArraySize));
1426
1427         bindingBitsSize = arraySize * 32;
1428     }
1429
1430     bindingBits[bit / 32] |= (1 << (bit % 32));
1431 }
1432
1433 void QQmlEnginePrivate::sendQuit()
1434 {
1435     Q_Q(QQmlEngine);
1436     emit q->quit();
1437     if (q->receivers(SIGNAL(quit())) == 0) {
1438         qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1439     }
1440 }
1441
1442 static void dumpwarning(const QQmlError &error)
1443 {
1444     QMessageLogger(error.url().toString().toLatin1().constData(),
1445                    error.line(), 0).warning().nospace()
1446             << qPrintable(error.toString());
1447 }
1448
1449 static void dumpwarning(const QList<QQmlError> &errors)
1450 {
1451     for (int ii = 0; ii < errors.count(); ++ii)
1452         dumpwarning(errors.at(ii));
1453 }
1454
1455 void QQmlEnginePrivate::warning(const QQmlError &error)
1456 {
1457     Q_Q(QQmlEngine);
1458     q->warnings(QList<QQmlError>() << error);
1459     if (outputWarningsToStdErr)
1460         dumpwarning(error);
1461 }
1462
1463 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1464 {
1465     Q_Q(QQmlEngine);
1466     q->warnings(errors);
1467     if (outputWarningsToStdErr)
1468         dumpwarning(errors);
1469 }
1470
1471 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1472 {
1473     if (engine)
1474         QQmlEnginePrivate::get(engine)->warning(error);
1475     else
1476         dumpwarning(error);
1477 }
1478
1479 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1480 {
1481     if (engine)
1482         QQmlEnginePrivate::get(engine)->warning(error);
1483     else
1484         dumpwarning(error);
1485 }
1486
1487 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1488 {
1489     if (engine)
1490         engine->warning(error);
1491     else
1492         dumpwarning(error);
1493 }
1494
1495 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1496 {
1497     if (engine)
1498         engine->warning(error);
1499     else
1500         dumpwarning(error);
1501 }
1502
1503 /*
1504    This function should be called prior to evaluation of any js expression,
1505    so that scarce resources are not freed prematurely (eg, if there is a
1506    nested javascript expression).
1507  */
1508 void QQmlEnginePrivate::referenceScarceResources()
1509 {
1510     scarceResourcesRefCount += 1;
1511 }
1512
1513 /*
1514    This function should be called after evaluation of the js expression is
1515    complete, and so the scarce resources may be freed safely.
1516  */
1517 void QQmlEnginePrivate::dereferenceScarceResources()
1518 {
1519     Q_ASSERT(scarceResourcesRefCount > 0);
1520     scarceResourcesRefCount -= 1;
1521
1522     // if the refcount is zero, then evaluation of the "top level"
1523     // expression must have completed.  We can safely release the
1524     // scarce resources.
1525     if (scarceResourcesRefCount == 0) {
1526         // iterate through the list and release them all.
1527         // note that the actual SRD is owned by the JS engine,
1528         // so we cannot delete the SRD; but we can free the
1529         // memory used by the variant in the SRD.
1530         while (ScarceResourceData *sr = scarceResources.first()) {
1531             sr->data = QVariant();
1532             scarceResources.remove(sr);
1533         }
1534     }
1535 }
1536
1537 /*!
1538   Adds \a path as a directory where the engine searches for
1539   installed modules in a URL-based directory structure.
1540   The \a path may be a local filesystem directory or a URL.
1541
1542   The newly added \a path will be first in the importPathList().
1543
1544   \sa setImportPathList(), {QML Modules}
1545 */
1546 void QQmlEngine::addImportPath(const QString& path)
1547 {
1548     Q_D(QQmlEngine);
1549     d->importDatabase.addImportPath(path);
1550 }
1551
1552 /*!
1553   Returns the list of directories where the engine searches for
1554   installed modules in a URL-based directory structure.
1555
1556   For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1557   imports \c com.mycompany.Feature will cause the QQmlEngine to look
1558   in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1559   provided by that module. A \c qmldir file is required for defining the
1560   type version mapping and possibly QML extensions plugins.
1561
1562   By default, the list contains the directory of the application executable,
1563   paths specified in the \c QML_IMPORT_PATH environment variable,
1564   and the builtin \c ImportsPath from QLibraryInfo.
1565
1566   \sa addImportPath(), setImportPathList()
1567 */
1568 QStringList QQmlEngine::importPathList() const
1569 {
1570     Q_D(const QQmlEngine);
1571     return d->importDatabase.importPathList();
1572 }
1573
1574 /*!
1575   Sets \a paths as the list of directories where the engine searches for
1576   installed modules in a URL-based directory structure.
1577
1578   By default, the list contains the directory of the application executable,
1579   paths specified in the \c QML_IMPORT_PATH environment variable,
1580   and the builtin \c ImportsPath from QLibraryInfo.
1581
1582   \sa importPathList(), addImportPath()
1583   */
1584 void QQmlEngine::setImportPathList(const QStringList &paths)
1585 {
1586     Q_D(QQmlEngine);
1587     d->importDatabase.setImportPathList(paths);
1588 }
1589
1590
1591 /*!
1592   Adds \a path as a directory where the engine searches for
1593   native plugins for imported modules (referenced in the \c qmldir file).
1594
1595   By default, the list contains only \c .,  i.e. the engine searches
1596   in the directory of the \c qmldir file itself.
1597
1598   The newly added \a path will be first in the pluginPathList().
1599
1600   \sa setPluginPathList()
1601 */
1602 void QQmlEngine::addPluginPath(const QString& path)
1603 {
1604     Q_D(QQmlEngine);
1605     d->importDatabase.addPluginPath(path);
1606 }
1607
1608
1609 /*!
1610   Returns the list of directories where the engine searches for
1611   native plugins for imported modules (referenced in the \c qmldir file).
1612
1613   By default, the list contains only \c .,  i.e. the engine searches
1614   in the directory of the \c qmldir file itself.
1615
1616   \sa addPluginPath(), setPluginPathList()
1617 */
1618 QStringList QQmlEngine::pluginPathList() const
1619 {
1620     Q_D(const QQmlEngine);
1621     return d->importDatabase.pluginPathList();
1622 }
1623
1624 /*!
1625   Sets the list of directories where the engine searches for
1626   native plugins for imported modules (referenced in the \c qmldir file)
1627   to \a paths.
1628
1629   By default, the list contains only \c .,  i.e. the engine searches
1630   in the directory of the \c qmldir file itself.
1631
1632   \sa pluginPathList(), addPluginPath()
1633   */
1634 void QQmlEngine::setPluginPathList(const QStringList &paths)
1635 {
1636     Q_D(QQmlEngine);
1637     d->importDatabase.setPluginPathList(paths);
1638 }
1639
1640 /*!
1641   Imports the plugin named \a filePath with the \a uri provided.
1642   Returns true if the plugin was successfully imported; otherwise returns false.
1643
1644   On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1645
1646   The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1647 */
1648 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1649 {
1650     Q_D(QQmlEngine);
1651     return d->importDatabase.importPlugin(filePath, uri, errors);
1652 }
1653
1654 /*!
1655   Imports the plugin named \a filePath with the \a uri provided.
1656   Returns true if the plugin was successfully imported; otherwise returns false.
1657
1658   On failure and if non-null, *\a errorString will be set to a message describing the failure.
1659
1660   The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1661 */
1662 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1663 {
1664     Q_D(QQmlEngine);
1665     QList<QQmlError> errors;
1666     bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1667     if (!errors.isEmpty()) {
1668         QString builtError;
1669         for (int i = 0; i < errors.size(); ++i) {
1670             builtError = QString(QLatin1String("%1\n        %2"))
1671                     .arg(builtError)
1672                     .arg(errors.at(i).toString());
1673         }
1674         *errorString = builtError;
1675     }
1676     return retn;
1677 }
1678
1679 /*!
1680   \property QQmlEngine::offlineStoragePath
1681   \brief the directory for storing offline user data
1682
1683   Returns the directory where SQL and other offline
1684   storage is placed.
1685
1686   QQuickWebView and the SQL databases created with openDatabase()
1687   are stored here.
1688
1689   The default is QML/OfflineStorage in the platform-standard
1690   user application data directory.
1691
1692   Note that the path may not currently exist on the filesystem, so
1693   callers wanting to \e create new files at this location should create
1694   it first - see QDir::mkpath().
1695 */
1696 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1697 {
1698     Q_D(QQmlEngine);
1699     d->offlineStoragePath = dir;
1700 }
1701
1702 QString QQmlEngine::offlineStoragePath() const
1703 {
1704     Q_D(const QQmlEngine);
1705     return d->offlineStoragePath;
1706 }
1707
1708 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1709 {
1710     Q_Q(QQmlEngine);
1711
1712     if (!mo->superClass()) {
1713         QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1714         propertyCache.insert(mo, rv);
1715         return rv;
1716     } else {
1717         QQmlPropertyCache *super = cache(mo->superClass());
1718         QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1719         propertyCache.insert(mo, rv);
1720         return rv;
1721     }
1722 }
1723
1724 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1725                                                                   QQmlError &error)
1726 {
1727     QList<QQmlType *> types;
1728
1729     int maxMinorVersion = 0;
1730
1731     const QMetaObject *metaObject = type->metaObject();
1732
1733     while (metaObject) {
1734         QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1735                                                             type->majorVersion(), minorVersion);
1736         if (t) {
1737             maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1738             types << t;
1739         } else {
1740             types << 0;
1741         }
1742
1743         metaObject = metaObject->superClass();
1744     }
1745
1746     if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1747         c->addref();
1748         typePropertyCache.insert(qMakePair(type, minorVersion), c);
1749         return c;
1750     }
1751
1752     QQmlPropertyCache *raw = cache(type->metaObject());
1753
1754     bool hasCopied = false;
1755
1756     for (int ii = 0; ii < types.count(); ++ii) {
1757         QQmlType *currentType = types.at(ii);
1758         if (!currentType)
1759             continue;
1760
1761         int rev = currentType->metaObjectRevision();
1762         int moIndex = types.count() - 1 - ii;
1763
1764         if (raw->allowedRevisionCache[moIndex] != rev) {
1765             if (!hasCopied) {
1766                 raw = raw->copy();
1767                 hasCopied = true;
1768             }
1769             raw->allowedRevisionCache[moIndex] = rev;
1770         }
1771     }
1772
1773     // Test revision compatibility - the basic rule is:
1774     //    * Anything that is excluded, cannot overload something that is not excluded *
1775
1776     // Signals override:
1777     //    * other signals and methods of the same name.
1778     //    * properties named on<Signal Name>
1779     //    * automatic <property name>Changed notify signals
1780
1781     // Methods override:
1782     //    * other methods of the same name
1783
1784     // Properties override:
1785     //    * other elements of the same name
1786
1787     bool overloadError = false;
1788     QString overloadName;
1789
1790 #if 0
1791     for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1792          !overloadError && iter != raw->stringCache.end();
1793          ++iter) {
1794
1795         QQmlPropertyData *d = *iter;
1796         if (raw->isAllowedInRevision(d))
1797             continue; // Not excluded - no problems
1798
1799         // check that a regular "name" overload isn't happening
1800         QQmlPropertyData *current = d;
1801         while (!overloadError && current) {
1802             current = d->overrideData(current);
1803             if (current && raw->isAllowedInRevision(current))
1804                 overloadError = true;
1805         }
1806     }
1807 #endif
1808
1809     if (overloadError) {
1810         if (hasCopied) raw->release();
1811
1812         error.setDescription(QLatin1String("Type ") + type->qmlTypeName() + QLatin1Char(' ') + QString::number(type->majorVersion()) + QLatin1Char('.') + QString::number(minorVersion) + QLatin1String(" contains an illegal property \"") + overloadName + QLatin1String("\".  This is an error in the type's implementation."));
1813         return 0;
1814     }
1815
1816     if (!hasCopied) raw->addref();
1817     typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1818
1819     if (minorVersion != maxMinorVersion) {
1820         raw->addref();
1821         typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1822     }
1823
1824     return raw;
1825 }
1826
1827 QQmlMetaType::ModuleApiInstance *
1828 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1829 {
1830     Locker locker(this);
1831
1832     QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1833     if (!a) {
1834         a = new QQmlMetaType::ModuleApiInstance;
1835         a->scriptCallback = module.script;
1836         a->qobjectCallback = module.qobject;
1837         a->instanceMetaObject = module.instanceMetaObject;
1838         moduleApiInstances.insert(module, a);
1839     }
1840
1841     return a;
1842 }
1843
1844 bool QQmlEnginePrivate::isQObject(int t)
1845 {
1846     Locker locker(this);
1847     return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1848 }
1849
1850 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1851 {
1852     Locker locker(this);
1853     int t = v.userType();
1854     if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1855         if (ok) *ok = true;
1856         return *(QObject **)(v.constData());
1857     } else {
1858         return QQmlMetaType::toQObject(v, ok);
1859     }
1860 }
1861
1862 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1863 {
1864     Locker locker(this);
1865     if (m_compositeTypes.contains(t))
1866         return QQmlMetaType::Object;
1867     else if (m_qmlLists.contains(t))
1868         return QQmlMetaType::List;
1869     else
1870         return QQmlMetaType::typeCategory(t);
1871 }
1872
1873 bool QQmlEnginePrivate::isList(int t) const
1874 {
1875     Locker locker(this);
1876     return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1877 }
1878
1879 int QQmlEnginePrivate::listType(int t) const
1880 {
1881     Locker locker(this);
1882     QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1883     if (iter != m_qmlLists.end())
1884         return *iter;
1885     else
1886         return QQmlMetaType::listType(t);
1887 }
1888
1889 const QMetaObject *QQmlEnginePrivate::rawMetaObjectForType(int t) const
1890 {
1891     Locker locker(this);
1892     QHash<int, const QMetaObject *>::ConstIterator iter = m_compositeTypes.find(t);
1893     if (iter != m_compositeTypes.end()) {
1894         return *iter;
1895     } else {
1896         QQmlType *type = QQmlMetaType::qmlType(t);
1897         return type?type->baseMetaObject():0;
1898     }
1899 }
1900
1901 const QMetaObject *QQmlEnginePrivate::metaObjectForType(int t) const
1902 {
1903     Locker locker(this);
1904     QHash<int, const QMetaObject *>::ConstIterator iter = m_compositeTypes.find(t);
1905     if (iter != m_compositeTypes.end()) {
1906         return *iter;
1907     } else {
1908         QQmlType *type = QQmlMetaType::qmlType(t);
1909         return type?type->metaObject():0;
1910     }
1911 }
1912
1913 void QQmlEnginePrivate::registerCompositeType(const QMetaObject *mo)
1914 {
1915     QByteArray name = mo->className();
1916
1917     QByteArray ptr = name + '*';
1918     QByteArray lst = "QQmlListProperty<" + name + '>';
1919
1920     int ptr_type = QMetaType::registerNormalizedType(ptr,
1921                                                      qMetaTypeDeleteHelper<QObject*>,
1922                                                      qMetaTypeCreateHelper<QObject*>,
1923                                                      qMetaTypeDestructHelper<QObject*>,
1924                                                      qMetaTypeConstructHelper<QObject*>,
1925                                                      sizeof(QObject*),
1926                                                      static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QObject*>::Flags),
1927                                                      mo);
1928     int lst_type = QMetaType::registerNormalizedType(lst,
1929                                                      qMetaTypeDeleteHelper<QQmlListProperty<QObject> >,
1930                                                      qMetaTypeCreateHelper<QQmlListProperty<QObject> >,
1931                                                      qMetaTypeDestructHelper<QQmlListProperty<QObject> >,
1932                                                      qMetaTypeConstructHelper<QQmlListProperty<QObject> >,
1933                                                      sizeof(QQmlListProperty<QObject>),
1934                                                      static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<QObject> >::Flags),
1935                                                      static_cast<QMetaObject*>(0));
1936
1937     Locker locker(this);
1938     m_qmlLists.insert(lst_type, ptr_type);
1939     m_compositeTypes.insert(ptr_type, mo);
1940 }
1941
1942 void QQmlEnginePrivate::unregisterCompositeType(const QMetaObject *mo)
1943 {
1944     QByteArray name = mo->className();
1945
1946     QByteArray ptr = name + '*';
1947     QByteArray lst = "QQmlListProperty<" + name + '>';
1948
1949     int ptr_type = QMetaType::type(ptr.constData());
1950     int lst_type = QMetaType::type(lst.constData());
1951
1952     Locker locker(this);
1953     m_qmlLists.remove(lst_type);
1954     m_compositeTypes.remove(ptr_type);
1955 }
1956
1957 void QQmlEnginePrivate::clearCache()
1958 {
1959     typeLoader.clearCache(this, &QQmlEnginePrivate::typeUnloaded);
1960 }
1961
1962 void QQmlEnginePrivate::trimCache()
1963 {
1964     typeLoader.trimCache(this, &QQmlEnginePrivate::typeUnloaded);
1965 }
1966
1967 void QQmlEnginePrivate::typeUnloaded(QQmlTypeData *typeData)
1968 {
1969     if (typeData && typeData->compiledData()) {
1970         const QMetaObject *mo = typeData->compiledData()->root;
1971         if (QQmlPropertyCache *pc = propertyCache.value(mo)) {
1972             propertyCache.remove(mo);
1973             pc->release();
1974         }
1975         unregisterCompositeType(mo);
1976     }
1977 }
1978
1979 bool QQmlEnginePrivate::isTypeLoaded(const QUrl &url) const
1980 {
1981     return typeLoader.isTypeLoaded(url);
1982 }
1983
1984 bool QQmlEnginePrivate::isScriptLoaded(const QUrl &url) const
1985 {
1986     return typeLoader.isScriptLoaded(url);
1987 }
1988
1989 bool QQml_isFileCaseCorrect(const QString &fileName)
1990 {
1991 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1992     QFileInfo info(fileName);
1993     const QString absolute = info.absoluteFilePath();
1994
1995 #if defined(Q_OS_MAC)
1996     const QString canonical = info.canonicalFilePath();
1997 #elif defined(Q_OS_WIN)
1998     wchar_t buffer[1024];
1999
2000     DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
2001     if (rv == 0 || rv >= 1024) return true;
2002     rv = ::GetLongPathName(buffer, buffer, 1024);
2003     if (rv == 0 || rv >= 1024) return true;
2004
2005     const QString canonical = QString::fromWCharArray(buffer);
2006 #endif
2007
2008     const int absoluteLength = absolute.length();
2009     const int canonicalLength = canonical.length();
2010
2011     const int length = qMin(absoluteLength, canonicalLength);
2012     for (int ii = 0; ii < length; ++ii) {
2013         const QChar &a = absolute.at(absoluteLength - 1 - ii);
2014         const QChar &c = canonical.at(canonicalLength - 1 - ii);
2015
2016         if (a.toLower() != c.toLower())
2017             return true;
2018         if (a != c)
2019             return false;
2020     }
2021 #else
2022     Q_UNUSED(fileName)
2023 #endif
2024     return true;
2025 }
2026
2027 /*!
2028     \fn QQmlEngine *qmlEngine(const QObject *object)
2029     \relates QQmlEngine
2030
2031     Returns the QQmlEngine associated with \a object, if any.  This is equivalent to
2032     QQmlEngine::contextForObject(object)->engine(), but more efficient.
2033 */
2034
2035 /*!
2036     \fn QQmlContext *qmlContext(const QObject *object)
2037     \relates QQmlEngine
2038
2039     Returns the QQmlContext associated with \a object, if any.  This is equivalent to
2040     QQmlEngine::contextForObject(object).
2041 */
2042
2043 QT_END_NAMESPACE