1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtQml module of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
42 #include "qqmlengine_p.h"
43 #include "qqmlengine.h"
44 #include "qqmlcomponentattached_p.h"
46 #include "qqmlcontext_p.h"
47 #include "qqmlcompiler_p.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>
74 #include <QtCore/qstandardpaths.h>
75 #include <QtCore/qsettings.h>
77 #include <QtCore/qmetaobject.h>
78 #include <QNetworkAccessManager>
80 #include <QtCore/qcoreapplication.h>
81 #include <QtCore/qdir.h>
82 #include <QtCore/qmutex.h>
83 #include <QtCore/qthread.h>
84 #include <private/qthread_p.h>
85 #include <QtNetwork/qnetworkconfigmanager.h>
87 #include <private/qobject_p.h>
88 #include <private/qmetaobject_p.h>
90 #include <private/qqmllocale_p.h>
92 #ifdef Q_OS_WIN // for %APPDATA%
93 #include <qt_windows.h>
97 #define CSIDL_APPDATA 0x001a // <username>\Application Data
100 Q_DECLARE_METATYPE(QQmlProperty)
104 void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
106 QQmlEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
107 QQmlValueTypeFactory::registerBaseTypes(uri, versionMajor, versionMinor);
111 \qmlclass QtObject QObject
112 \ingroup qml-utility-elements
114 \brief The QtObject element is the most basic element in QML.
116 The QtObject element is a non-visual element which contains only the
119 It can be useful to create a QtObject if you need an extremely
120 lightweight element to enclose a set of custom properties:
122 \snippet doc/snippets/qml/qtobject.qml 0
124 It can also be useful for C++ integration, as it is just a plain
125 QObject. See the QObject documentation for further details.
128 \qmlproperty string QtObject::objectName
129 This property holds the QObject::objectName for this specific object instance.
131 This allows a C++ application to locate an item within a QML component
132 using the QObject::findChild() method. For example, the following C++
133 application locates the child \l Rectangle item and dynamically changes its
142 width: 200; height: 200
156 view.setSource(QUrl::fromLocalFile("MyRect.qml"));
159 QQuickItem *item = view.rootObject()->findChild<QQuickItem*>("myRect");
161 item->setProperty("color", QColor(Qt::yellow));
165 bool QQmlEnginePrivate::qml_debugging_enabled = false;
167 void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
169 qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
170 qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
171 qmlRegisterType<QQuickListElement>(uri, versionMajor, versionMinor,"ListElement");
172 qmlRegisterCustomType<QQuickListModel>(uri, versionMajor, versionMinor,"ListModel", new QQuickListModelParser);
173 qmlRegisterType<QQuickWorkerScript>(uri,versionMajor,versionMinor,"WorkerScript");
176 void QQmlEnginePrivate::defineModule()
178 registerBaseTypes("QtQuick", 2, 0);
179 qmlRegisterUncreatableType<QQmlLocale>("QtQuick",2,0,"Locale",QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
184 \class QQmlImageProviderBase
185 \brief The QQmlImageProviderBase class is used to register image providers in the QML engine.
188 Image providers must be registered with the QML engine. The only information the QML
189 engine knows about image providers is the type of image data they provide. To use an
190 image provider to acquire image data, you must cast the QQmlImageProviderBase pointer
191 to a QQuickImageProvider pointer.
193 \sa QQuickImageProvider, QQuickTextureFactory
197 \enum QQmlImageProviderBase::ImageType
199 Defines the type of image supported by this image provider.
201 \value Image The Image Provider provides QImage images.
202 The QQuickImageProvider::requestImage() method will be called for all image requests.
203 \value Pixmap The Image Provider provides QPixmap images.
204 The QQuickImageProvider::requestPixmap() method will be called for all image requests.
205 \value Texture The Image Provider provides QSGTextureProvider based images.
206 The QQuickImageProvider::requestTexture() method will be called for all image requests. \omitvalue
210 \enum QQmlImageProviderBase::Flag
212 Defines specific requirements or features of this image provider.
214 \value ForceAsynchronousImageLoading Ensures that image requests to the provider are
215 run in a separate thread, which allows the provider to spend as much time as needed
216 on producing the image without blocking the main thread.
220 QQmlImageProviderBase::QQmlImageProviderBase()
225 QQmlImageProviderBase::~QQmlImageProviderBase()
231 \qmlclass Qt QQmlEnginePrivate
232 \ingroup qml-utility-elements
233 \brief The QML global Qt object provides useful enums and functions from Qt.
235 \keyword QmlGlobalQtObject
237 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
239 The \c Qt object is a global object with utility functions, properties and enums.
241 It is not instantiable; to use it, call the members of the global \c Qt object directly.
248 color: Qt.rgba(1, 0, 0, 1)
249 text: Qt.md5("hello, world")
256 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
257 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
261 The Qt object also contains helper functions for creating objects of specific
262 data types. This is primarily useful when setting the properties of an item
263 when the property has one of the following types:
266 \li \c color - use \l{Qt::rgba()}{Qt.rgba()}, \l{Qt::hsla()}{Qt.hsla()}, \l{Qt::darker()}{Qt.darker()}, \l{Qt::lighter()}{Qt.lighter()} or \l{Qt::tint()}{Qt.tint()}
267 \li \c rect - use \l{Qt::rect()}{Qt.rect()}
268 \li \c point - use \l{Qt::point()}{Qt.point()}
269 \li \c size - use \l{Qt::size()}{Qt.size()}
270 \li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
273 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
275 \section1 Date/Time Formatters
277 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
280 \li \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
281 \li \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
282 \li \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
285 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
288 \section1 Dynamic Object Creation
289 The following functions on the global object allow you to dynamically create QML
290 items from files or strings. See \l{Dynamic Object Management in QML} for an overview
294 \li \l{Qt::createComponent()}{object Qt.createComponent(url)}
295 \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
299 \section1 Other Functions
301 The following functions are also on the Qt object.
304 \li \l{Qt::quit()}{Qt.quit()}
305 \li \l{Qt::md5()}{Qt.md5(string)}
306 \li \l{Qt::btoa()}{string Qt.btoa(string)}
307 \li \l{Qt::atob()}{string Qt.atob(string)}
308 \li \l{Qt::binding()}{object Qt.binding(function)}
309 \li \l{Qt::locale()}{object Qt.locale()}
310 \li \l{Qt::resolvedUrl()}{string Qt.resolvedUrl(string)}
311 \li \l{Qt::openUrlExternally()}{Qt.openUrlExternally(string)}
312 \li \l{Qt::fontFamilies()}{list<string> Qt.fontFamilies()}
317 \qmlproperty object Qt::application
320 The \c application object provides access to global application state
321 properties shared by many QML components.
327 \li \c application.active
329 This read-only property indicates whether the application is the top-most and focused
330 application, and the user is able to interact with the application. The property
331 is false when the application is in the background, the device keylock or screen
332 saver is active, the screen backlight is turned off, or the global system dialog
333 is being displayed on top of the application. It can be used for stopping and
334 pausing animations, timers and active processing of data in order to save device
335 battery power and free device memory and processor load when the application is not
339 \li \c application.layoutDirection
341 This read-only property can be used to query the default layout direction of the
342 application. On system start-up, the default layout direction depends on the
343 application's language. The property has a value of \c Qt.RightToLeft in locales
344 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
345 where the reading direction flows from left to right. You can bind to this
346 property to customize your application layouts to support both layout directions.
351 \li Qt.LeftToRight - Text and graphics elements should be positioned
353 \li Qt.RightToLeft - Text and graphics elements should be positioned
359 The following example uses the \c application object to indicate
360 whether the application is currently active:
362 \snippet doc/snippets/qml/application.qml document
366 \qmlproperty object Qt::inputMethod
369 The \c inputMethod object allows access to application's QInputMethod object
370 and all its properties and slots. See the QInputMethod documentation for
376 \qmlmethod object Qt::include(string url, jsobject callback)
378 Includes another JavaScript file. This method can only be used from within JavaScript files,
379 and not regular QML files.
381 This imports all functions from \a url into the current script's namespace.
383 Qt.include() returns an object that describes the status of the operation. The object has
384 a single property, \c {status}, that is set to one of the following values:
387 \header \li Symbol \li Value \li Description
388 \row \li result.OK \li 0 \li The include completed successfully.
389 \row \li result.LOADING \li 1 \li Data is being loaded from the network.
390 \row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
391 \row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
392 An additional \c exception property will be set in this case.
395 The \c status property will be updated as the operation progresses.
397 If provided, \a callback is invoked when the operation completes. The callback is passed
398 the same object as is returned from the Qt.include() call.
400 // Qt.include() is implemented in qv8include.cpp
403 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
404 : propertyCapture(0), rootContext(0), isDebugging(false),
405 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
406 cleanup(0), erroredBindings(0), inProgressCreations(0),
407 workerScriptEngine(0), activeVME(0),
408 networkAccessManager(0), networkAccessManagerFactory(0),
409 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
410 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
414 QQmlEnginePrivate::~QQmlEnginePrivate()
416 if (inProgressCreations)
417 qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
420 QQmlCleanup *c = cleanup;
422 if (cleanup) cleanup->prev = &cleanup;
428 doDeleteInEngineThread();
430 if (incubationController) incubationController->d = 0;
431 incubationController = 0;
436 for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
438 for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
440 for(QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
441 delete (*iter)->qobjectApi;
446 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
448 QObjectPrivate *p = QObjectPrivate::get(o);
449 if (p->declarativeData) {
450 QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
451 if (d->ownContext && d->context) {
452 d->context->destroy();
456 // Mark this object as in the process of deletion to
457 // prevent it resolving in bindings
458 QQmlData::markAsDeleted(o);
462 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
464 static_cast<QQmlData *>(d)->destroyed(o);
467 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
469 static_cast<QQmlData *>(d)->parentChanged(o, p);
472 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **a)
474 QQmlData *ddata = QQmlData::get(object, false);
475 if (!ddata) return; // Probably being deleted
477 // In general, QML only supports QObject's that live on the same thread as the QQmlEngine
478 // that they're exposed to. However, to make writing "worker objects" that calculate data
479 // in a separate thread easier, QML allows a QObject that lives in the same thread as the
480 // QQmlEngine to emit signals from a different thread. These signals are then automatically
481 // marshalled back onto the QObject's thread and handled by QML from there. This is tested
482 // by the qqmlecmascript::threadSignal() autotest.
483 if (ddata->notifyList &&
484 QThread::currentThreadId() != QObjectPrivate::get(object)->threadData->threadId) {
486 QMetaMethod m = object->metaObject()->method(index);
487 QList<QByteArray> parameterTypes = m.parameterTypes();
489 int *types = (int *)malloc((parameterTypes.count() + 1) * sizeof(int));
490 void **args = (void **) malloc((parameterTypes.count() + 1) *sizeof(void *));
492 types[0] = 0; // return type
493 args[0] = 0; // return value
495 for (int ii = 0; ii < parameterTypes.count(); ++ii) {
496 const QByteArray &typeName = parameterTypes.at(ii);
497 if (typeName.endsWith('*'))
498 types[ii + 1] = QMetaType::VoidStar;
500 types[ii + 1] = QMetaType::type(typeName);
502 if (!types[ii + 1]) {
503 qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
504 "(Make sure '%s' is registered using qRegisterMetaType().)",
505 typeName.constData(), typeName.constData());
511 args[ii + 1] = QMetaType::create(types[ii + 1], a[ii + 1]);
514 QMetaCallEvent *ev = new QMetaCallEvent(index, 0, 0, object, index,
515 parameterTypes.count() + 1, types, args);
516 QCoreApplication::postEvent(object, ev);
519 QQmlNotifierEndpoint *ep = ddata->notify(index);
520 if (ep) QQmlNotifier::emitNotify(ep, a);
524 int QQmlData::receivers(QAbstractDeclarativeData *d, const QObject *, int index)
526 return static_cast<QQmlData *>(d)->endpointCount(index);
529 int QQmlData::endpointCount(int index)
532 QQmlNotifierEndpoint *ep = notify(index);
543 void QQmlData::markAsDeleted(QObject *o)
545 QQmlData::setQueuedForDeletion(o);
547 QObjectPrivate *p = QObjectPrivate::get(o);
548 for (QList<QObject *>::iterator it = p->children.begin(), end = p->children.end(); it != end; ++it) {
549 QQmlData::markAsDeleted(*it);
553 void QQmlData::setQueuedForDeletion(QObject *object)
556 if (QObjectPrivate *priv = QObjectPrivate::get(object)) {
557 if (!priv->wasDeleted && priv->declarativeData) {
558 QQmlData *ddata = QQmlData::get(object, false);
559 if (ddata->ownContext && ddata->context)
560 ddata->context->emitDestruction();
561 ddata->isQueuedForDeletion = true;
567 void QQmlEnginePrivate::init()
571 static bool firstTime = true;
573 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component");
579 qRegisterMetaType<QVariant>("QVariant");
580 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
581 qRegisterMetaType<QJSValue>("QJSValue");
582 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
583 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
584 qRegisterMetaType<QList<int> >("QList<int>");
585 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
587 v8engine()->setEngine(q);
589 rootContext = new QQmlContext(q,true);
591 if (QCoreApplication::instance()->thread() == q->thread() &&
592 QQmlEngineDebugService::isDebuggingEnabled()) {
594 QQmlEngineDebugService::instance()->addEngine(q);
595 QV8DebugService::initialize(v8engine());
596 QV8ProfilerService::initialize();
597 QQmlProfilerService::initialize();
598 QDebugMessageService::instance();
601 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
602 if (!dataLocation.isEmpty())
603 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator())
604 + QDir::separator() + QLatin1String("QML")
605 + QDir::separator() + QLatin1String("OfflineStorage");
608 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
611 if (!workerScriptEngine)
612 workerScriptEngine = new QQuickWorkerScriptEngine(q);
613 return workerScriptEngine;
620 \brief The QQmlEngine class provides an environment for instantiating QML components.
623 Each QML component is instantiated in a QQmlContext.
624 QQmlContext's are essential for passing data to QML
625 components. In QML, contexts are arranged hierarchically and this
626 hierarchy is managed by the QQmlEngine.
628 Prior to creating any QML components, an application must have
629 created a QQmlEngine to gain access to a QML context. The
630 following example shows how to create a simple Text item.
634 QQmlComponent component(&engine);
635 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
636 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
638 //add item to view, etc
642 In this case, the Text item will be created in the engine's
643 \l {QQmlEngine::rootContext()}{root context}.
645 Note that the QtQuick 1 version is called QDeclarativeEngine.
647 \sa QQmlComponent, QQmlContext
651 Create a new QQmlEngine with the given \a parent.
653 QQmlEngine::QQmlEngine(QObject *parent)
654 : QJSEngine(*new QQmlEnginePrivate(this), parent)
661 Destroys the QQmlEngine.
663 Any QQmlContext's created on this engine will be
664 invalidated, but not destroyed (unless they are parented to the
667 QQmlEngine::~QQmlEngine()
670 if (d->isDebugging) {
671 QQmlEngineDebugService::instance()->remEngine(this);
674 // Emit onDestruction signals for the root context before
675 // we destroy the contexts, engine, Module APIs etc. that
676 // may be required to handle the destruction signal.
677 QQmlContextData::get(rootContext())->emitDestruction();
679 // if we are the parent of any of the qobject module api instances,
680 // we need to remove them from our internal list, in order to prevent
681 // a segfault in engine private dtor.
682 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
683 QObject *currQObjectApi = 0;
684 QQmlMetaType::ModuleApiInstance *currInstance = 0;
685 foreach (const QQmlMetaType::ModuleApi &key, keys) {
686 currInstance = d->moduleApiInstances.value(key);
687 currQObjectApi = currInstance->qobjectApi;
688 if (this->children().contains(currQObjectApi)) {
689 delete currQObjectApi;
691 d->moduleApiInstances.remove(key);
695 if (d->incubationController)
696 d->incubationController->d = 0;
699 /*! \fn void QQmlEngine::quit()
700 This signal is emitted when the QML loaded by the engine would like to quit.
703 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
704 This signal is emitted when \a warnings messages are generated by QML.
708 Clears the engine's internal component cache.
710 This function causes the property metadata of all components previously
711 loaded by the engine to be destroyed. All previously loaded components and
712 the property bindings for all extant objects created from those components will
715 This function returns the engine to a state where it does not contain any loaded
716 component data. This may be useful in order to reload a smaller subset of the
717 previous component set, or to load a new version of a previously loaded component.
719 Once the component cache has been cleared, components must be loaded before
720 any new objects can be created.
722 \sa trimComponentCache()
724 void QQmlEngine::clearComponentCache()
731 Trims the engine's internal component cache.
733 This function causes the property metadata of any loaded components which are
734 not currently in use to be destroyed.
736 A component is considered to be in use if there are any extant instances of
737 the component itself, any instances of other components that use the component,
738 or any objects instantiated by any of those components.
740 \sa clearComponentCache()
742 void QQmlEngine::trimComponentCache()
749 Returns the engine's root context.
751 The root context is automatically created by the QQmlEngine.
752 Data that should be available to all QML component instances
753 instantiated by the engine should be put in the root context.
755 Additional data that should only be available to a subset of
756 component instances should be added to sub-contexts parented to the
759 QQmlContext *QQmlEngine::rootContext() const
761 Q_D(const QQmlEngine);
762 return d->rootContext;
766 Sets the \a factory to use for creating QNetworkAccessManager(s).
768 QNetworkAccessManager is used for all network access by QML. By
769 implementing a factory it is possible to create custom
770 QNetworkAccessManager with specialized caching, proxy and cookie
773 The factory must be set before executing the engine.
775 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
778 QMutexLocker locker(&d->mutex);
779 d->networkAccessManagerFactory = factory;
783 Returns the current QQmlNetworkAccessManagerFactory.
785 \sa setNetworkAccessManagerFactory()
787 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
789 Q_D(const QQmlEngine);
790 return d->networkAccessManagerFactory;
793 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
796 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
798 void *args[] = { 0 };
799 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
803 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
805 QMutexLocker locker(&mutex);
806 QNetworkAccessManager *nam;
807 if (networkAccessManagerFactory) {
808 nam = networkAccessManagerFactory->create(parent);
810 nam = new QNetworkAccessManager(parent);
816 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
818 Q_Q(const QQmlEngine);
819 if (!networkAccessManager)
820 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
821 return networkAccessManager;
825 Returns a common QNetworkAccessManager which can be used by any QML
826 element instantiated by this engine.
828 If a QQmlNetworkAccessManagerFactory has been set and a
829 QNetworkAccessManager has not yet been created, the
830 QQmlNetworkAccessManagerFactory will be used to create the
831 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
832 will have no proxy or cache set.
834 \sa setNetworkAccessManagerFactory()
836 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
838 Q_D(const QQmlEngine);
839 return d->getNetworkAccessManager();
844 Sets the \a provider to use for images requested via the \e
845 image: url scheme, with host \a providerId. The QQmlEngine
846 takes ownership of \a provider.
848 Image providers enable support for pixmap and threaded image
849 requests. See the QQuickImageProvider documentation for details on
850 implementing and using image providers.
852 All required image providers should be added to the engine before any
853 QML sources files are loaded.
855 \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
857 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
860 QMutexLocker locker(&d->mutex);
861 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
865 Returns the image provider set for \a providerId.
867 Returns the provider if it was found; otherwise returns 0.
869 \sa QQuickImageProvider
871 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
873 Q_D(const QQmlEngine);
874 QMutexLocker locker(&d->mutex);
875 return d->imageProviders.value(providerId).data();
879 Removes the image provider for \a providerId.
881 \sa addImageProvider(), QQuickImageProvider
883 void QQmlEngine::removeImageProvider(const QString &providerId)
886 QMutexLocker locker(&d->mutex);
887 d->imageProviders.take(providerId);
891 Return the base URL for this engine. The base URL is only used to
892 resolve components when a relative URL is passed to the
893 QQmlComponent constructor.
895 If a base URL has not been explicitly set, this method returns the
896 application's current working directory.
900 QUrl QQmlEngine::baseUrl() const
902 Q_D(const QQmlEngine);
903 if (d->baseUrl.isEmpty()) {
904 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
911 Set the base URL for this engine to \a url.
915 void QQmlEngine::setBaseUrl(const QUrl &url)
922 Returns true if warning messages will be output to stderr in addition
923 to being emitted by the warnings() signal, otherwise false.
925 The default value is true.
927 bool QQmlEngine::outputWarningsToStandardError() const
929 Q_D(const QQmlEngine);
930 return d->outputWarningsToStdErr;
934 Set whether warning messages will be output to stderr to \a enabled.
936 If \a enabled is true, any warning messages generated by QML will be
937 output to stderr and emitted by the warnings() signal. If \a enabled
938 is false, on the warnings() signal will be emitted. This allows
939 applications to handle warning output themselves.
941 The default value is true.
943 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
946 d->outputWarningsToStdErr = enabled;
950 Attempt to free unused memory.
952 void QQmlEngine::collectGarbage()
958 Returns the QQmlContext for the \a object, or 0 if no
959 context has been set.
961 When the QQmlEngine instantiates a QObject, the context is
964 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
969 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
972 static_cast<QQmlData *>(priv->declarativeData);
976 else if (data->outerContext)
977 return data->outerContext->asQQmlContext();
983 Sets the QQmlContext for the \a object to \a context.
984 If the \a object already has a context, a warning is
985 output, but the context is not changed.
987 When the QQmlEngine instantiates a QObject, the context is
990 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
992 if (!object || !context)
995 QQmlData *data = QQmlData::get(object, true);
997 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
1001 QQmlContextData *contextData = QQmlContextData::get(context);
1002 contextData->addObject(object);
1006 \enum QQmlEngine::ObjectOwnership
1008 Ownership controls whether or not QML automatically destroys the
1009 QObject when the object is garbage collected by the JavaScript
1010 engine. The two ownership options are:
1012 \value CppOwnership The object is owned by C++ code, and will
1013 never be deleted by QML. The JavaScript destroy() method cannot be
1014 used on objects with CppOwnership. This option is similar to
1015 QScriptEngine::QtOwnership.
1017 \value JavaScriptOwnership The object is owned by JavaScript.
1018 When the object is returned to QML as the return value of a method
1019 call or property access, QML will track it, and delete the object
1020 if there are no remaining JavaScript references to it and it has no
1021 QObject::parent(). An object tracked by one QQmlEngine
1022 will be deleted during that QQmlEngine's destructor, and thus
1023 JavaScript references between objects with JavaScriptOwnership from
1024 two different engines will not be valid after the deletion of one of
1025 those engines. This option is similar to QScriptEngine::ScriptOwnership.
1027 Generally an application doesn't need to set an object's ownership
1028 explicitly. QML uses a heuristic to set the default object
1029 ownership. By default, an object that is created by QML has
1030 JavaScriptOwnership. The exception to this are the root objects
1031 created by calling QQmlComponent::create() or
1032 QQmlComponent::beginCreate() which have CppOwnership by
1033 default. The ownership of these root-level objects is considered to
1034 have been transferred to the C++ caller.
1036 Objects not-created by QML have CppOwnership by default. The
1037 exception to this is objects returned from a C++ method call. The
1038 ownership of these objects is passed to JavaScript.
1040 Calling setObjectOwnership() overrides the default ownership
1041 heuristic used by QML.
1045 Sets the \a ownership of \a object.
1047 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
1052 QQmlData *ddata = QQmlData::get(object, true);
1056 ddata->indestructible = (ownership == CppOwnership)?true:false;
1057 ddata->explicitIndestructibleSet = true;
1061 Returns the ownership of \a object.
1063 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
1066 return CppOwnership;
1068 QQmlData *ddata = QQmlData::get(object, false);
1070 return CppOwnership;
1072 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
1075 bool QQmlEngine::event(QEvent *e)
1078 if (e->type() == QEvent::User)
1079 d->doDeleteInEngineThread();
1081 return QJSEngine::event(e);
1084 void QQmlEnginePrivate::doDeleteInEngineThread()
1086 QFieldList<Deletable, &Deletable::next> list;
1088 list.copyAndClear(toDeleteInEngineThread);
1091 while (Deletable *d = list.takeFirst())
1095 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
1097 QQmlData *data = QQmlData::get(object);
1099 if (data && data->compiledData && data->deferredIdx) {
1100 QQmlObjectCreatingProfiler prof;
1102 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
1103 prof.setTypeName(type ? type->qmlTypeName()
1104 : QString::fromUtf8(object->metaObject()->className()));
1105 if (data->outerContext)
1106 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
1108 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
1110 QQmlComponentPrivate::ConstructionState state;
1111 QQmlComponentPrivate::beginDeferred(ep, object, &state);
1113 // Release the reference for the deferral action (we still have one from construction)
1114 data->compiledData->release();
1115 data->compiledData = 0;
1117 QQmlComponentPrivate::complete(ep, &state);
1121 QQmlContext *qmlContext(const QObject *obj)
1123 return QQmlEngine::contextForObject(obj);
1126 QQmlEngine *qmlEngine(const QObject *obj)
1128 QQmlData *data = QQmlData::get(obj, false);
1129 if (!data || !data->context)
1131 return data->context->engine;
1134 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1136 QQmlData *data = QQmlData::get(object);
1138 return 0; // Attached properties are only on objects created by QML
1140 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1144 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1148 rv = pf(const_cast<QObject *>(object));
1151 data->attachedProperties()->insert(id, rv);
1156 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1157 const QMetaObject *attachedMetaObject, bool create)
1160 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1162 if (*idCache == -1 || !object)
1165 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1168 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1170 #ifndef QQML_NO_DEBUG_PROTOCOL
1171 if (!QQmlEnginePrivate::qml_debugging_enabled
1173 qDebug("QML debugging is enabled. Only use this in a safe environment.");
1175 QQmlEnginePrivate::qml_debugging_enabled = true;
1180 class QQmlDataExtended {
1183 ~QQmlDataExtended();
1185 QHash<int, QObject *> attachedProperties;
1188 QQmlDataExtended::QQmlDataExtended()
1192 QQmlDataExtended::~QQmlDataExtended()
1196 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1199 layout(endpoint->next);
1201 int index = endpoint->sourceSignal;
1202 index = qMin(index, 0xFFFF - 1);
1204 endpoint->next = notifies[index];
1205 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1206 endpoint->prev = ¬ifies[index];
1207 notifies[index] = endpoint;
1210 void QQmlData::NotifyList::layout()
1212 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1215 QQmlNotifierEndpoint **old = notifies;
1216 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1217 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1218 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1219 sizeof(QQmlNotifierEndpoint*);
1220 memset(notifies + notifiesSize, 0, memsetSize);
1222 if (notifies != old) {
1223 for (int ii = 0; ii < notifiesSize; ++ii)
1225 notifies[ii]->prev = ¬ifies[ii];
1228 notifiesSize = maximumTodoIndex + 1;
1233 maximumTodoIndex = 0;
1237 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1240 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1241 notifyList->connectionMask = 0;
1242 notifyList->maximumTodoIndex = 0;
1243 notifyList->notifiesSize = 0;
1244 notifyList->todo = 0;
1245 notifyList->notifies = 0;
1248 Q_ASSERT(!endpoint->isConnected());
1250 index = qMin(index, 0xFFFF - 1);
1251 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1253 if (index < notifyList->notifiesSize) {
1255 endpoint->next = notifyList->notifies[index];
1256 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1257 endpoint->prev = ¬ifyList->notifies[index];
1258 notifyList->notifies[index] = endpoint;
1261 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1263 endpoint->next = notifyList->todo;
1264 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1265 endpoint->prev = ¬ifyList->todo;
1266 notifyList->todo = endpoint;
1270 bool QQml_isSignalConnected(QObject *obj, int signal_index, int index)
1272 QQmlData *data = QQmlData::get(obj);
1273 return QObjectPrivate::get(obj)->isSignalConnected(signal_index) || (data && data->signalHasEndpoint(index));
1277 index MUST be the index returned by QMetaMethod::index()
1278 This is different than the index returned by QObjectPrivate::signalIndex()
1280 bool QQmlData::signalHasEndpoint(int index)
1282 return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
1285 QHash<int, QObject *> *QQmlData::attachedProperties() const
1287 if (!extendedData) extendedData = new QQmlDataExtended;
1288 return &extendedData->attachedProperties;
1291 void QQmlData::destroyed(QObject *object)
1293 if (nextContextObject)
1294 nextContextObject->prevContextObject = prevContextObject;
1295 if (prevContextObject)
1296 *prevContextObject = nextContextObject;
1298 QQmlAbstractBinding *binding = bindings;
1300 QQmlAbstractBinding *next = binding->m_nextBinding;
1301 binding->m_prevBinding = 0;
1302 binding->m_nextBinding = 0;
1308 compiledData->release();
1312 QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1313 while (signalHandler) {
1314 if (signalHandler->isEvaluating()) {
1315 // The object is being deleted during signal handler evaluation.
1316 // This will cause a crash due to invalid memory access when the
1317 // evaluation has completed.
1318 // Abort with a friendly message instead.
1319 QString locationString;
1320 QQmlBoundSignalExpression *expr = signalHandler->expression();
1322 QString fileName = expr->sourceFile();
1323 if (fileName.isEmpty())
1324 fileName = QStringLiteral("<Unknown File>");
1325 locationString.append(fileName);
1326 locationString.append(QString::fromLatin1(":%0: ").arg(expr->lineNumber()));
1327 QString source = expr->expression();
1328 if (source.size() > 100) {
1329 source.truncate(96);
1330 source.append(QStringLiteral(" ..."));
1332 locationString.append(source);
1334 locationString = QStringLiteral("<Unknown Location>");
1336 qFatal("Object %p destroyed while one of its QML signal handlers is in progress.\n"
1337 "Most likely the object was deleted synchronously (use QObject::deleteLater() "
1338 "instead), or the application is running a nested event loop.\n"
1339 "This behavior is NOT supported!\n"
1340 "%s", object, qPrintable(locationString));
1343 QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1344 signalHandler->m_prevSignal = 0;
1345 signalHandler->m_nextSignal = 0;
1346 delete signalHandler;
1347 signalHandler = next;
1354 propertyCache->release();
1356 if (ownContext && context)
1360 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1361 *guard = (QObject *)0;
1362 guard->objectDestroyed(object);
1366 while (notifyList->todo)
1367 notifyList->todo->disconnect();
1368 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1369 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1372 free(notifyList->notifies);
1378 delete extendedData;
1380 // Dispose the handle.
1381 // We don't simply clear it (and wait for next gc cycle to dispose
1382 // via the weak qobject reference callback) as this affects the
1383 // outcomes of v8's gc statistical analysis heuristics, which can
1384 // cause unnecessary growth of the old pointer space js heap area.
1385 qPersistentDispose(v8object);
1391 void QQmlData::parentChanged(QObject *object, QObject *parent)
1397 bool QQmlData::hasBindingBit(int bit) const
1399 if (bindingBitsSize > bit)
1400 return bindingBits[bit / 32] & (1 << (bit % 32));
1405 void QQmlData::clearBindingBit(int bit)
1407 if (bindingBitsSize > bit)
1408 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1411 void QQmlData::setBindingBit(QObject *obj, int bit)
1413 if (bindingBitsSize <= bit) {
1414 int props = obj->metaObject()->propertyCount();
1415 Q_ASSERT(bit < props);
1417 int arraySize = (props + 31) / 32;
1418 int oldArraySize = bindingBitsSize / 32;
1420 bindingBits = (quint32 *)realloc(bindingBits,
1421 arraySize * sizeof(quint32));
1423 memset(bindingBits + oldArraySize,
1425 sizeof(quint32) * (arraySize - oldArraySize));
1427 bindingBitsSize = arraySize * 32;
1430 bindingBits[bit / 32] |= (1 << (bit % 32));
1433 void QQmlEnginePrivate::sendQuit()
1437 if (q->receivers(SIGNAL(quit())) == 0) {
1438 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1442 static void dumpwarning(const QQmlError &error)
1444 QMessageLogger(error.url().toString().toLatin1().constData(),
1445 error.line(), 0).warning().nospace()
1446 << qPrintable(error.toString());
1449 static void dumpwarning(const QList<QQmlError> &errors)
1451 for (int ii = 0; ii < errors.count(); ++ii)
1452 dumpwarning(errors.at(ii));
1455 void QQmlEnginePrivate::warning(const QQmlError &error)
1458 q->warnings(QList<QQmlError>() << error);
1459 if (outputWarningsToStdErr)
1463 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1466 q->warnings(errors);
1467 if (outputWarningsToStdErr)
1468 dumpwarning(errors);
1471 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1474 QQmlEnginePrivate::get(engine)->warning(error);
1479 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1482 QQmlEnginePrivate::get(engine)->warning(error);
1487 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1490 engine->warning(error);
1495 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1498 engine->warning(error);
1504 This function should be called prior to evaluation of any js expression,
1505 so that scarce resources are not freed prematurely (eg, if there is a
1506 nested javascript expression).
1508 void QQmlEnginePrivate::referenceScarceResources()
1510 scarceResourcesRefCount += 1;
1514 This function should be called after evaluation of the js expression is
1515 complete, and so the scarce resources may be freed safely.
1517 void QQmlEnginePrivate::dereferenceScarceResources()
1519 Q_ASSERT(scarceResourcesRefCount > 0);
1520 scarceResourcesRefCount -= 1;
1522 // if the refcount is zero, then evaluation of the "top level"
1523 // expression must have completed. We can safely release the
1524 // scarce resources.
1525 if (scarceResourcesRefCount == 0) {
1526 // iterate through the list and release them all.
1527 // note that the actual SRD is owned by the JS engine,
1528 // so we cannot delete the SRD; but we can free the
1529 // memory used by the variant in the SRD.
1530 while (ScarceResourceData *sr = scarceResources.first()) {
1531 sr->data = QVariant();
1532 scarceResources.remove(sr);
1538 Adds \a path as a directory where the engine searches for
1539 installed modules in a URL-based directory structure.
1540 The \a path may be a local filesystem directory or a URL.
1542 The newly added \a path will be first in the importPathList().
1544 \sa setImportPathList(), {QML Modules}
1546 void QQmlEngine::addImportPath(const QString& path)
1549 d->importDatabase.addImportPath(path);
1553 Returns the list of directories where the engine searches for
1554 installed modules in a URL-based directory structure.
1556 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1557 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1558 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1559 provided by that module. A \c qmldir file is required for defining the
1560 type version mapping and possibly QML extensions plugins.
1562 By default, the list contains the directory of the application executable,
1563 paths specified in the \c QML_IMPORT_PATH environment variable,
1564 and the builtin \c ImportsPath from QLibraryInfo.
1566 \sa addImportPath(), setImportPathList()
1568 QStringList QQmlEngine::importPathList() const
1570 Q_D(const QQmlEngine);
1571 return d->importDatabase.importPathList();
1575 Sets \a paths as the list of directories where the engine searches for
1576 installed modules in a URL-based directory structure.
1578 By default, the list contains the directory of the application executable,
1579 paths specified in the \c QML_IMPORT_PATH environment variable,
1580 and the builtin \c ImportsPath from QLibraryInfo.
1582 \sa importPathList(), addImportPath()
1584 void QQmlEngine::setImportPathList(const QStringList &paths)
1587 d->importDatabase.setImportPathList(paths);
1592 Adds \a path as a directory where the engine searches for
1593 native plugins for imported modules (referenced in the \c qmldir file).
1595 By default, the list contains only \c ., i.e. the engine searches
1596 in the directory of the \c qmldir file itself.
1598 The newly added \a path will be first in the pluginPathList().
1600 \sa setPluginPathList()
1602 void QQmlEngine::addPluginPath(const QString& path)
1605 d->importDatabase.addPluginPath(path);
1610 Returns the list of directories where the engine searches for
1611 native plugins for imported modules (referenced in the \c qmldir file).
1613 By default, the list contains only \c ., i.e. the engine searches
1614 in the directory of the \c qmldir file itself.
1616 \sa addPluginPath(), setPluginPathList()
1618 QStringList QQmlEngine::pluginPathList() const
1620 Q_D(const QQmlEngine);
1621 return d->importDatabase.pluginPathList();
1625 Sets the list of directories where the engine searches for
1626 native plugins for imported modules (referenced in the \c qmldir file)
1629 By default, the list contains only \c ., i.e. the engine searches
1630 in the directory of the \c qmldir file itself.
1632 \sa pluginPathList(), addPluginPath()
1634 void QQmlEngine::setPluginPathList(const QStringList &paths)
1637 d->importDatabase.setPluginPathList(paths);
1641 Imports the plugin named \a filePath with the \a uri provided.
1642 Returns true if the plugin was successfully imported; otherwise returns false.
1644 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1646 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1648 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1651 return d->importDatabase.importPlugin(filePath, uri, errors);
1655 Imports the plugin named \a filePath with the \a uri provided.
1656 Returns true if the plugin was successfully imported; otherwise returns false.
1658 On failure and if non-null, *\a errorString will be set to a message describing the failure.
1660 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1662 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1665 QList<QQmlError> errors;
1666 bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1667 if (!errors.isEmpty()) {
1669 for (int i = 0; i < errors.size(); ++i) {
1670 builtError = QString(QLatin1String("%1\n %2"))
1672 .arg(errors.at(i).toString());
1674 *errorString = builtError;
1680 \property QQmlEngine::offlineStoragePath
1681 \brief the directory for storing offline user data
1683 Returns the directory where SQL and other offline
1686 QQuickWebView and the SQL databases created with openDatabase()
1689 The default is QML/OfflineStorage in the platform-standard
1690 user application data directory.
1692 Note that the path may not currently exist on the filesystem, so
1693 callers wanting to \e create new files at this location should create
1694 it first - see QDir::mkpath().
1696 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1699 d->offlineStoragePath = dir;
1702 QString QQmlEngine::offlineStoragePath() const
1704 Q_D(const QQmlEngine);
1705 return d->offlineStoragePath;
1708 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1712 if (!mo->superClass()) {
1713 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1714 propertyCache.insert(mo, rv);
1717 QQmlPropertyCache *super = cache(mo->superClass());
1718 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1719 propertyCache.insert(mo, rv);
1724 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1727 QList<QQmlType *> types;
1729 int maxMinorVersion = 0;
1731 const QMetaObject *metaObject = type->metaObject();
1733 while (metaObject) {
1734 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1735 type->majorVersion(), minorVersion);
1737 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1743 metaObject = metaObject->superClass();
1746 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1748 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1752 QQmlPropertyCache *raw = cache(type->metaObject());
1754 bool hasCopied = false;
1756 for (int ii = 0; ii < types.count(); ++ii) {
1757 QQmlType *currentType = types.at(ii);
1761 int rev = currentType->metaObjectRevision();
1762 int moIndex = types.count() - 1 - ii;
1764 if (raw->allowedRevisionCache[moIndex] != rev) {
1769 raw->allowedRevisionCache[moIndex] = rev;
1773 // Test revision compatibility - the basic rule is:
1774 // * Anything that is excluded, cannot overload something that is not excluded *
1776 // Signals override:
1777 // * other signals and methods of the same name.
1778 // * properties named on<Signal Name>
1779 // * automatic <property name>Changed notify signals
1781 // Methods override:
1782 // * other methods of the same name
1784 // Properties override:
1785 // * other elements of the same name
1787 bool overloadError = false;
1788 QString overloadName;
1791 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1792 !overloadError && iter != raw->stringCache.end();
1795 QQmlPropertyData *d = *iter;
1796 if (raw->isAllowedInRevision(d))
1797 continue; // Not excluded - no problems
1799 // check that a regular "name" overload isn't happening
1800 QQmlPropertyData *current = d;
1801 while (!overloadError && current) {
1802 current = d->overrideData(current);
1803 if (current && raw->isAllowedInRevision(current))
1804 overloadError = true;
1809 if (overloadError) {
1810 if (hasCopied) raw->release();
1812 error.setDescription(QLatin1String("Type ") + type->qmlTypeName() + QLatin1Char(' ') + QString::number(type->majorVersion()) + QLatin1Char('.') + QString::number(minorVersion) + QLatin1String(" contains an illegal property \"") + overloadName + QLatin1String("\". This is an error in the type's implementation."));
1816 if (!hasCopied) raw->addref();
1817 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1819 if (minorVersion != maxMinorVersion) {
1821 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1827 QQmlMetaType::ModuleApiInstance *
1828 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1830 Locker locker(this);
1832 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1834 a = new QQmlMetaType::ModuleApiInstance;
1835 a->scriptCallback = module.script;
1836 a->qobjectCallback = module.qobject;
1837 a->instanceMetaObject = module.instanceMetaObject;
1838 moduleApiInstances.insert(module, a);
1844 bool QQmlEnginePrivate::isQObject(int t)
1846 Locker locker(this);
1847 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1850 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1852 Locker locker(this);
1853 int t = v.userType();
1854 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1856 return *(QObject **)(v.constData());
1858 return QQmlMetaType::toQObject(v, ok);
1862 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1864 Locker locker(this);
1865 if (m_compositeTypes.contains(t))
1866 return QQmlMetaType::Object;
1867 else if (m_qmlLists.contains(t))
1868 return QQmlMetaType::List;
1870 return QQmlMetaType::typeCategory(t);
1873 bool QQmlEnginePrivate::isList(int t) const
1875 Locker locker(this);
1876 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1879 int QQmlEnginePrivate::listType(int t) const
1881 Locker locker(this);
1882 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1883 if (iter != m_qmlLists.end())
1886 return QQmlMetaType::listType(t);
1889 const QMetaObject *QQmlEnginePrivate::rawMetaObjectForType(int t) const
1891 Locker locker(this);
1892 QHash<int, const QMetaObject *>::ConstIterator iter = m_compositeTypes.find(t);
1893 if (iter != m_compositeTypes.end()) {
1896 QQmlType *type = QQmlMetaType::qmlType(t);
1897 return type?type->baseMetaObject():0;
1901 const QMetaObject *QQmlEnginePrivate::metaObjectForType(int t) const
1903 Locker locker(this);
1904 QHash<int, const QMetaObject *>::ConstIterator iter = m_compositeTypes.find(t);
1905 if (iter != m_compositeTypes.end()) {
1908 QQmlType *type = QQmlMetaType::qmlType(t);
1909 return type?type->metaObject():0;
1913 void QQmlEnginePrivate::registerCompositeType(const QMetaObject *mo)
1915 QByteArray name = mo->className();
1917 QByteArray ptr = name + '*';
1918 QByteArray lst = "QQmlListProperty<" + name + '>';
1920 int ptr_type = QMetaType::registerNormalizedType(ptr,
1921 qMetaTypeDeleteHelper<QObject*>,
1922 qMetaTypeCreateHelper<QObject*>,
1923 qMetaTypeDestructHelper<QObject*>,
1924 qMetaTypeConstructHelper<QObject*>,
1926 static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QObject*>::Flags),
1928 int lst_type = QMetaType::registerNormalizedType(lst,
1929 qMetaTypeDeleteHelper<QQmlListProperty<QObject> >,
1930 qMetaTypeCreateHelper<QQmlListProperty<QObject> >,
1931 qMetaTypeDestructHelper<QQmlListProperty<QObject> >,
1932 qMetaTypeConstructHelper<QQmlListProperty<QObject> >,
1933 sizeof(QQmlListProperty<QObject>),
1934 static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<QObject> >::Flags),
1935 static_cast<QMetaObject*>(0));
1937 Locker locker(this);
1938 m_qmlLists.insert(lst_type, ptr_type);
1939 m_compositeTypes.insert(ptr_type, mo);
1942 void QQmlEnginePrivate::unregisterCompositeType(const QMetaObject *mo)
1944 QByteArray name = mo->className();
1946 QByteArray ptr = name + '*';
1947 QByteArray lst = "QQmlListProperty<" + name + '>';
1949 int ptr_type = QMetaType::type(ptr.constData());
1950 int lst_type = QMetaType::type(lst.constData());
1952 Locker locker(this);
1953 m_qmlLists.remove(lst_type);
1954 m_compositeTypes.remove(ptr_type);
1957 void QQmlEnginePrivate::clearCache()
1959 typeLoader.clearCache(this, &QQmlEnginePrivate::typeUnloaded);
1962 void QQmlEnginePrivate::trimCache()
1964 typeLoader.trimCache(this, &QQmlEnginePrivate::typeUnloaded);
1967 void QQmlEnginePrivate::typeUnloaded(QQmlTypeData *typeData)
1969 if (typeData && typeData->compiledData()) {
1970 const QMetaObject *mo = typeData->compiledData()->root;
1971 if (QQmlPropertyCache *pc = propertyCache.value(mo)) {
1972 propertyCache.remove(mo);
1975 unregisterCompositeType(mo);
1979 bool QQmlEnginePrivate::isTypeLoaded(const QUrl &url) const
1981 return typeLoader.isTypeLoaded(url);
1984 bool QQmlEnginePrivate::isScriptLoaded(const QUrl &url) const
1986 return typeLoader.isScriptLoaded(url);
1989 bool QQml_isFileCaseCorrect(const QString &fileName)
1991 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1992 QFileInfo info(fileName);
1993 const QString absolute = info.absoluteFilePath();
1995 #if defined(Q_OS_MAC)
1996 const QString canonical = info.canonicalFilePath();
1997 #elif defined(Q_OS_WIN)
1998 wchar_t buffer[1024];
2000 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
2001 if (rv == 0 || rv >= 1024) return true;
2002 rv = ::GetLongPathName(buffer, buffer, 1024);
2003 if (rv == 0 || rv >= 1024) return true;
2005 const QString canonical = QString::fromWCharArray(buffer);
2008 const int absoluteLength = absolute.length();
2009 const int canonicalLength = canonical.length();
2011 const int length = qMin(absoluteLength, canonicalLength);
2012 for (int ii = 0; ii < length; ++ii) {
2013 const QChar &a = absolute.at(absoluteLength - 1 - ii);
2014 const QChar &c = canonical.at(canonicalLength - 1 - ii);
2016 if (a.toLower() != c.toLower())
2028 \fn QQmlEngine *qmlEngine(const QObject *object)
2031 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
2032 QQmlEngine::contextForObject(object)->engine(), but more efficient.
2036 \fn QQmlContext *qmlContext(const QObject *object)
2039 Returns the QQmlContext associated with \a object, if any. This is equivalent to
2040 QQmlEngine::contextForObject(object).