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