QtQuick: Fix string related warnings, single character strings.
[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     The following example uses the \c application object to indicate
358     whether the application is currently active:
359
360     \snippet doc/snippets/qml/application.qml document
361
362     \qmlproperty object Qt::inputMethod
363     \since QtQuick 2.0
364
365     The \c inputMethod object allows access to application's QInputMethod object
366     and all its properties and slots. See the QInputMethod documentation for
367     further details.
368 */
369
370
371 /*!
372 \qmlmethod object Qt::include(string url, jsobject callback)
373
374 Includes another JavaScript file. This method can only be used from within JavaScript files,
375 and not regular QML files.
376
377 This imports all functions from \a url into the current script's namespace.
378
379 Qt.include() returns an object that describes the status of the operation.  The object has
380 a single property, \c {status}, that is set to one of the following values:
381
382 \table
383 \header \li Symbol \li Value \li Description
384 \row \li result.OK \li 0 \li The include completed successfully.
385 \row \li result.LOADING \li 1 \li Data is being loaded from the network.
386 \row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
387 \row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
388 An additional \c exception property will be set in this case.
389 \endtable
390
391 The \c status property will be updated as the operation progresses.
392
393 If provided, \a callback is invoked when the operation completes.  The callback is passed
394 the same object as is returned from the Qt.include() call.
395 */
396 // Qt.include() is implemented in qv8include.cpp
397
398
399 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
400 : propertyCapture(0), rootContext(0), isDebugging(false),
401   outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
402   cleanup(0), erroredBindings(0), inProgressCreations(0),
403   workerScriptEngine(0), activeVME(0),
404   networkAccessManager(0), networkAccessManagerFactory(0),
405   scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
406   incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
407 {
408 }
409
410 QQmlEnginePrivate::~QQmlEnginePrivate()
411 {
412     if (inProgressCreations)
413         qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
414
415     while (cleanup) {
416         QQmlCleanup *c = cleanup;
417         cleanup = c->next;
418         if (cleanup) cleanup->prev = &cleanup;
419         c->next = 0;
420         c->prev = 0;
421         c->clear();
422     }
423
424     doDeleteInEngineThread();
425
426     if (incubationController) incubationController->d = 0;
427     incubationController = 0;
428
429     delete rootContext;
430     rootContext = 0;
431
432     for(QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
433         (*iter)->release();
434     for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
435         (*iter)->release();
436     for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
437         (*iter)->release();
438     for(QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
439         delete (*iter)->qobjectApi;
440         delete *iter;
441     }
442 }
443
444 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
445 {
446     QObjectPrivate *p = QObjectPrivate::get(o);
447     if (p->declarativeData) {
448         QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
449         if (d->ownContext && d->context) {
450             d->context->destroy();
451             d->context = 0;
452         }
453
454         // Mark this object as in the process of deletion to
455         // prevent it resolving in bindings
456         QQmlData::markAsDeleted(o);
457     }
458 }
459
460 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
461 {
462     static_cast<QQmlData *>(d)->destroyed(o);
463 }
464
465 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
466 {
467     static_cast<QQmlData *>(d)->parentChanged(o, p);
468 }
469
470 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **a)
471 {
472     QQmlData *ddata = QQmlData::get(object, false);
473     if (!ddata) return; // Probably being deleted
474
475     // In general, QML only supports QObject's that live on the same thread as the QQmlEngine
476     // that they're exposed to.  However, to make writing "worker objects" that calculate data
477     // in a separate thread easier, QML allows a QObject that lives in the same thread as the
478     // QQmlEngine to emit signals from a different thread.  These signals are then automatically
479     // marshalled back onto the QObject's thread and handled by QML from there.  This is tested
480     // by the qqmlecmascript::threadSignal() autotest.
481     if (ddata->notifyList &&
482         QThread::currentThreadId() != QObjectPrivate::get(object)->threadData->threadId) {
483
484         QMetaMethod m = object->metaObject()->method(index);
485         QList<QByteArray> parameterTypes = m.parameterTypes();
486
487         int *types = (int *)malloc((parameterTypes.count() + 1) * sizeof(int));
488         void **args = (void **) malloc((parameterTypes.count() + 1) *sizeof(void *));
489
490         types[0] = 0; // return type
491         args[0] = 0; // return value
492
493         for (int ii = 0; ii < parameterTypes.count(); ++ii) {
494             const QByteArray &typeName = parameterTypes.at(ii);
495             if (typeName.endsWith('*'))
496                 types[ii + 1] = QMetaType::VoidStar;
497             else
498                 types[ii + 1] = QMetaType::type(typeName);
499
500             if (!types[ii + 1]) {
501                 qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
502                          "(Make sure '%s' is registered using qRegisterMetaType().)",
503                          typeName.constData(), typeName.constData());
504                 free(types);
505                 free(args);
506                 return;
507             }
508
509             args[ii + 1] = QMetaType::create(types[ii + 1], a[ii + 1]);
510         }
511
512         QMetaCallEvent *ev = new QMetaCallEvent(index, 0, 0, object, index,
513                                                 parameterTypes.count() + 1, types, args);
514         QCoreApplication::postEvent(object, ev);
515
516     } else {
517         QQmlNotifierEndpoint *ep = ddata->notify(index);
518         if (ep) QQmlNotifier::emitNotify(ep, a);
519     }
520 }
521
522 int QQmlData::receivers(QAbstractDeclarativeData *d, const QObject *, int index)
523 {
524     return static_cast<QQmlData *>(d)->endpointCount(index);
525 }
526
527 int QQmlData::endpointCount(int index)
528 {
529     int count = 0;
530     QQmlNotifierEndpoint *ep = notify(index);
531     if (!ep)
532         return count;
533     ++count;
534     while (ep->next) {
535         ++count;
536         ep = ep->next;
537     }
538     return count;
539 }
540
541 void QQmlData::markAsDeleted(QObject *o)
542 {
543     QQmlData::setQueuedForDeletion(o);
544
545     QObjectPrivate *p = QObjectPrivate::get(o);
546     for (QList<QObject *>::iterator it = p->children.begin(), end = p->children.end(); it != end; ++it) {
547         QQmlData::markAsDeleted(*it);
548     }
549 }
550
551 void QQmlData::setQueuedForDeletion(QObject *object)
552 {
553     if (object) {
554         if (QObjectPrivate *priv = QObjectPrivate::get(object)) {
555             if (!priv->wasDeleted && priv->declarativeData) {
556                 QQmlData *ddata = QQmlData::get(object, false);
557                 if (ddata->ownContext && ddata->context)
558                     ddata->context->emitDestruction();
559                 ddata->isQueuedForDeletion = true;
560             }
561         }
562     }
563 }
564
565 void QQmlEnginePrivate::init()
566 {
567     Q_Q(QQmlEngine);
568
569     static bool firstTime = true;
570     if (firstTime) {
571         qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component");
572
573         QQmlData::init();
574         firstTime = false;
575     }
576
577     qRegisterMetaType<QVariant>("QVariant");
578     qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
579     qRegisterMetaType<QJSValue>("QJSValue");
580     qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
581     qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
582     qRegisterMetaType<QList<int> >("QList<int>");
583     qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
584
585     v8engine()->setEngine(q);
586
587     rootContext = new QQmlContext(q,true);
588
589     if (QCoreApplication::instance()->thread() == q->thread() &&
590         QQmlEngineDebugService::isDebuggingEnabled()) {
591         isDebugging = true;
592         QQmlEngineDebugService::instance()->addEngine(q);
593         QV8DebugService::initialize(v8engine());
594         QV8ProfilerService::initialize();
595         QQmlProfilerService::initialize();
596         QDebugMessageService::instance();
597     }
598
599     QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
600     if (!dataLocation.isEmpty())
601         offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator())
602                            + QDir::separator() + QLatin1String("QML")
603                            + QDir::separator() + QLatin1String("OfflineStorage");
604 }
605
606 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
607 {
608     Q_Q(QQmlEngine);
609     if (!workerScriptEngine)
610         workerScriptEngine = new QQuickWorkerScriptEngine(q);
611     return workerScriptEngine;
612 }
613
614 /*!
615   \class QQmlEngine
616   \since 5.0
617   \inmodule QtQml
618   \brief The QQmlEngine class provides an environment for instantiating QML components.
619   \mainclass
620
621   Each QML component is instantiated in a QQmlContext.
622   QQmlContext's are essential for passing data to QML
623   components.  In QML, contexts are arranged hierarchically and this
624   hierarchy is managed by the QQmlEngine.
625
626   Prior to creating any QML components, an application must have
627   created a QQmlEngine to gain access to a QML context.  The
628   following example shows how to create a simple Text item.
629
630   \code
631   QQmlEngine engine;
632   QQmlComponent component(&engine);
633   component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
634   QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
635
636   //add item to view, etc
637   ...
638   \endcode
639
640   In this case, the Text item will be created in the engine's
641   \l {QQmlEngine::rootContext()}{root context}.
642
643   Note that the QtQuick 1 version is called QDeclarativeEngine.
644
645   \sa QQmlComponent, QQmlContext
646 */
647
648 /*!
649   Create a new QQmlEngine with the given \a parent.
650 */
651 QQmlEngine::QQmlEngine(QObject *parent)
652 : QJSEngine(*new QQmlEnginePrivate(this), parent)
653 {
654     Q_D(QQmlEngine);
655     d->init();
656 }
657
658 /*!
659   Destroys the QQmlEngine.
660
661   Any QQmlContext's created on this engine will be
662   invalidated, but not destroyed (unless they are parented to the
663   QQmlEngine object).
664 */
665 QQmlEngine::~QQmlEngine()
666 {
667     Q_D(QQmlEngine);
668     if (d->isDebugging) {
669         QQmlEngineDebugService::instance()->remEngine(this);
670     }
671
672     // Emit onDestruction signals for the root context before
673     // we destroy the contexts, engine, Module APIs etc. that
674     // may be required to handle the destruction signal.
675     QQmlContextData::get(rootContext())->emitDestruction();
676
677     // if we are the parent of any of the qobject module api instances,
678     // we need to remove them from our internal list, in order to prevent
679     // a segfault in engine private dtor.
680     QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
681     QObject *currQObjectApi = 0;
682     QQmlMetaType::ModuleApiInstance *currInstance = 0;
683     foreach (const QQmlMetaType::ModuleApi &key, keys) {
684         currInstance = d->moduleApiInstances.value(key);
685         currQObjectApi = currInstance->qobjectApi;
686         if (this->children().contains(currQObjectApi)) {
687             delete currQObjectApi;
688             delete currInstance;
689             d->moduleApiInstances.remove(key);
690         }
691     }
692
693     if (d->incubationController)
694         d->incubationController->d = 0;
695 }
696
697 /*! \fn void QQmlEngine::quit()
698     This signal is emitted when the QML loaded by the engine would like to quit.
699  */
700
701 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
702     This signal is emitted when \a warnings messages are generated by QML.
703  */
704
705 /*!
706   Clears the engine's internal component cache.
707
708   This function causes the property metadata of all components previously
709   loaded by the engine to be destroyed.  All previously loaded components and
710   the property bindings for all extant objects created from those components will
711   cease to function.
712
713   This function returns the engine to a state where it does not contain any loaded
714   component data.  This may be useful in order to reload a smaller subset of the
715   previous component set, or to load a new version of a previously loaded component.
716
717   Once the component cache has been cleared, components must be loaded before
718   any new objects can be created.
719  */
720 void QQmlEngine::clearComponentCache()
721 {
722     Q_D(QQmlEngine);
723     d->typeLoader.clearCache();
724 }
725
726 /*!
727   Returns the engine's root context.
728
729   The root context is automatically created by the QQmlEngine.
730   Data that should be available to all QML component instances
731   instantiated by the engine should be put in the root context.
732
733   Additional data that should only be available to a subset of
734   component instances should be added to sub-contexts parented to the
735   root context.
736 */
737 QQmlContext *QQmlEngine::rootContext() const
738 {
739     Q_D(const QQmlEngine);
740     return d->rootContext;
741 }
742
743 /*!
744   Sets the \a factory to use for creating QNetworkAccessManager(s).
745
746   QNetworkAccessManager is used for all network access by QML.  By
747   implementing a factory it is possible to create custom
748   QNetworkAccessManager with specialized caching, proxy and cookie
749   support.
750
751   The factory must be set before executing the engine.
752 */
753 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
754 {
755     Q_D(QQmlEngine);
756     QMutexLocker locker(&d->mutex);
757     d->networkAccessManagerFactory = factory;
758 }
759
760 /*!
761   Returns the current QQmlNetworkAccessManagerFactory.
762
763   \sa setNetworkAccessManagerFactory()
764 */
765 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
766 {
767     Q_D(const QQmlEngine);
768     return d->networkAccessManagerFactory;
769 }
770
771 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
772 {
773     if (activeVME) {
774         activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
775     } else {
776         void *args[] = { 0 };
777         QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
778     }
779 }
780
781 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
782 {
783     QMutexLocker locker(&mutex);
784     QNetworkAccessManager *nam;
785     if (networkAccessManagerFactory) {
786         nam = networkAccessManagerFactory->create(parent);
787     } else {
788         nam = new QNetworkAccessManager(parent);
789     }
790
791     return nam;
792 }
793
794 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
795 {
796     Q_Q(const QQmlEngine);
797     if (!networkAccessManager)
798         networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
799     return networkAccessManager;
800 }
801
802 /*!
803   Returns a common QNetworkAccessManager which can be used by any QML
804   element instantiated by this engine.
805
806   If a QQmlNetworkAccessManagerFactory has been set and a
807   QNetworkAccessManager has not yet been created, the
808   QQmlNetworkAccessManagerFactory will be used to create the
809   QNetworkAccessManager; otherwise the returned QNetworkAccessManager
810   will have no proxy or cache set.
811
812   \sa setNetworkAccessManagerFactory()
813 */
814 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
815 {
816     Q_D(const QQmlEngine);
817     return d->getNetworkAccessManager();
818 }
819
820 /*!
821
822   Sets the \a provider to use for images requested via the \e
823   image: url scheme, with host \a providerId. The QQmlEngine
824   takes ownership of \a provider.
825
826   Image providers enable support for pixmap and threaded image
827   requests. See the QQuickImageProvider documentation for details on
828   implementing and using image providers.
829
830   All required image providers should be added to the engine before any
831   QML sources files are loaded.
832
833   \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
834 */
835 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
836 {
837     Q_D(QQmlEngine);
838     QMutexLocker locker(&d->mutex);
839     d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
840 }
841
842 /*!
843   Returns the image provider set for \a providerId.
844
845   Returns the provider if it was found; otherwise returns 0.
846
847   \sa QQuickImageProvider
848 */
849 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
850 {
851     Q_D(const QQmlEngine);
852     QMutexLocker locker(&d->mutex);
853     return d->imageProviders.value(providerId).data();
854 }
855
856 /*!
857   Removes the image provider for \a providerId.
858
859   \sa addImageProvider(), QQuickImageProvider
860 */
861 void QQmlEngine::removeImageProvider(const QString &providerId)
862 {
863     Q_D(QQmlEngine);
864     QMutexLocker locker(&d->mutex);
865     d->imageProviders.take(providerId);
866 }
867
868 /*!
869   Return the base URL for this engine.  The base URL is only used to
870   resolve components when a relative URL is passed to the
871   QQmlComponent constructor.
872
873   If a base URL has not been explicitly set, this method returns the
874   application's current working directory.
875
876   \sa setBaseUrl()
877 */
878 QUrl QQmlEngine::baseUrl() const
879 {
880     Q_D(const QQmlEngine);
881     if (d->baseUrl.isEmpty()) {
882         return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
883     } else {
884         return d->baseUrl;
885     }
886 }
887
888 /*!
889   Set the  base URL for this engine to \a url.
890
891   \sa baseUrl()
892 */
893 void QQmlEngine::setBaseUrl(const QUrl &url)
894 {
895     Q_D(QQmlEngine);
896     d->baseUrl = url;
897 }
898
899 /*!
900   Returns true if warning messages will be output to stderr in addition
901   to being emitted by the warnings() signal, otherwise false.
902
903   The default value is true.
904 */
905 bool QQmlEngine::outputWarningsToStandardError() const
906 {
907     Q_D(const QQmlEngine);
908     return d->outputWarningsToStdErr;
909 }
910
911 /*!
912   Set whether warning messages will be output to stderr to \a enabled.
913
914   If \a enabled is true, any warning messages generated by QML will be
915   output to stderr and emitted by the warnings() signal.  If \a enabled
916   is false, on the warnings() signal will be emitted.  This allows
917   applications to handle warning output themselves.
918
919   The default value is true.
920 */
921 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
922 {
923     Q_D(QQmlEngine);
924     d->outputWarningsToStdErr = enabled;
925 }
926
927 /*!
928   Attempt to free unused memory.
929 */
930 void QQmlEngine::collectGarbage()
931 {
932     QV8Engine::gc();
933 }
934
935 /*!
936   Returns the QQmlContext for the \a object, or 0 if no
937   context has been set.
938
939   When the QQmlEngine instantiates a QObject, the context is
940   set automatically.
941   */
942 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
943 {
944     if(!object)
945         return 0;
946
947     QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
948
949     QQmlData *data =
950         static_cast<QQmlData *>(priv->declarativeData);
951
952     if (!data)
953         return 0;
954     else if (data->outerContext)
955         return data->outerContext->asQQmlContext();
956     else
957         return 0;
958 }
959
960 /*!
961   Sets the QQmlContext for the \a object to \a context.
962   If the \a object already has a context, a warning is
963   output, but the context is not changed.
964
965   When the QQmlEngine instantiates a QObject, the context is
966   set automatically.
967  */
968 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
969 {
970     if (!object || !context)
971         return;
972
973     QQmlData *data = QQmlData::get(object, true);
974     if (data->context) {
975         qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
976         return;
977     }
978
979     QQmlContextData *contextData = QQmlContextData::get(context);
980     contextData->addObject(object);
981 }
982
983 /*!
984   \enum QQmlEngine::ObjectOwnership
985
986   Ownership controls whether or not QML automatically destroys the
987   QObject when the object is garbage collected by the JavaScript
988   engine.  The two ownership options are:
989
990   \value CppOwnership The object is owned by C++ code, and will
991   never be deleted by QML.  The JavaScript destroy() method cannot be
992   used on objects with CppOwnership.  This option is similar to
993   QScriptEngine::QtOwnership.
994
995   \value JavaScriptOwnership The object is owned by JavaScript.
996   When the object is returned to QML as the return value of a method
997   call or property access, QML will track it, and delete the object
998   if there are no remaining JavaScript references to it and it has no
999   QObject::parent().  An object tracked by one QQmlEngine
1000   will be deleted during that QQmlEngine's destructor, and thus
1001   JavaScript references between objects with JavaScriptOwnership from
1002   two different engines will not be valid after the deletion of one of
1003   those engines.  This option is similar to QScriptEngine::ScriptOwnership.
1004
1005   Generally an application doesn't need to set an object's ownership
1006   explicitly.  QML uses a heuristic to set the default object
1007   ownership.  By default, an object that is created by QML has
1008   JavaScriptOwnership.  The exception to this are the root objects
1009   created by calling QQmlComponent::create() or
1010   QQmlComponent::beginCreate() which have CppOwnership by
1011   default.  The ownership of these root-level objects is considered to
1012   have been transferred to the C++ caller.
1013
1014   Objects not-created by QML have CppOwnership by default.  The
1015   exception to this is objects returned from a C++ method call.  The
1016   ownership of these objects is passed to JavaScript.
1017
1018   Calling setObjectOwnership() overrides the default ownership
1019   heuristic used by QML.
1020 */
1021
1022 /*!
1023   Sets the \a ownership of \a object.
1024 */
1025 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
1026 {
1027     if (!object)
1028         return;
1029
1030     QQmlData *ddata = QQmlData::get(object, true);
1031     if (!ddata)
1032         return;
1033
1034     ddata->indestructible = (ownership == CppOwnership)?true:false;
1035     ddata->explicitIndestructibleSet = true;
1036 }
1037
1038 /*!
1039   Returns the ownership of \a object.
1040 */
1041 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
1042 {
1043     if (!object)
1044         return CppOwnership;
1045
1046     QQmlData *ddata = QQmlData::get(object, false);
1047     if (!ddata)
1048         return CppOwnership;
1049     else
1050         return ddata->indestructible?CppOwnership:JavaScriptOwnership;
1051 }
1052
1053 bool QQmlEngine::event(QEvent *e)
1054 {
1055     Q_D(QQmlEngine);
1056     if (e->type() == QEvent::User)
1057         d->doDeleteInEngineThread();
1058
1059     return QJSEngine::event(e);
1060 }
1061
1062 void QQmlEnginePrivate::doDeleteInEngineThread()
1063 {
1064     QFieldList<Deletable, &Deletable::next> list;
1065     mutex.lock();
1066     list.copyAndClear(toDeleteInEngineThread);
1067     mutex.unlock();
1068
1069     while (Deletable *d = list.takeFirst())
1070         delete d;
1071 }
1072
1073 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
1074 {
1075     QQmlData *data = QQmlData::get(object);
1076
1077     if (data && data->deferredComponent) {
1078         QQmlObjectCreatingProfiler prof;
1079         if (prof.enabled) {
1080             QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
1081             prof.setTypeName(type ? type->qmlTypeName()
1082                                   : QString::fromUtf8(object->metaObject()->className()));
1083             if (data->outerContext)
1084                 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
1085         }
1086         QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
1087
1088         QQmlComponentPrivate::ConstructionState state;
1089         QQmlComponentPrivate::beginDeferred(ep, object, &state);
1090
1091         data->deferredComponent->release();
1092         data->deferredComponent = 0;
1093
1094         QQmlComponentPrivate::complete(ep, &state);
1095     }
1096 }
1097
1098 QQmlContext *qmlContext(const QObject *obj)
1099 {
1100     return QQmlEngine::contextForObject(obj);
1101 }
1102
1103 QQmlEngine *qmlEngine(const QObject *obj)
1104 {
1105     QQmlData *data = QQmlData::get(obj, false);
1106     if (!data || !data->context)
1107         return 0;
1108     return data->context->engine;
1109 }
1110
1111 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1112 {
1113     QQmlData *data = QQmlData::get(object);
1114     if (!data)
1115         return 0; // Attached properties are only on objects created by QML
1116
1117     QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1118     if (rv || !create)
1119         return rv;
1120
1121     QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1122     if (!pf)
1123         return 0;
1124
1125     rv = pf(const_cast<QObject *>(object));
1126
1127     if (rv)
1128         data->attachedProperties()->insert(id, rv);
1129
1130     return rv;
1131 }
1132
1133 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1134                                      const QMetaObject *attachedMetaObject, bool create)
1135 {
1136     if (*idCache == -1)
1137         *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1138
1139     if (*idCache == -1 || !object)
1140         return 0;
1141
1142     return qmlAttachedPropertiesObjectById(*idCache, object, create);
1143 }
1144
1145 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1146 {
1147 #ifndef QQML_NO_DEBUG_PROTOCOL
1148     if (!QQmlEnginePrivate::qml_debugging_enabled
1149             && printWarning) {
1150         qDebug("QML debugging is enabled. Only use this in a safe environment.");
1151     }
1152     QQmlEnginePrivate::qml_debugging_enabled = true;
1153 #endif
1154 }
1155
1156
1157 class QQmlDataExtended {
1158 public:
1159     QQmlDataExtended();
1160     ~QQmlDataExtended();
1161
1162     QHash<int, QObject *> attachedProperties;
1163 };
1164
1165 QQmlDataExtended::QQmlDataExtended()
1166 {
1167 }
1168
1169 QQmlDataExtended::~QQmlDataExtended()
1170 {
1171 }
1172
1173 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1174 {
1175     if (endpoint->next)
1176         layout(endpoint->next);
1177
1178     int index = endpoint->sourceSignal;
1179     index = qMin(index, 0xFFFF - 1);
1180
1181     endpoint->next = notifies[index];
1182     if (endpoint->next) endpoint->next->prev = &endpoint->next;
1183     endpoint->prev = &notifies[index];
1184     notifies[index] = endpoint;
1185 }
1186
1187 void QQmlData::NotifyList::layout()
1188 {
1189     Q_ASSERT(maximumTodoIndex >= notifiesSize);
1190
1191     if (todo) {
1192         QQmlNotifierEndpoint **old = notifies;
1193         const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1194         notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1195         const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1196                                sizeof(QQmlNotifierEndpoint*);
1197         memset(notifies + notifiesSize, 0, memsetSize);
1198
1199         if (notifies != old) {
1200             for (int ii = 0; ii < notifiesSize; ++ii)
1201                 if (notifies[ii])
1202                     notifies[ii]->prev = &notifies[ii];
1203         }
1204
1205         notifiesSize = maximumTodoIndex + 1;
1206
1207         layout(todo);
1208     }
1209
1210     maximumTodoIndex = 0;
1211     todo = 0;
1212 }
1213
1214 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1215 {
1216     if (!notifyList) {
1217         notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1218         notifyList->connectionMask = 0;
1219         notifyList->maximumTodoIndex = 0;
1220         notifyList->notifiesSize = 0;
1221         notifyList->todo = 0;
1222         notifyList->notifies = 0;
1223     }
1224
1225     Q_ASSERT(!endpoint->isConnected());
1226
1227     index = qMin(index, 0xFFFF - 1);
1228     notifyList->connectionMask |= (1ULL << quint64(index % 64));
1229
1230     if (index < notifyList->notifiesSize) {
1231
1232         endpoint->next = notifyList->notifies[index];
1233         if (endpoint->next) endpoint->next->prev = &endpoint->next;
1234         endpoint->prev = &notifyList->notifies[index];
1235         notifyList->notifies[index] = endpoint;
1236
1237     } else {
1238         notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1239
1240         endpoint->next = notifyList->todo;
1241         if (endpoint->next) endpoint->next->prev = &endpoint->next;
1242         endpoint->prev = &notifyList->todo;
1243         notifyList->todo = endpoint;
1244     }
1245 }
1246
1247 bool QQml_isSignalConnected(QObject *obj, int signal_index, int index)
1248 {
1249     QQmlData *data = QQmlData::get(obj);
1250     return QObjectPrivate::get(obj)->isSignalConnected(signal_index) || (data && data->signalHasEndpoint(index));
1251 }
1252
1253 /*
1254     index MUST be the index returned by QMetaMethod::index()
1255     This is different than the index returned by QObjectPrivate::signalIndex()
1256 */
1257 bool QQmlData::signalHasEndpoint(int index)
1258 {
1259     return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
1260 }
1261
1262 QHash<int, QObject *> *QQmlData::attachedProperties() const
1263 {
1264     if (!extendedData) extendedData = new QQmlDataExtended;
1265     return &extendedData->attachedProperties;
1266 }
1267
1268 void QQmlData::destroyed(QObject *object)
1269 {
1270     if (deferredComponent)
1271         deferredComponent->release();
1272
1273     if (nextContextObject)
1274         nextContextObject->prevContextObject = prevContextObject;
1275     if (prevContextObject)
1276         *prevContextObject = nextContextObject;
1277
1278     QQmlAbstractBinding *binding = bindings;
1279     while (binding) {
1280         QQmlAbstractBinding *next = binding->m_nextBinding;
1281         binding->m_prevBinding = 0;
1282         binding->m_nextBinding = 0;
1283         binding->destroy();
1284         binding = next;
1285     }
1286
1287     QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1288     while (signalHandler) {
1289         QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1290         signalHandler->m_prevSignal = 0;
1291         signalHandler->m_nextSignal = 0;
1292         delete signalHandler;
1293         signalHandler = next;
1294     }
1295
1296     if (bindingBits)
1297         free(bindingBits);
1298
1299     if (propertyCache)
1300         propertyCache->release();
1301
1302     if (ownContext && context)
1303         context->destroy();
1304
1305     while (guards) {
1306         QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1307         *guard = (QObject *)0;
1308         guard->objectDestroyed(object);
1309     }
1310
1311     if (notifyList) {
1312         while (notifyList->todo)
1313             notifyList->todo->disconnect();
1314         for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1315             while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1316                 ep->disconnect();
1317         }
1318         free(notifyList->notifies);
1319         free(notifyList);
1320         notifyList = 0;
1321     }
1322
1323     if (extendedData)
1324         delete extendedData;
1325
1326     // Dispose the handle.
1327     // We don't simply clear it (and wait for next gc cycle to dispose
1328     // via the weak qobject reference callback) as this affects the
1329     // outcomes of v8's gc statistical analysis heuristics, which can
1330     // cause unnecessary growth of the old pointer space js heap area.
1331     qPersistentDispose(v8object);
1332
1333     if (ownMemory)
1334         delete this;
1335 }
1336
1337 void QQmlData::parentChanged(QObject *object, QObject *parent)
1338 {
1339     Q_UNUSED(object);
1340     Q_UNUSED(parent);
1341 }
1342
1343 bool QQmlData::hasBindingBit(int bit) const
1344 {
1345     if (bindingBitsSize > bit)
1346         return bindingBits[bit / 32] & (1 << (bit % 32));
1347     else
1348         return false;
1349 }
1350
1351 void QQmlData::clearBindingBit(int bit)
1352 {
1353     if (bindingBitsSize > bit)
1354         bindingBits[bit / 32] &= ~(1 << (bit % 32));
1355 }
1356
1357 void QQmlData::setBindingBit(QObject *obj, int bit)
1358 {
1359     if (bindingBitsSize <= bit) {
1360         int props = obj->metaObject()->propertyCount();
1361         Q_ASSERT(bit < props);
1362
1363         int arraySize = (props + 31) / 32;
1364         int oldArraySize = bindingBitsSize / 32;
1365
1366         bindingBits = (quint32 *)realloc(bindingBits,
1367                                          arraySize * sizeof(quint32));
1368
1369         memset(bindingBits + oldArraySize,
1370                0x00,
1371                sizeof(quint32) * (arraySize - oldArraySize));
1372
1373         bindingBitsSize = arraySize * 32;
1374     }
1375
1376     bindingBits[bit / 32] |= (1 << (bit % 32));
1377 }
1378
1379 void QQmlEnginePrivate::sendQuit()
1380 {
1381     Q_Q(QQmlEngine);
1382     emit q->quit();
1383     if (q->receivers(SIGNAL(quit())) == 0) {
1384         qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1385     }
1386 }
1387
1388 static void dumpwarning(const QQmlError &error)
1389 {
1390     QMessageLogger(error.url().toString().toLatin1().constData(),
1391                    error.line(), 0).warning().nospace()
1392             << qPrintable(error.toString());
1393 }
1394
1395 static void dumpwarning(const QList<QQmlError> &errors)
1396 {
1397     for (int ii = 0; ii < errors.count(); ++ii)
1398         dumpwarning(errors.at(ii));
1399 }
1400
1401 void QQmlEnginePrivate::warning(const QQmlError &error)
1402 {
1403     Q_Q(QQmlEngine);
1404     q->warnings(QList<QQmlError>() << error);
1405     if (outputWarningsToStdErr)
1406         dumpwarning(error);
1407 }
1408
1409 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1410 {
1411     Q_Q(QQmlEngine);
1412     q->warnings(errors);
1413     if (outputWarningsToStdErr)
1414         dumpwarning(errors);
1415 }
1416
1417 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1418 {
1419     if (engine)
1420         QQmlEnginePrivate::get(engine)->warning(error);
1421     else
1422         dumpwarning(error);
1423 }
1424
1425 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1426 {
1427     if (engine)
1428         QQmlEnginePrivate::get(engine)->warning(error);
1429     else
1430         dumpwarning(error);
1431 }
1432
1433 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1434 {
1435     if (engine)
1436         engine->warning(error);
1437     else
1438         dumpwarning(error);
1439 }
1440
1441 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1442 {
1443     if (engine)
1444         engine->warning(error);
1445     else
1446         dumpwarning(error);
1447 }
1448
1449 /*
1450    This function should be called prior to evaluation of any js expression,
1451    so that scarce resources are not freed prematurely (eg, if there is a
1452    nested javascript expression).
1453  */
1454 void QQmlEnginePrivate::referenceScarceResources()
1455 {
1456     scarceResourcesRefCount += 1;
1457 }
1458
1459 /*
1460    This function should be called after evaluation of the js expression is
1461    complete, and so the scarce resources may be freed safely.
1462  */
1463 void QQmlEnginePrivate::dereferenceScarceResources()
1464 {
1465     Q_ASSERT(scarceResourcesRefCount > 0);
1466     scarceResourcesRefCount -= 1;
1467
1468     // if the refcount is zero, then evaluation of the "top level"
1469     // expression must have completed.  We can safely release the
1470     // scarce resources.
1471     if (scarceResourcesRefCount == 0) {
1472         // iterate through the list and release them all.
1473         // note that the actual SRD is owned by the JS engine,
1474         // so we cannot delete the SRD; but we can free the
1475         // memory used by the variant in the SRD.
1476         while (ScarceResourceData *sr = scarceResources.first()) {
1477             sr->data = QVariant();
1478             scarceResources.remove(sr);
1479         }
1480     }
1481 }
1482
1483 /*!
1484   Adds \a path as a directory where the engine searches for
1485   installed modules in a URL-based directory structure.
1486   The \a path may be a local filesystem directory or a URL.
1487
1488   The newly added \a path will be first in the importPathList().
1489
1490   \sa setImportPathList(), {QML Modules}
1491 */
1492 void QQmlEngine::addImportPath(const QString& path)
1493 {
1494     Q_D(QQmlEngine);
1495     d->importDatabase.addImportPath(path);
1496 }
1497
1498 /*!
1499   Returns the list of directories where the engine searches for
1500   installed modules in a URL-based directory structure.
1501
1502   For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1503   imports \c com.mycompany.Feature will cause the QQmlEngine to look
1504   in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1505   provided by that module. A \c qmldir file is required for defining the
1506   type version mapping and possibly QML extensions plugins.
1507
1508   By default, the list contains the directory of the application executable,
1509   paths specified in the \c QML_IMPORT_PATH environment variable,
1510   and the builtin \c ImportsPath from QLibraryInfo.
1511
1512   \sa addImportPath(), setImportPathList()
1513 */
1514 QStringList QQmlEngine::importPathList() const
1515 {
1516     Q_D(const QQmlEngine);
1517     return d->importDatabase.importPathList();
1518 }
1519
1520 /*!
1521   Sets \a paths as the list of directories where the engine searches for
1522   installed modules in a URL-based directory structure.
1523
1524   By default, the list contains the directory of the application executable,
1525   paths specified in the \c QML_IMPORT_PATH environment variable,
1526   and the builtin \c ImportsPath from QLibraryInfo.
1527
1528   \sa importPathList(), addImportPath()
1529   */
1530 void QQmlEngine::setImportPathList(const QStringList &paths)
1531 {
1532     Q_D(QQmlEngine);
1533     d->importDatabase.setImportPathList(paths);
1534 }
1535
1536
1537 /*!
1538   Adds \a path as a directory where the engine searches for
1539   native plugins for imported modules (referenced in the \c qmldir file).
1540
1541   By default, the list contains only \c .,  i.e. the engine searches
1542   in the directory of the \c qmldir file itself.
1543
1544   The newly added \a path will be first in the pluginPathList().
1545
1546   \sa setPluginPathList()
1547 */
1548 void QQmlEngine::addPluginPath(const QString& path)
1549 {
1550     Q_D(QQmlEngine);
1551     d->importDatabase.addPluginPath(path);
1552 }
1553
1554
1555 /*!
1556   Returns the list of directories where the engine searches for
1557   native plugins for imported modules (referenced in the \c qmldir file).
1558
1559   By default, the list contains only \c .,  i.e. the engine searches
1560   in the directory of the \c qmldir file itself.
1561
1562   \sa addPluginPath(), setPluginPathList()
1563 */
1564 QStringList QQmlEngine::pluginPathList() const
1565 {
1566     Q_D(const QQmlEngine);
1567     return d->importDatabase.pluginPathList();
1568 }
1569
1570 /*!
1571   Sets the list of directories where the engine searches for
1572   native plugins for imported modules (referenced in the \c qmldir file)
1573   to \a paths.
1574
1575   By default, the list contains only \c .,  i.e. the engine searches
1576   in the directory of the \c qmldir file itself.
1577
1578   \sa pluginPathList(), addPluginPath()
1579   */
1580 void QQmlEngine::setPluginPathList(const QStringList &paths)
1581 {
1582     Q_D(QQmlEngine);
1583     d->importDatabase.setPluginPathList(paths);
1584 }
1585
1586 /*!
1587   Imports the plugin named \a filePath with the \a uri provided.
1588   Returns true if the plugin was successfully imported; otherwise returns false.
1589
1590   On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1591
1592   The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1593 */
1594 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1595 {
1596     Q_D(QQmlEngine);
1597     return d->importDatabase.importPlugin(filePath, uri, errors);
1598 }
1599
1600 /*!
1601   Imports the plugin named \a filePath with the \a uri provided.
1602   Returns true if the plugin was successfully imported; otherwise returns false.
1603
1604   On failure and if non-null, *\a errorString will be set to a message describing the failure.
1605
1606   The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1607 */
1608 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1609 {
1610     Q_D(QQmlEngine);
1611     QList<QQmlError> errors;
1612     bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1613     if (!errors.isEmpty()) {
1614         QString builtError;
1615         for (int i = 0; i < errors.size(); ++i) {
1616             builtError = QString(QLatin1String("%1\n        %2"))
1617                     .arg(builtError)
1618                     .arg(errors.at(i).toString());
1619         }
1620         *errorString = builtError;
1621     }
1622     return retn;
1623 }
1624
1625 /*!
1626   \property QQmlEngine::offlineStoragePath
1627   \brief the directory for storing offline user data
1628
1629   Returns the directory where SQL and other offline
1630   storage is placed.
1631
1632   QQuickWebView and the SQL databases created with openDatabase()
1633   are stored here.
1634
1635   The default is QML/OfflineStorage in the platform-standard
1636   user application data directory.
1637
1638   Note that the path may not currently exist on the filesystem, so
1639   callers wanting to \e create new files at this location should create
1640   it first - see QDir::mkpath().
1641 */
1642 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1643 {
1644     Q_D(QQmlEngine);
1645     d->offlineStoragePath = dir;
1646 }
1647
1648 QString QQmlEngine::offlineStoragePath() const
1649 {
1650     Q_D(const QQmlEngine);
1651     return d->offlineStoragePath;
1652 }
1653
1654 static void voidptr_destructor(void *v)
1655 {
1656     void **ptr = (void **)v;
1657     delete ptr;
1658 }
1659
1660 static void *voidptr_constructor(const void *v)
1661 {
1662     if (!v) {
1663         return new void*;
1664     } else {
1665         return new void*(*(void **)v);
1666     }
1667 }
1668
1669 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1670 {
1671     Q_Q(QQmlEngine);
1672
1673     if (!mo->superClass()) {
1674         QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1675         propertyCache.insert(mo, rv);
1676         return rv;
1677     } else {
1678         QQmlPropertyCache *super = cache(mo->superClass());
1679         QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1680         propertyCache.insert(mo, rv);
1681         return rv;
1682     }
1683 }
1684
1685 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1686                                                                   QQmlError &error)
1687 {
1688     QList<QQmlType *> types;
1689
1690     int maxMinorVersion = 0;
1691
1692     const QMetaObject *metaObject = type->metaObject();
1693
1694     while (metaObject) {
1695         QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1696                                                             type->majorVersion(), minorVersion);
1697         if (t) {
1698             maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1699             types << t;
1700         } else {
1701             types << 0;
1702         }
1703
1704         metaObject = metaObject->superClass();
1705     }
1706
1707     if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1708         c->addref();
1709         typePropertyCache.insert(qMakePair(type, minorVersion), c);
1710         return c;
1711     }
1712
1713     QQmlPropertyCache *raw = cache(type->metaObject());
1714
1715     bool hasCopied = false;
1716
1717     for (int ii = 0; ii < types.count(); ++ii) {
1718         QQmlType *currentType = types.at(ii);
1719         if (!currentType)
1720             continue;
1721
1722         int rev = currentType->metaObjectRevision();
1723         int moIndex = types.count() - 1 - ii;
1724
1725         if (raw->allowedRevisionCache[moIndex] != rev) {
1726             if (!hasCopied) {
1727                 raw = raw->copy();
1728                 hasCopied = true;
1729             }
1730             raw->allowedRevisionCache[moIndex] = rev;
1731         }
1732     }
1733
1734     // Test revision compatibility - the basic rule is:
1735     //    * Anything that is excluded, cannot overload something that is not excluded *
1736
1737     // Signals override:
1738     //    * other signals and methods of the same name.
1739     //    * properties named on<Signal Name>
1740     //    * automatic <property name>Changed notify signals
1741
1742     // Methods override:
1743     //    * other methods of the same name
1744
1745     // Properties override:
1746     //    * other elements of the same name
1747
1748     bool overloadError = false;
1749     QString overloadName;
1750
1751 #if 0
1752     for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1753          !overloadError && iter != raw->stringCache.end();
1754          ++iter) {
1755
1756         QQmlPropertyData *d = *iter;
1757         if (raw->isAllowedInRevision(d))
1758             continue; // Not excluded - no problems
1759
1760         // check that a regular "name" overload isn't happening
1761         QQmlPropertyData *current = d;
1762         while (!overloadError && current) {
1763             current = d->overrideData(current);
1764             if (current && raw->isAllowedInRevision(current))
1765                 overloadError = true;
1766         }
1767     }
1768 #endif
1769
1770     if (overloadError) {
1771         if (hasCopied) raw->release();
1772
1773         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."));
1774         return 0;
1775     }
1776
1777     if (!hasCopied) raw->addref();
1778     typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1779
1780     if (minorVersion != maxMinorVersion) {
1781         raw->addref();
1782         typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1783     }
1784
1785     return raw;
1786 }
1787
1788 QQmlMetaType::ModuleApiInstance *
1789 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1790 {
1791     Locker locker(this);
1792
1793     QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1794     if (!a) {
1795         a = new QQmlMetaType::ModuleApiInstance;
1796         a->scriptCallback = module.script;
1797         a->qobjectCallback = module.qobject;
1798         a->instanceMetaObject = module.instanceMetaObject;
1799         moduleApiInstances.insert(module, a);
1800     }
1801
1802     return a;
1803 }
1804
1805 bool QQmlEnginePrivate::isQObject(int t)
1806 {
1807     Locker locker(this);
1808     return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1809 }
1810
1811 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1812 {
1813     Locker locker(this);
1814     int t = v.userType();
1815     if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1816         if (ok) *ok = true;
1817         return *(QObject **)(v.constData());
1818     } else {
1819         return QQmlMetaType::toQObject(v, ok);
1820     }
1821 }
1822
1823 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1824 {
1825     Locker locker(this);
1826     if (m_compositeTypes.contains(t))
1827         return QQmlMetaType::Object;
1828     else if (m_qmlLists.contains(t))
1829         return QQmlMetaType::List;
1830     else
1831         return QQmlMetaType::typeCategory(t);
1832 }
1833
1834 bool QQmlEnginePrivate::isList(int t) const
1835 {
1836     Locker locker(this);
1837     return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1838 }
1839
1840 int QQmlEnginePrivate::listType(int t) const
1841 {
1842     Locker locker(this);
1843     QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1844     if (iter != m_qmlLists.end())
1845         return *iter;
1846     else
1847         return QQmlMetaType::listType(t);
1848 }
1849
1850 const QMetaObject *QQmlEnginePrivate::rawMetaObjectForType(int t) const
1851 {
1852     Locker locker(this);
1853     QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1854     if (iter != m_compositeTypes.end()) {
1855         return (*iter)->root;
1856     } else {
1857         QQmlType *type = QQmlMetaType::qmlType(t);
1858         return type?type->baseMetaObject():0;
1859     }
1860 }
1861
1862 const QMetaObject *QQmlEnginePrivate::metaObjectForType(int t) const
1863 {
1864     Locker locker(this);
1865     QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1866     if (iter != m_compositeTypes.end()) {
1867         return (*iter)->root;
1868     } else {
1869         QQmlType *type = QQmlMetaType::qmlType(t);
1870         return type?type->metaObject():0;
1871     }
1872 }
1873
1874 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1875 {
1876     QByteArray name = data->root->className();
1877
1878     QByteArray ptr = name + '*';
1879     QByteArray lst = "QQmlListProperty<" + name + '>';
1880
1881     int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
1882                                            voidptr_constructor);
1883     int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
1884                                            voidptr_constructor);
1885
1886     data->addref();
1887
1888     Locker locker(this);
1889     m_qmlLists.insert(lst_type, ptr_type);
1890     m_compositeTypes.insert(ptr_type, data);
1891 }
1892
1893 bool QQml_isFileCaseCorrect(const QString &fileName)
1894 {
1895 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1896     QFileInfo info(fileName);
1897     const QString absolute = info.absoluteFilePath();
1898
1899 #if defined(Q_OS_MAC)
1900     const QString canonical = info.canonicalFilePath();
1901 #elif defined(Q_OS_WIN)
1902     wchar_t buffer[1024];
1903
1904     DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1905     if (rv == 0 || rv >= 1024) return true;
1906     rv = ::GetLongPathName(buffer, buffer, 1024);
1907     if (rv == 0 || rv >= 1024) return true;
1908
1909     const QString canonical = QString::fromWCharArray(buffer);
1910 #endif
1911
1912     const int absoluteLength = absolute.length();
1913     const int canonicalLength = canonical.length();
1914
1915     const int length = qMin(absoluteLength, canonicalLength);
1916     for (int ii = 0; ii < length; ++ii) {
1917         const QChar &a = absolute.at(absoluteLength - 1 - ii);
1918         const QChar &c = canonical.at(canonicalLength - 1 - ii);
1919
1920         if (a.toLower() != c.toLower())
1921             return true;
1922         if (a != c)
1923             return false;
1924     }
1925 #else
1926     Q_UNUSED(fileName)
1927 #endif
1928     return true;
1929 }
1930
1931 /*!
1932     \fn QQmlEngine *qmlEngine(const QObject *object)
1933     \relates QQmlEngine
1934
1935     Returns the QQmlEngine associated with \a object, if any.  This is equivalent to
1936     QQmlEngine::contextForObject(object)->engine(), but more efficient.
1937 */
1938
1939 /*!
1940     \fn QQmlContext *qmlContext(const QObject *object)
1941     \relates QQmlEngine
1942
1943     Returns the QQmlContext associated with \a object, if any.  This is equivalent to
1944     QQmlEngine::contextForObject(object).
1945 */
1946
1947 QT_END_NAMESPACE