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