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;
444 for (QHash<int, QQmlCompiledData *>::Iterator iter = m_compositeTypes.begin(); iter != m_compositeTypes.end(); ++iter)
445 iter.value()->isRegisteredWithEngine = false;
448 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
450 QObjectPrivate *p = QObjectPrivate::get(o);
451 if (p->declarativeData) {
452 QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
453 if (d->ownContext && d->context) {
454 d->context->destroy();
458 // Mark this object as in the process of deletion to
459 // prevent it resolving in bindings
460 QQmlData::markAsDeleted(o);
464 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
466 static_cast<QQmlData *>(d)->destroyed(o);
469 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
471 static_cast<QQmlData *>(d)->parentChanged(o, p);
474 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **a)
476 QQmlData *ddata = QQmlData::get(object, false);
477 if (!ddata) return; // Probably being deleted
479 // In general, QML only supports QObject's that live on the same thread as the QQmlEngine
480 // that they're exposed to. However, to make writing "worker objects" that calculate data
481 // in a separate thread easier, QML allows a QObject that lives in the same thread as the
482 // QQmlEngine to emit signals from a different thread. These signals are then automatically
483 // marshalled back onto the QObject's thread and handled by QML from there. This is tested
484 // by the qqmlecmascript::threadSignal() autotest.
485 if (ddata->notifyList &&
486 QThread::currentThreadId() != QObjectPrivate::get(object)->threadData->threadId) {
488 QMetaMethod m = object->metaObject()->method(index);
489 QList<QByteArray> parameterTypes = m.parameterTypes();
491 int *types = (int *)malloc((parameterTypes.count() + 1) * sizeof(int));
492 void **args = (void **) malloc((parameterTypes.count() + 1) *sizeof(void *));
494 types[0] = 0; // return type
495 args[0] = 0; // return value
497 for (int ii = 0; ii < parameterTypes.count(); ++ii) {
498 const QByteArray &typeName = parameterTypes.at(ii);
499 if (typeName.endsWith('*'))
500 types[ii + 1] = QMetaType::VoidStar;
502 types[ii + 1] = QMetaType::type(typeName);
504 if (!types[ii + 1]) {
505 qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
506 "(Make sure '%s' is registered using qRegisterMetaType().)",
507 typeName.constData(), typeName.constData());
513 args[ii + 1] = QMetaType::create(types[ii + 1], a[ii + 1]);
516 QMetaCallEvent *ev = new QMetaCallEvent(index, 0, 0, object, index,
517 parameterTypes.count() + 1, types, args);
518 QCoreApplication::postEvent(object, ev);
521 QQmlNotifierEndpoint *ep = ddata->notify(index);
522 if (ep) QQmlNotifier::emitNotify(ep, a);
526 int QQmlData::receivers(QAbstractDeclarativeData *d, const QObject *, int index)
528 return static_cast<QQmlData *>(d)->endpointCount(index);
531 int QQmlData::endpointCount(int index)
534 QQmlNotifierEndpoint *ep = notify(index);
545 void QQmlData::markAsDeleted(QObject *o)
547 QQmlData::setQueuedForDeletion(o);
549 QObjectPrivate *p = QObjectPrivate::get(o);
550 for (QList<QObject *>::iterator it = p->children.begin(), end = p->children.end(); it != end; ++it) {
551 QQmlData::markAsDeleted(*it);
555 void QQmlData::setQueuedForDeletion(QObject *object)
558 if (QObjectPrivate *priv = QObjectPrivate::get(object)) {
559 if (!priv->wasDeleted && priv->declarativeData) {
560 QQmlData *ddata = QQmlData::get(object, false);
561 if (ddata->ownContext && ddata->context)
562 ddata->context->emitDestruction();
563 ddata->isQueuedForDeletion = true;
569 void QQmlEnginePrivate::init()
573 static bool firstTime = true;
575 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component");
581 qRegisterMetaType<QVariant>("QVariant");
582 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
583 qRegisterMetaType<QJSValue>("QJSValue");
584 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
585 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
586 qRegisterMetaType<QList<int> >("QList<int>");
587 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
589 v8engine()->setEngine(q);
591 rootContext = new QQmlContext(q,true);
593 if (QCoreApplication::instance()->thread() == q->thread() &&
594 QQmlEngineDebugService::isDebuggingEnabled()) {
596 QQmlEngineDebugService::instance()->addEngine(q);
597 QV8DebugService::initialize(v8engine());
598 QV8ProfilerService::initialize();
599 QQmlProfilerService::initialize();
600 QDebugMessageService::instance();
603 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
604 if (!dataLocation.isEmpty())
605 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator())
606 + QDir::separator() + QLatin1String("QML")
607 + QDir::separator() + QLatin1String("OfflineStorage");
610 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
613 if (!workerScriptEngine)
614 workerScriptEngine = new QQuickWorkerScriptEngine(q);
615 return workerScriptEngine;
622 \brief The QQmlEngine class provides an environment for instantiating QML components.
625 Each QML component is instantiated in a QQmlContext.
626 QQmlContext's are essential for passing data to QML
627 components. In QML, contexts are arranged hierarchically and this
628 hierarchy is managed by the QQmlEngine.
630 Prior to creating any QML components, an application must have
631 created a QQmlEngine to gain access to a QML context. The
632 following example shows how to create a simple Text item.
636 QQmlComponent component(&engine);
637 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
638 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
640 //add item to view, etc
644 In this case, the Text item will be created in the engine's
645 \l {QQmlEngine::rootContext()}{root context}.
647 Note that the QtQuick 1 version is called QDeclarativeEngine.
649 \sa QQmlComponent, QQmlContext
653 Create a new QQmlEngine with the given \a parent.
655 QQmlEngine::QQmlEngine(QObject *parent)
656 : QJSEngine(*new QQmlEnginePrivate(this), parent)
663 Destroys the QQmlEngine.
665 Any QQmlContext's created on this engine will be
666 invalidated, but not destroyed (unless they are parented to the
669 QQmlEngine::~QQmlEngine()
672 if (d->isDebugging) {
673 QQmlEngineDebugService::instance()->remEngine(this);
676 // Emit onDestruction signals for the root context before
677 // we destroy the contexts, engine, Module APIs etc. that
678 // may be required to handle the destruction signal.
679 QQmlContextData::get(rootContext())->emitDestruction();
681 // if we are the parent of any of the qobject module api instances,
682 // we need to remove them from our internal list, in order to prevent
683 // a segfault in engine private dtor.
684 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
685 QObject *currQObjectApi = 0;
686 QQmlMetaType::ModuleApiInstance *currInstance = 0;
687 foreach (const QQmlMetaType::ModuleApi &key, keys) {
688 currInstance = d->moduleApiInstances.value(key);
689 currQObjectApi = currInstance->qobjectApi;
690 if (this->children().contains(currQObjectApi)) {
691 delete currQObjectApi;
693 d->moduleApiInstances.remove(key);
697 if (d->incubationController)
698 d->incubationController->d = 0;
701 /*! \fn void QQmlEngine::quit()
702 This signal is emitted when the QML loaded by the engine would like to quit.
705 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
706 This signal is emitted when \a warnings messages are generated by QML.
710 Clears the engine's internal component cache.
712 This function causes the property metadata of all components previously
713 loaded by the engine to be destroyed. All previously loaded components and
714 the property bindings for all extant objects created from those components will
717 This function returns the engine to a state where it does not contain any loaded
718 component data. This may be useful in order to reload a smaller subset of the
719 previous component set, or to load a new version of a previously loaded component.
721 Once the component cache has been cleared, components must be loaded before
722 any new objects can be created.
724 \sa trimComponentCache()
726 void QQmlEngine::clearComponentCache()
729 d->typeLoader.clearCache();
733 Trims the engine's internal component cache.
735 This function causes the property metadata of any loaded components which are
736 not currently in use to be destroyed.
738 A component is considered to be in use if there are any extant instances of
739 the component itself, any instances of other components that use the component,
740 or any objects instantiated by any of those components.
742 \sa clearComponentCache()
744 void QQmlEngine::trimComponentCache()
747 d->typeLoader.trimCache();
751 Returns the engine's root context.
753 The root context is automatically created by the QQmlEngine.
754 Data that should be available to all QML component instances
755 instantiated by the engine should be put in the root context.
757 Additional data that should only be available to a subset of
758 component instances should be added to sub-contexts parented to the
761 QQmlContext *QQmlEngine::rootContext() const
763 Q_D(const QQmlEngine);
764 return d->rootContext;
768 Sets the \a factory to use for creating QNetworkAccessManager(s).
770 QNetworkAccessManager is used for all network access by QML. By
771 implementing a factory it is possible to create custom
772 QNetworkAccessManager with specialized caching, proxy and cookie
775 The factory must be set before executing the engine.
777 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
780 QMutexLocker locker(&d->mutex);
781 d->networkAccessManagerFactory = factory;
785 Returns the current QQmlNetworkAccessManagerFactory.
787 \sa setNetworkAccessManagerFactory()
789 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
791 Q_D(const QQmlEngine);
792 return d->networkAccessManagerFactory;
795 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
798 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
800 void *args[] = { 0 };
801 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
805 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
807 QMutexLocker locker(&mutex);
808 QNetworkAccessManager *nam;
809 if (networkAccessManagerFactory) {
810 nam = networkAccessManagerFactory->create(parent);
812 nam = new QNetworkAccessManager(parent);
818 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
820 Q_Q(const QQmlEngine);
821 if (!networkAccessManager)
822 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
823 return networkAccessManager;
827 Returns a common QNetworkAccessManager which can be used by any QML
828 element instantiated by this engine.
830 If a QQmlNetworkAccessManagerFactory has been set and a
831 QNetworkAccessManager has not yet been created, the
832 QQmlNetworkAccessManagerFactory will be used to create the
833 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
834 will have no proxy or cache set.
836 \sa setNetworkAccessManagerFactory()
838 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
840 Q_D(const QQmlEngine);
841 return d->getNetworkAccessManager();
846 Sets the \a provider to use for images requested via the \e
847 image: url scheme, with host \a providerId. The QQmlEngine
848 takes ownership of \a provider.
850 Image providers enable support for pixmap and threaded image
851 requests. See the QQuickImageProvider documentation for details on
852 implementing and using image providers.
854 All required image providers should be added to the engine before any
855 QML sources files are loaded.
857 \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
859 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
862 QMutexLocker locker(&d->mutex);
863 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
867 Returns the image provider set for \a providerId.
869 Returns the provider if it was found; otherwise returns 0.
871 \sa QQuickImageProvider
873 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
875 Q_D(const QQmlEngine);
876 QMutexLocker locker(&d->mutex);
877 return d->imageProviders.value(providerId).data();
881 Removes the image provider for \a providerId.
883 \sa addImageProvider(), QQuickImageProvider
885 void QQmlEngine::removeImageProvider(const QString &providerId)
888 QMutexLocker locker(&d->mutex);
889 d->imageProviders.take(providerId);
893 Return the base URL for this engine. The base URL is only used to
894 resolve components when a relative URL is passed to the
895 QQmlComponent constructor.
897 If a base URL has not been explicitly set, this method returns the
898 application's current working directory.
902 QUrl QQmlEngine::baseUrl() const
904 Q_D(const QQmlEngine);
905 if (d->baseUrl.isEmpty()) {
906 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
913 Set the base URL for this engine to \a url.
917 void QQmlEngine::setBaseUrl(const QUrl &url)
924 Returns true if warning messages will be output to stderr in addition
925 to being emitted by the warnings() signal, otherwise false.
927 The default value is true.
929 bool QQmlEngine::outputWarningsToStandardError() const
931 Q_D(const QQmlEngine);
932 return d->outputWarningsToStdErr;
936 Set whether warning messages will be output to stderr to \a enabled.
938 If \a enabled is true, any warning messages generated by QML will be
939 output to stderr and emitted by the warnings() signal. If \a enabled
940 is false, on the warnings() signal will be emitted. This allows
941 applications to handle warning output themselves.
943 The default value is true.
945 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
948 d->outputWarningsToStdErr = enabled;
952 Returns the QQmlContext for the \a object, or 0 if no
953 context has been set.
955 When the QQmlEngine instantiates a QObject, the context is
958 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
963 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
966 static_cast<QQmlData *>(priv->declarativeData);
970 else if (data->outerContext)
971 return data->outerContext->asQQmlContext();
977 Sets the QQmlContext for the \a object to \a context.
978 If the \a object already has a context, a warning is
979 output, but the context is not changed.
981 When the QQmlEngine instantiates a QObject, the context is
984 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
986 if (!object || !context)
989 QQmlData *data = QQmlData::get(object, true);
991 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
995 QQmlContextData *contextData = QQmlContextData::get(context);
996 contextData->addObject(object);
1000 \enum QQmlEngine::ObjectOwnership
1002 Ownership controls whether or not QML automatically destroys the
1003 QObject when the object is garbage collected by the JavaScript
1004 engine. The two ownership options are:
1006 \value CppOwnership The object is owned by C++ code, and will
1007 never be deleted by QML. The JavaScript destroy() method cannot be
1008 used on objects with CppOwnership. This option is similar to
1009 QScriptEngine::QtOwnership.
1011 \value JavaScriptOwnership The object is owned by JavaScript.
1012 When the object is returned to QML as the return value of a method
1013 call or property access, QML will track it, and delete the object
1014 if there are no remaining JavaScript references to it and it has no
1015 QObject::parent(). An object tracked by one QQmlEngine
1016 will be deleted during that QQmlEngine's destructor, and thus
1017 JavaScript references between objects with JavaScriptOwnership from
1018 two different engines will not be valid after the deletion of one of
1019 those engines. This option is similar to QScriptEngine::ScriptOwnership.
1021 Generally an application doesn't need to set an object's ownership
1022 explicitly. QML uses a heuristic to set the default object
1023 ownership. By default, an object that is created by QML has
1024 JavaScriptOwnership. The exception to this are the root objects
1025 created by calling QQmlComponent::create() or
1026 QQmlComponent::beginCreate() which have CppOwnership by
1027 default. The ownership of these root-level objects is considered to
1028 have been transferred to the C++ caller.
1030 Objects not-created by QML have CppOwnership by default. The
1031 exception to this is objects returned from a C++ method call. The
1032 ownership of these objects is passed to JavaScript.
1034 Calling setObjectOwnership() overrides the default ownership
1035 heuristic used by QML.
1039 Sets the \a ownership of \a object.
1041 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
1046 QQmlData *ddata = QQmlData::get(object, true);
1050 ddata->indestructible = (ownership == CppOwnership)?true:false;
1051 ddata->explicitIndestructibleSet = true;
1055 Returns the ownership of \a object.
1057 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
1060 return CppOwnership;
1062 QQmlData *ddata = QQmlData::get(object, false);
1064 return CppOwnership;
1066 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
1069 bool QQmlEngine::event(QEvent *e)
1072 if (e->type() == QEvent::User)
1073 d->doDeleteInEngineThread();
1075 return QJSEngine::event(e);
1078 void QQmlEnginePrivate::doDeleteInEngineThread()
1080 QFieldList<Deletable, &Deletable::next> list;
1082 list.copyAndClear(toDeleteInEngineThread);
1085 while (Deletable *d = list.takeFirst())
1089 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
1091 QQmlData *data = QQmlData::get(object);
1093 if (data && data->compiledData && data->deferredIdx) {
1094 QQmlObjectCreatingProfiler prof;
1096 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
1097 prof.setTypeName(type ? type->qmlTypeName()
1098 : QString::fromUtf8(object->metaObject()->className()));
1099 if (data->outerContext)
1100 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
1102 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
1104 QQmlComponentPrivate::ConstructionState state;
1105 QQmlComponentPrivate::beginDeferred(ep, object, &state);
1107 // Release the reference for the deferral action (we still have one from construction)
1108 data->compiledData->release();
1109 data->compiledData = 0;
1111 QQmlComponentPrivate::complete(ep, &state);
1115 QQmlContext *qmlContext(const QObject *obj)
1117 return QQmlEngine::contextForObject(obj);
1120 QQmlEngine *qmlEngine(const QObject *obj)
1122 QQmlData *data = QQmlData::get(obj, false);
1123 if (!data || !data->context)
1125 return data->context->engine;
1128 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1130 QQmlData *data = QQmlData::get(object);
1132 return 0; // Attached properties are only on objects created by QML
1134 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1138 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1142 rv = pf(const_cast<QObject *>(object));
1145 data->attachedProperties()->insert(id, rv);
1150 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1151 const QMetaObject *attachedMetaObject, bool create)
1154 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1156 if (*idCache == -1 || !object)
1159 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1162 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1164 #ifndef QQML_NO_DEBUG_PROTOCOL
1165 if (!QQmlEnginePrivate::qml_debugging_enabled
1167 qDebug("QML debugging is enabled. Only use this in a safe environment.");
1169 QQmlEnginePrivate::qml_debugging_enabled = true;
1174 class QQmlDataExtended {
1177 ~QQmlDataExtended();
1179 QHash<int, QObject *> attachedProperties;
1182 QQmlDataExtended::QQmlDataExtended()
1186 QQmlDataExtended::~QQmlDataExtended()
1190 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1193 layout(endpoint->next);
1195 int index = endpoint->sourceSignal;
1196 index = qMin(index, 0xFFFF - 1);
1198 endpoint->next = notifies[index];
1199 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1200 endpoint->prev = ¬ifies[index];
1201 notifies[index] = endpoint;
1204 void QQmlData::NotifyList::layout()
1206 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1209 QQmlNotifierEndpoint **old = notifies;
1210 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1211 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1212 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1213 sizeof(QQmlNotifierEndpoint*);
1214 memset(notifies + notifiesSize, 0, memsetSize);
1216 if (notifies != old) {
1217 for (int ii = 0; ii < notifiesSize; ++ii)
1219 notifies[ii]->prev = ¬ifies[ii];
1222 notifiesSize = maximumTodoIndex + 1;
1227 maximumTodoIndex = 0;
1231 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1234 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1235 notifyList->connectionMask = 0;
1236 notifyList->maximumTodoIndex = 0;
1237 notifyList->notifiesSize = 0;
1238 notifyList->todo = 0;
1239 notifyList->notifies = 0;
1242 Q_ASSERT(!endpoint->isConnected());
1244 index = qMin(index, 0xFFFF - 1);
1245 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1247 if (index < notifyList->notifiesSize) {
1249 endpoint->next = notifyList->notifies[index];
1250 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1251 endpoint->prev = ¬ifyList->notifies[index];
1252 notifyList->notifies[index] = endpoint;
1255 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1257 endpoint->next = notifyList->todo;
1258 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1259 endpoint->prev = ¬ifyList->todo;
1260 notifyList->todo = endpoint;
1264 bool QQml_isSignalConnected(QObject *obj, int signal_index, int index)
1266 QQmlData *data = QQmlData::get(obj);
1267 return QObjectPrivate::get(obj)->isSignalConnected(signal_index) || (data && data->signalHasEndpoint(index));
1271 index MUST be the index returned by QMetaMethod::index()
1272 This is different than the index returned by QObjectPrivate::signalIndex()
1274 bool QQmlData::signalHasEndpoint(int index)
1276 return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
1279 QHash<int, QObject *> *QQmlData::attachedProperties() const
1281 if (!extendedData) extendedData = new QQmlDataExtended;
1282 return &extendedData->attachedProperties;
1285 void QQmlData::destroyed(QObject *object)
1287 if (nextContextObject)
1288 nextContextObject->prevContextObject = prevContextObject;
1289 if (prevContextObject)
1290 *prevContextObject = nextContextObject;
1292 QQmlAbstractBinding *binding = bindings;
1294 QQmlAbstractBinding *next = binding->m_nextBinding;
1295 binding->m_prevBinding = 0;
1296 binding->m_nextBinding = 0;
1302 compiledData->release();
1306 QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1307 while (signalHandler) {
1308 if (signalHandler->isEvaluating()) {
1309 // The object is being deleted during signal handler evaluation.
1310 // This will cause a crash due to invalid memory access when the
1311 // evaluation has completed.
1312 // Abort with a friendly message instead.
1313 QString locationString;
1314 QQmlBoundSignalExpression *expr = signalHandler->expression();
1316 QString fileName = expr->sourceFile();
1317 if (fileName.isEmpty())
1318 fileName = QStringLiteral("<Unknown File>");
1319 locationString.append(fileName);
1320 locationString.append(QString::fromLatin1(":%0: ").arg(expr->lineNumber()));
1321 QString source = expr->expression();
1322 if (source.size() > 100) {
1323 source.truncate(96);
1324 source.append(QStringLiteral(" ..."));
1326 locationString.append(source);
1328 locationString = QStringLiteral("<Unknown Location>");
1330 qFatal("Object %p destroyed while one of its QML signal handlers is in progress.\n"
1331 "Most likely the object was deleted synchronously (use QObject::deleteLater() "
1332 "instead), or the application is running a nested event loop.\n"
1333 "This behavior is NOT supported!\n"
1334 "%s", object, qPrintable(locationString));
1337 QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1338 signalHandler->m_prevSignal = 0;
1339 signalHandler->m_nextSignal = 0;
1340 delete signalHandler;
1341 signalHandler = next;
1348 propertyCache->release();
1350 if (ownContext && context)
1354 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1355 *guard = (QObject *)0;
1356 guard->objectDestroyed(object);
1360 while (notifyList->todo)
1361 notifyList->todo->disconnect();
1362 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1363 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1366 free(notifyList->notifies);
1372 delete extendedData;
1374 // Dispose the handle.
1375 // We don't simply clear it (and wait for next gc cycle to dispose
1376 // via the weak qobject reference callback) as this affects the
1377 // outcomes of v8's gc statistical analysis heuristics, which can
1378 // cause unnecessary growth of the old pointer space js heap area.
1379 qPersistentDispose(v8object);
1385 void QQmlData::parentChanged(QObject *object, QObject *parent)
1391 bool QQmlData::hasBindingBit(int bit) const
1393 if (bindingBitsSize > bit)
1394 return bindingBits[bit / 32] & (1 << (bit % 32));
1399 void QQmlData::clearBindingBit(int bit)
1401 if (bindingBitsSize > bit)
1402 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1405 void QQmlData::setBindingBit(QObject *obj, int bit)
1407 if (bindingBitsSize <= bit) {
1408 int props = QQmlMetaObject(obj).propertyCount();
1409 Q_ASSERT(bit < props);
1411 int arraySize = (props + 31) / 32;
1412 int oldArraySize = bindingBitsSize / 32;
1414 bindingBits = (quint32 *)realloc(bindingBits,
1415 arraySize * sizeof(quint32));
1417 memset(bindingBits + oldArraySize,
1419 sizeof(quint32) * (arraySize - oldArraySize));
1421 bindingBitsSize = arraySize * 32;
1424 bindingBits[bit / 32] |= (1 << (bit % 32));
1427 void QQmlEnginePrivate::sendQuit()
1431 if (q->receivers(SIGNAL(quit())) == 0) {
1432 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1436 static void dumpwarning(const QQmlError &error)
1438 QMessageLogger(error.url().toString().toLatin1().constData(),
1439 error.line(), 0).warning().nospace()
1440 << qPrintable(error.toString());
1443 static void dumpwarning(const QList<QQmlError> &errors)
1445 for (int ii = 0; ii < errors.count(); ++ii)
1446 dumpwarning(errors.at(ii));
1449 void QQmlEnginePrivate::warning(const QQmlError &error)
1452 q->warnings(QList<QQmlError>() << error);
1453 if (outputWarningsToStdErr)
1457 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1460 q->warnings(errors);
1461 if (outputWarningsToStdErr)
1462 dumpwarning(errors);
1465 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1468 QQmlEnginePrivate::get(engine)->warning(error);
1473 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1476 QQmlEnginePrivate::get(engine)->warning(error);
1481 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1484 engine->warning(error);
1489 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1492 engine->warning(error);
1498 This function should be called prior to evaluation of any js expression,
1499 so that scarce resources are not freed prematurely (eg, if there is a
1500 nested javascript expression).
1502 void QQmlEnginePrivate::referenceScarceResources()
1504 scarceResourcesRefCount += 1;
1508 This function should be called after evaluation of the js expression is
1509 complete, and so the scarce resources may be freed safely.
1511 void QQmlEnginePrivate::dereferenceScarceResources()
1513 Q_ASSERT(scarceResourcesRefCount > 0);
1514 scarceResourcesRefCount -= 1;
1516 // if the refcount is zero, then evaluation of the "top level"
1517 // expression must have completed. We can safely release the
1518 // scarce resources.
1519 if (scarceResourcesRefCount == 0) {
1520 // iterate through the list and release them all.
1521 // note that the actual SRD is owned by the JS engine,
1522 // so we cannot delete the SRD; but we can free the
1523 // memory used by the variant in the SRD.
1524 while (ScarceResourceData *sr = scarceResources.first()) {
1525 sr->data = QVariant();
1526 scarceResources.remove(sr);
1532 Adds \a path as a directory where the engine searches for
1533 installed modules in a URL-based directory structure.
1534 The \a path may be a local filesystem directory or a URL.
1536 The newly added \a path will be first in the importPathList().
1538 \sa setImportPathList(), {QML Modules}
1540 void QQmlEngine::addImportPath(const QString& path)
1543 d->importDatabase.addImportPath(path);
1547 Returns the list of directories where the engine searches for
1548 installed modules in a URL-based directory structure.
1550 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1551 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1552 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1553 provided by that module. A \c qmldir file is required for defining the
1554 type version mapping and possibly QML extensions plugins.
1556 By default, the list contains the directory of the application executable,
1557 paths specified in the \c QML_IMPORT_PATH environment variable,
1558 and the builtin \c ImportsPath from QLibraryInfo.
1560 \sa addImportPath(), setImportPathList()
1562 QStringList QQmlEngine::importPathList() const
1564 Q_D(const QQmlEngine);
1565 return d->importDatabase.importPathList();
1569 Sets \a paths as the list of directories where the engine searches for
1570 installed modules in a URL-based directory structure.
1572 By default, the list contains the directory of the application executable,
1573 paths specified in the \c QML_IMPORT_PATH environment variable,
1574 and the builtin \c ImportsPath from QLibraryInfo.
1576 \sa importPathList(), addImportPath()
1578 void QQmlEngine::setImportPathList(const QStringList &paths)
1581 d->importDatabase.setImportPathList(paths);
1586 Adds \a path as a directory where the engine searches for
1587 native plugins for imported modules (referenced in the \c qmldir file).
1589 By default, the list contains only \c ., i.e. the engine searches
1590 in the directory of the \c qmldir file itself.
1592 The newly added \a path will be first in the pluginPathList().
1594 \sa setPluginPathList()
1596 void QQmlEngine::addPluginPath(const QString& path)
1599 d->importDatabase.addPluginPath(path);
1604 Returns the list of directories where the engine searches for
1605 native plugins for imported modules (referenced in the \c qmldir file).
1607 By default, the list contains only \c ., i.e. the engine searches
1608 in the directory of the \c qmldir file itself.
1610 \sa addPluginPath(), setPluginPathList()
1612 QStringList QQmlEngine::pluginPathList() const
1614 Q_D(const QQmlEngine);
1615 return d->importDatabase.pluginPathList();
1619 Sets the list of directories where the engine searches for
1620 native plugins for imported modules (referenced in the \c qmldir file)
1623 By default, the list contains only \c ., i.e. the engine searches
1624 in the directory of the \c qmldir file itself.
1626 \sa pluginPathList(), addPluginPath()
1628 void QQmlEngine::setPluginPathList(const QStringList &paths)
1631 d->importDatabase.setPluginPathList(paths);
1635 Imports the plugin named \a filePath with the \a uri provided.
1636 Returns true if the plugin was successfully imported; otherwise returns false.
1638 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1640 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1642 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1645 return d->importDatabase.importPlugin(filePath, uri, errors);
1649 Imports the plugin named \a filePath with the \a uri provided.
1650 Returns true if the plugin was successfully imported; otherwise returns false.
1652 On failure and if non-null, *\a errorString will be set to a message describing the failure.
1654 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1656 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1659 QList<QQmlError> errors;
1660 bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1661 if (!errors.isEmpty()) {
1663 for (int i = 0; i < errors.size(); ++i) {
1664 builtError = QString(QLatin1String("%1\n %2"))
1666 .arg(errors.at(i).toString());
1668 *errorString = builtError;
1674 \property QQmlEngine::offlineStoragePath
1675 \brief the directory for storing offline user data
1677 Returns the directory where SQL and other offline
1680 QQuickWebView and the SQL databases created with openDatabase()
1683 The default is QML/OfflineStorage in the platform-standard
1684 user application data directory.
1686 Note that the path may not currently exist on the filesystem, so
1687 callers wanting to \e create new files at this location should create
1688 it first - see QDir::mkpath().
1690 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1693 d->offlineStoragePath = dir;
1696 QString QQmlEngine::offlineStoragePath() const
1698 Q_D(const QQmlEngine);
1699 return d->offlineStoragePath;
1702 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1706 if (!mo->superClass()) {
1707 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1708 propertyCache.insert(mo, rv);
1711 QQmlPropertyCache *super = cache(mo->superClass());
1712 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1713 propertyCache.insert(mo, rv);
1718 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1721 QList<QQmlType *> types;
1723 int maxMinorVersion = 0;
1725 const QMetaObject *metaObject = type->metaObject();
1727 while (metaObject) {
1728 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1729 type->majorVersion(), minorVersion);
1731 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1737 metaObject = metaObject->superClass();
1740 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1742 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1746 QQmlPropertyCache *raw = cache(type->metaObject());
1748 bool hasCopied = false;
1750 for (int ii = 0; ii < types.count(); ++ii) {
1751 QQmlType *currentType = types.at(ii);
1755 int rev = currentType->metaObjectRevision();
1756 int moIndex = types.count() - 1 - ii;
1758 if (raw->allowedRevisionCache[moIndex] != rev) {
1763 raw->allowedRevisionCache[moIndex] = rev;
1767 // Test revision compatibility - the basic rule is:
1768 // * Anything that is excluded, cannot overload something that is not excluded *
1770 // Signals override:
1771 // * other signals and methods of the same name.
1772 // * properties named on<Signal Name>
1773 // * automatic <property name>Changed notify signals
1775 // Methods override:
1776 // * other methods of the same name
1778 // Properties override:
1779 // * other elements of the same name
1781 bool overloadError = false;
1782 QString overloadName;
1785 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1786 !overloadError && iter != raw->stringCache.end();
1789 QQmlPropertyData *d = *iter;
1790 if (raw->isAllowedInRevision(d))
1791 continue; // Not excluded - no problems
1793 // check that a regular "name" overload isn't happening
1794 QQmlPropertyData *current = d;
1795 while (!overloadError && current) {
1796 current = d->overrideData(current);
1797 if (current && raw->isAllowedInRevision(current))
1798 overloadError = true;
1803 if (overloadError) {
1804 if (hasCopied) raw->release();
1806 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."));
1810 if (!hasCopied) raw->addref();
1811 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1813 if (minorVersion != maxMinorVersion) {
1815 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1821 QQmlMetaType::ModuleApiInstance *
1822 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1824 Locker locker(this);
1826 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1828 a = new QQmlMetaType::ModuleApiInstance;
1829 a->scriptCallback = module.script;
1830 a->qobjectCallback = module.qobject;
1831 a->instanceMetaObject = module.instanceMetaObject;
1832 moduleApiInstances.insert(module, a);
1838 bool QQmlEnginePrivate::isQObject(int t)
1840 Locker locker(this);
1841 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1844 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1846 Locker locker(this);
1847 int t = v.userType();
1848 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1850 return *(QObject **)(v.constData());
1852 return QQmlMetaType::toQObject(v, ok);
1856 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1858 Locker locker(this);
1859 if (m_compositeTypes.contains(t))
1860 return QQmlMetaType::Object;
1861 else if (m_qmlLists.contains(t))
1862 return QQmlMetaType::List;
1864 return QQmlMetaType::typeCategory(t);
1867 bool QQmlEnginePrivate::isList(int t) const
1869 Locker locker(this);
1870 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1873 int QQmlEnginePrivate::listType(int t) const
1875 Locker locker(this);
1876 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1877 if (iter != m_qmlLists.end())
1880 return QQmlMetaType::listType(t);
1883 QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
1885 Locker locker(this);
1886 QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1887 if (iter != m_compositeTypes.end()) {
1888 return QQmlMetaObject((*iter)->rootPropertyCache);
1890 QQmlType *type = QQmlMetaType::qmlType(t);
1891 return QQmlMetaObject(type?type->baseMetaObject():0);
1895 QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
1897 Locker locker(this);
1898 QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1899 if (iter != m_compositeTypes.end()) {
1900 return QQmlMetaObject((*iter)->rootPropertyCache);
1902 QQmlType *type = QQmlMetaType::qmlType(t);
1903 return QQmlMetaObject(type?type->metaObject():0);
1907 QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
1909 Locker locker(this);
1910 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1911 if (iter != m_compositeTypes.end()) {
1912 return (*iter)->rootPropertyCache;
1914 QQmlType *type = QQmlMetaType::qmlType(t);
1916 return type?cache(type->metaObject()):0;
1920 QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t)
1922 Locker locker(this);
1923 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1924 if (iter != m_compositeTypes.end()) {
1925 return (*iter)->rootPropertyCache;
1927 QQmlType *type = QQmlMetaType::qmlType(t);
1929 return type?cache(type->baseMetaObject()):0;
1933 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1935 QByteArray name = data->rootPropertyCache->className();
1937 QByteArray ptr = name + '*';
1938 QByteArray lst = "QQmlListProperty<" + name + '>';
1940 int ptr_type = QMetaType::registerNormalizedType(ptr,
1941 qMetaTypeDeleteHelper<QObject*>,
1942 qMetaTypeCreateHelper<QObject*>,
1943 qMetaTypeDestructHelper<QObject*>,
1944 qMetaTypeConstructHelper<QObject*>,
1946 static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QObject*>::Flags),
1948 int lst_type = QMetaType::registerNormalizedType(lst,
1949 qMetaTypeDeleteHelper<QQmlListProperty<QObject> >,
1950 qMetaTypeCreateHelper<QQmlListProperty<QObject> >,
1951 qMetaTypeDestructHelper<QQmlListProperty<QObject> >,
1952 qMetaTypeConstructHelper<QQmlListProperty<QObject> >,
1953 sizeof(QQmlListProperty<QObject>),
1954 static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<QObject> >::Flags),
1955 static_cast<QMetaObject*>(0));
1957 data->metaTypeId = ptr_type;
1958 data->listMetaTypeId = lst_type;
1959 data->isRegisteredWithEngine = true;
1961 Locker locker(this);
1962 m_qmlLists.insert(lst_type, ptr_type);
1963 // The QQmlCompiledData is not referenced here, but it is removed from this
1964 // hash in the QQmlCompiledData destructor
1965 m_compositeTypes.insert(ptr_type, data);
1968 void QQmlEnginePrivate::unregisterCompositeType(QQmlCompiledData *data)
1970 int ptr_type = data->metaTypeId;
1971 int lst_type = data->listMetaTypeId;
1973 Locker locker(this);
1974 m_qmlLists.remove(lst_type);
1975 m_compositeTypes.remove(ptr_type);
1978 bool QQmlEnginePrivate::isTypeLoaded(const QUrl &url) const
1980 return typeLoader.isTypeLoaded(url);
1983 bool QQmlEnginePrivate::isScriptLoaded(const QUrl &url) const
1985 return typeLoader.isScriptLoaded(url);
1988 bool QQml_isFileCaseCorrect(const QString &fileName)
1990 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1991 QFileInfo info(fileName);
1992 const QString absolute = info.absoluteFilePath();
1994 #if defined(Q_OS_MAC)
1995 const QString canonical = info.canonicalFilePath();
1996 #elif defined(Q_OS_WIN)
1997 wchar_t buffer[1024];
1999 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
2000 if (rv == 0 || rv >= 1024) return true;
2001 rv = ::GetLongPathName(buffer, buffer, 1024);
2002 if (rv == 0 || rv >= 1024) return true;
2004 const QString canonical = QString::fromWCharArray(buffer);
2007 const int absoluteLength = absolute.length();
2008 const int canonicalLength = canonical.length();
2010 const int length = qMin(absoluteLength, canonicalLength);
2011 for (int ii = 0; ii < length; ++ii) {
2012 const QChar &a = absolute.at(absoluteLength - 1 - ii);
2013 const QChar &c = canonical.at(canonicalLength - 1 - ii);
2015 if (a.toLower() != c.toLower())
2027 \fn QQmlEngine *qmlEngine(const QObject *object)
2030 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
2031 QQmlEngine::contextForObject(object)->engine(), but more efficient.
2035 \fn QQmlContext *qmlContext(const QObject *object)
2038 Returns the QQmlContext associated with \a object, if any. This is equivalent to
2039 QQmlEngine::contextForObject(object).