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 \inqmlmodule QtQuick 2
113 \ingroup qml-utility-elements
115 \brief A basic QML type
117 The QtObject element is a non-visual element which contains only the
120 It can be useful to create a QtObject if you need an extremely
121 lightweight element to enclose a set of custom properties:
123 \snippet qml/qtobject.qml 0
125 It can also be useful for C++ integration, as it is just a plain
126 QObject. See the QObject documentation for further details.
129 \qmlproperty string QtObject::objectName
130 This property holds the QObject::objectName for this specific object instance.
132 This allows a C++ application to locate an item within a QML component
133 using the QObject::findChild() method. For example, the following C++
134 application locates the child \l Rectangle item and dynamically changes its
143 width: 200; height: 200
157 view.setSource(QUrl::fromLocalFile("MyRect.qml"));
160 QQuickItem *item = view.rootObject()->findChild<QQuickItem*>("myRect");
162 item->setProperty("color", QColor(Qt::yellow));
166 bool QQmlEnginePrivate::qml_debugging_enabled = false;
168 void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
170 qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
171 qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
172 qmlRegisterType<QQuickListElement>(uri, versionMajor, versionMinor,"ListElement");
173 qmlRegisterCustomType<QQuickListModel>(uri, versionMajor, versionMinor,"ListModel", new QQuickListModelParser);
174 qmlRegisterType<QQuickWorkerScript>(uri,versionMajor,versionMinor,"WorkerScript");
177 void QQmlEnginePrivate::defineModule()
179 registerBaseTypes("QtQuick", 2, 0);
180 qmlRegisterUncreatableType<QQmlLocale>("QtQuick",2,0,"Locale",QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
185 \class QQmlImageProviderBase
186 \brief The QQmlImageProviderBase class is used to register image providers in the QML engine.
189 Image providers must be registered with the QML engine. The only information the QML
190 engine knows about image providers is the type of image data they provide. To use an
191 image provider to acquire image data, you must cast the QQmlImageProviderBase pointer
192 to a QQuickImageProvider pointer.
194 \sa QQuickImageProvider, QQuickTextureFactory
198 \enum QQmlImageProviderBase::ImageType
200 Defines the type of image supported by this image provider.
202 \value Image The Image Provider provides QImage images.
203 The QQuickImageProvider::requestImage() method will be called for all image requests.
204 \value Pixmap The Image Provider provides QPixmap images.
205 The QQuickImageProvider::requestPixmap() method will be called for all image requests.
206 \value Texture The Image Provider provides QSGTextureProvider based images.
207 The QQuickImageProvider::requestTexture() method will be called for all image requests. \omitvalue
211 \enum QQmlImageProviderBase::Flag
213 Defines specific requirements or features of this image provider.
215 \value ForceAsynchronousImageLoading Ensures that image requests to the provider are
216 run in a separate thread, which allows the provider to spend as much time as needed
217 on producing the image without blocking the main thread.
221 QQmlImageProviderBase::QQmlImageProviderBase()
226 QQmlImageProviderBase::~QQmlImageProviderBase()
232 \qmlclass Qt QQmlEnginePrivate
233 \ingroup qml-utility-elements
234 \brief The QML global Qt object provides useful enums and functions from Qt.
236 \keyword QmlGlobalQtObject
238 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
240 The \c Qt object is a global object with utility functions, properties and enums.
242 It is not instantiable; to use it, call the members of the global \c Qt object directly.
249 color: Qt.rgba(1, 0, 0, 1)
250 text: Qt.md5("hello, world")
257 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
258 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
262 The Qt object also contains helper functions for creating objects of specific
263 data types. This is primarily useful when setting the properties of an item
264 when the property has one of the following types:
267 \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()}
268 \li \c rect - use \l{Qt::rect()}{Qt.rect()}
269 \li \c point - use \l{Qt::point()}{Qt.point()}
270 \li \c size - use \l{Qt::size()}{Qt.size()}
271 \li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
274 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
276 \section1 Date/Time Formatters
278 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
281 \li \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
282 \li \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
283 \li \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
286 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
289 \section1 Dynamic Object Creation
290 The following functions on the global object allow you to dynamically create QML
291 items from files or strings. See \l{Dynamic Object Management in QML} for an overview
295 \li \l{Qt::createComponent()}{object Qt.createComponent(url)}
296 \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
300 \section1 Other Functions
302 The following functions are also on the Qt object.
305 \li \l{Qt::quit()}{Qt.quit()}
306 \li \l{Qt::md5()}{Qt.md5(string)}
307 \li \l{Qt::btoa()}{string Qt.btoa(string)}
308 \li \l{Qt::atob()}{string Qt.atob(string)}
309 \li \l{Qt::binding()}{object Qt.binding(function)}
310 \li \l{Qt::locale()}{object Qt.locale()}
311 \li \l{Qt::resolvedUrl()}{string Qt.resolvedUrl(string)}
312 \li \l{Qt::openUrlExternally()}{Qt.openUrlExternally(string)}
313 \li \l{Qt::fontFamilies()}{list<string> Qt.fontFamilies()}
318 \qmlproperty object Qt::application
321 The \c application object provides access to global application state
322 properties shared by many QML components.
328 \li \c application.active
330 This read-only property indicates whether the application is the top-most and focused
331 application, and the user is able to interact with the application. The property
332 is false when the application is in the background, the device keylock or screen
333 saver is active, the screen backlight is turned off, or the global system dialog
334 is being displayed on top of the application. It can be used for stopping and
335 pausing animations, timers and active processing of data in order to save device
336 battery power and free device memory and processor load when the application is not
340 \li \c application.layoutDirection
342 This read-only property can be used to query the default layout direction of the
343 application. On system start-up, the default layout direction depends on the
344 application's language. The property has a value of \c Qt.RightToLeft in locales
345 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
346 where the reading direction flows from left to right. You can bind to this
347 property to customize your application layouts to support both layout directions.
352 \li Qt.LeftToRight - Text and graphics elements should be positioned
354 \li Qt.RightToLeft - Text and graphics elements should be positioned
360 The following example uses the \c application object to indicate
361 whether the application is currently active:
363 \snippet qml/application.qml document
367 \qmlproperty object Qt::inputMethod
370 The \c inputMethod object allows access to application's QInputMethod object
371 and all its properties and slots. See the QInputMethod documentation for
377 \qmlmethod object Qt::include(string url, jsobject callback)
379 Includes another JavaScript file. This method can only be used from within JavaScript files,
380 and not regular QML files.
382 This imports all functions from \a url into the current script's namespace.
384 Qt.include() returns an object that describes the status of the operation. The object has
385 a single property, \c {status}, that is set to one of the following values:
388 \header \li Symbol \li Value \li Description
389 \row \li result.OK \li 0 \li The include completed successfully.
390 \row \li result.LOADING \li 1 \li Data is being loaded from the network.
391 \row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
392 \row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
393 An additional \c exception property will be set in this case.
396 The \c status property will be updated as the operation progresses.
398 If provided, \a callback is invoked when the operation completes. The callback is passed
399 the same object as is returned from the Qt.include() call.
401 // Qt.include() is implemented in qv8include.cpp
404 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
405 : propertyCapture(0), rootContext(0), isDebugging(false),
406 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
407 cleanup(0), erroredBindings(0), inProgressCreations(0),
408 workerScriptEngine(0), activeVME(0),
409 networkAccessManager(0), networkAccessManagerFactory(0),
410 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
411 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
415 QQmlEnginePrivate::~QQmlEnginePrivate()
417 if (inProgressCreations)
418 qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
421 QQmlCleanup *c = cleanup;
423 if (cleanup) cleanup->prev = &cleanup;
429 doDeleteInEngineThread();
431 if (incubationController) incubationController->d = 0;
432 incubationController = 0;
437 for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
439 for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
441 for(QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
442 delete (*iter)->qobjectApi;
445 for (QHash<int, QQmlCompiledData *>::Iterator iter = m_compositeTypes.begin(); iter != m_compositeTypes.end(); ++iter)
446 iter.value()->isRegisteredWithEngine = false;
449 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
451 QObjectPrivate *p = QObjectPrivate::get(o);
452 if (p->declarativeData) {
453 QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
454 if (d->ownContext && d->context) {
455 d->context->destroy();
459 // Mark this object as in the process of deletion to
460 // prevent it resolving in bindings
461 QQmlData::markAsDeleted(o);
465 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
467 static_cast<QQmlData *>(d)->destroyed(o);
470 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
472 static_cast<QQmlData *>(d)->parentChanged(o, p);
475 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **a)
477 QQmlData *ddata = QQmlData::get(object, false);
478 if (!ddata) return; // Probably being deleted
480 // In general, QML only supports QObject's that live on the same thread as the QQmlEngine
481 // that they're exposed to. However, to make writing "worker objects" that calculate data
482 // in a separate thread easier, QML allows a QObject that lives in the same thread as the
483 // QQmlEngine to emit signals from a different thread. These signals are then automatically
484 // marshalled back onto the QObject's thread and handled by QML from there. This is tested
485 // by the qqmlecmascript::threadSignal() autotest.
486 if (ddata->notifyList &&
487 QThread::currentThreadId() != QObjectPrivate::get(object)->threadData->threadId) {
489 QMetaMethod m = object->metaObject()->method(index);
490 QList<QByteArray> parameterTypes = m.parameterTypes();
492 int *types = (int *)malloc((parameterTypes.count() + 1) * sizeof(int));
493 void **args = (void **) malloc((parameterTypes.count() + 1) *sizeof(void *));
495 types[0] = 0; // return type
496 args[0] = 0; // return value
498 for (int ii = 0; ii < parameterTypes.count(); ++ii) {
499 const QByteArray &typeName = parameterTypes.at(ii);
500 if (typeName.endsWith('*'))
501 types[ii + 1] = QMetaType::VoidStar;
503 types[ii + 1] = QMetaType::type(typeName);
505 if (!types[ii + 1]) {
506 qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
507 "(Make sure '%s' is registered using qRegisterMetaType().)",
508 typeName.constData(), typeName.constData());
514 args[ii + 1] = QMetaType::create(types[ii + 1], a[ii + 1]);
517 QMetaCallEvent *ev = new QMetaCallEvent(index, 0, 0, object, index,
518 parameterTypes.count() + 1, types, args);
519 QCoreApplication::postEvent(object, ev);
522 QQmlNotifierEndpoint *ep = ddata->notify(index);
523 if (ep) QQmlNotifier::emitNotify(ep, a);
527 int QQmlData::receivers(QAbstractDeclarativeData *d, const QObject *, int index)
529 return static_cast<QQmlData *>(d)->endpointCount(index);
532 int QQmlData::endpointCount(int index)
535 QQmlNotifierEndpoint *ep = notify(index);
546 void QQmlData::markAsDeleted(QObject *o)
548 QQmlData::setQueuedForDeletion(o);
550 QObjectPrivate *p = QObjectPrivate::get(o);
551 for (QList<QObject *>::iterator it = p->children.begin(), end = p->children.end(); it != end; ++it) {
552 QQmlData::markAsDeleted(*it);
556 void QQmlData::setQueuedForDeletion(QObject *object)
559 if (QObjectPrivate *priv = QObjectPrivate::get(object)) {
560 if (!priv->wasDeleted && priv->declarativeData) {
561 QQmlData *ddata = QQmlData::get(object, false);
562 if (ddata->ownContext && ddata->context)
563 ddata->context->emitDestruction();
564 ddata->isQueuedForDeletion = true;
570 void QQmlEnginePrivate::init()
574 static bool firstTime = true;
576 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component");
582 qRegisterMetaType<QVariant>("QVariant");
583 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
584 qRegisterMetaType<QJSValue>("QJSValue");
585 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
586 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
587 qRegisterMetaType<QList<int> >("QList<int>");
588 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
590 v8engine()->setEngine(q);
592 rootContext = new QQmlContext(q,true);
594 if (QCoreApplication::instance()->thread() == q->thread() &&
595 QQmlEngineDebugService::isDebuggingEnabled()) {
597 QQmlEngineDebugService::instance()->addEngine(q);
598 QV8DebugService::initialize(v8engine());
599 QV8ProfilerService::initialize();
600 QQmlProfilerService::initialize();
601 QDebugMessageService::instance();
604 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
605 if (!dataLocation.isEmpty())
606 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator())
607 + QDir::separator() + QLatin1String("QML")
608 + QDir::separator() + QLatin1String("OfflineStorage");
611 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
614 if (!workerScriptEngine)
615 workerScriptEngine = new QQuickWorkerScriptEngine(q);
616 return workerScriptEngine;
623 \brief The QQmlEngine class provides an environment for instantiating QML components.
626 Each QML component is instantiated in a QQmlContext.
627 QQmlContext's are essential for passing data to QML
628 components. In QML, contexts are arranged hierarchically and this
629 hierarchy is managed by the QQmlEngine.
631 Prior to creating any QML components, an application must have
632 created a QQmlEngine to gain access to a QML context. The
633 following example shows how to create a simple Text item.
637 QQmlComponent component(&engine);
638 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
639 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
641 //add item to view, etc
645 In this case, the Text item will be created in the engine's
646 \l {QQmlEngine::rootContext()}{root context}.
648 Note that the QtQuick 1 version is called QDeclarativeEngine.
650 \sa QQmlComponent, QQmlContext
654 Create a new QQmlEngine with the given \a parent.
656 QQmlEngine::QQmlEngine(QObject *parent)
657 : QJSEngine(*new QQmlEnginePrivate(this), parent)
664 Destroys the QQmlEngine.
666 Any QQmlContext's created on this engine will be
667 invalidated, but not destroyed (unless they are parented to the
670 QQmlEngine::~QQmlEngine()
673 if (d->isDebugging) {
674 QQmlEngineDebugService::instance()->remEngine(this);
677 // Emit onDestruction signals for the root context before
678 // we destroy the contexts, engine, Module APIs etc. that
679 // may be required to handle the destruction signal.
680 QQmlContextData::get(rootContext())->emitDestruction();
682 // if we are the parent of any of the qobject module api instances,
683 // we need to remove them from our internal list, in order to prevent
684 // a segfault in engine private dtor.
685 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
686 QObject *currQObjectApi = 0;
687 QQmlMetaType::ModuleApiInstance *currInstance = 0;
688 foreach (const QQmlMetaType::ModuleApi &key, keys) {
689 currInstance = d->moduleApiInstances.value(key);
690 currQObjectApi = currInstance->qobjectApi;
691 if (this->children().contains(currQObjectApi)) {
692 delete currQObjectApi;
694 d->moduleApiInstances.remove(key);
698 if (d->incubationController)
699 d->incubationController->d = 0;
702 /*! \fn void QQmlEngine::quit()
703 This signal is emitted when the QML loaded by the engine would like to quit.
706 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
707 This signal is emitted when \a warnings messages are generated by QML.
711 Clears the engine's internal component cache.
713 This function causes the property metadata of all components previously
714 loaded by the engine to be destroyed. All previously loaded components and
715 the property bindings for all extant objects created from those components will
718 This function returns the engine to a state where it does not contain any loaded
719 component data. This may be useful in order to reload a smaller subset of the
720 previous component set, or to load a new version of a previously loaded component.
722 Once the component cache has been cleared, components must be loaded before
723 any new objects can be created.
725 \sa trimComponentCache()
727 void QQmlEngine::clearComponentCache()
730 d->typeLoader.clearCache();
734 Trims the engine's internal component cache.
736 This function causes the property metadata of any loaded components which are
737 not currently in use to be destroyed.
739 A component is considered to be in use if there are any extant instances of
740 the component itself, any instances of other components that use the component,
741 or any objects instantiated by any of those components.
743 \sa clearComponentCache()
745 void QQmlEngine::trimComponentCache()
748 d->typeLoader.trimCache();
752 Returns the engine's root context.
754 The root context is automatically created by the QQmlEngine.
755 Data that should be available to all QML component instances
756 instantiated by the engine should be put in the root context.
758 Additional data that should only be available to a subset of
759 component instances should be added to sub-contexts parented to the
762 QQmlContext *QQmlEngine::rootContext() const
764 Q_D(const QQmlEngine);
765 return d->rootContext;
769 Sets the \a factory to use for creating QNetworkAccessManager(s).
771 QNetworkAccessManager is used for all network access by QML. By
772 implementing a factory it is possible to create custom
773 QNetworkAccessManager with specialized caching, proxy and cookie
776 The factory must be set before executing the engine.
778 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
781 QMutexLocker locker(&d->mutex);
782 d->networkAccessManagerFactory = factory;
786 Returns the current QQmlNetworkAccessManagerFactory.
788 \sa setNetworkAccessManagerFactory()
790 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
792 Q_D(const QQmlEngine);
793 return d->networkAccessManagerFactory;
796 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
799 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
801 void *args[] = { 0 };
802 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
806 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
808 QMutexLocker locker(&mutex);
809 QNetworkAccessManager *nam;
810 if (networkAccessManagerFactory) {
811 nam = networkAccessManagerFactory->create(parent);
813 nam = new QNetworkAccessManager(parent);
819 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
821 Q_Q(const QQmlEngine);
822 if (!networkAccessManager)
823 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
824 return networkAccessManager;
828 Returns a common QNetworkAccessManager which can be used by any QML
829 element instantiated by this engine.
831 If a QQmlNetworkAccessManagerFactory has been set and a
832 QNetworkAccessManager has not yet been created, the
833 QQmlNetworkAccessManagerFactory will be used to create the
834 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
835 will have no proxy or cache set.
837 \sa setNetworkAccessManagerFactory()
839 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
841 Q_D(const QQmlEngine);
842 return d->getNetworkAccessManager();
847 Sets the \a provider to use for images requested via the \e
848 image: url scheme, with host \a providerId. The QQmlEngine
849 takes ownership of \a provider.
851 Image providers enable support for pixmap and threaded image
852 requests. See the QQuickImageProvider documentation for details on
853 implementing and using image providers.
855 All required image providers should be added to the engine before any
856 QML sources files are loaded.
858 \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
860 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
863 QMutexLocker locker(&d->mutex);
864 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
868 Returns the image provider set for \a providerId.
870 Returns the provider if it was found; otherwise returns 0.
872 \sa QQuickImageProvider
874 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
876 Q_D(const QQmlEngine);
877 QMutexLocker locker(&d->mutex);
878 return d->imageProviders.value(providerId).data();
882 Removes the image provider for \a providerId.
884 \sa addImageProvider(), QQuickImageProvider
886 void QQmlEngine::removeImageProvider(const QString &providerId)
889 QMutexLocker locker(&d->mutex);
890 d->imageProviders.take(providerId);
894 Return the base URL for this engine. The base URL is only used to
895 resolve components when a relative URL is passed to the
896 QQmlComponent constructor.
898 If a base URL has not been explicitly set, this method returns the
899 application's current working directory.
903 QUrl QQmlEngine::baseUrl() const
905 Q_D(const QQmlEngine);
906 if (d->baseUrl.isEmpty()) {
907 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
914 Set the base URL for this engine to \a url.
918 void QQmlEngine::setBaseUrl(const QUrl &url)
925 Returns true if warning messages will be output to stderr in addition
926 to being emitted by the warnings() signal, otherwise false.
928 The default value is true.
930 bool QQmlEngine::outputWarningsToStandardError() const
932 Q_D(const QQmlEngine);
933 return d->outputWarningsToStdErr;
937 Set whether warning messages will be output to stderr to \a enabled.
939 If \a enabled is true, any warning messages generated by QML will be
940 output to stderr and emitted by the warnings() signal. If \a enabled
941 is false, on the warnings() signal will be emitted. This allows
942 applications to handle warning output themselves.
944 The default value is true.
946 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
949 d->outputWarningsToStdErr = enabled;
953 Returns the QQmlContext for the \a object, or 0 if no
954 context has been set.
956 When the QQmlEngine instantiates a QObject, the context is
959 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
964 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
967 static_cast<QQmlData *>(priv->declarativeData);
971 else if (data->outerContext)
972 return data->outerContext->asQQmlContext();
978 Sets the QQmlContext for the \a object to \a context.
979 If the \a object already has a context, a warning is
980 output, but the context is not changed.
982 When the QQmlEngine instantiates a QObject, the context is
985 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
987 if (!object || !context)
990 QQmlData *data = QQmlData::get(object, true);
992 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
996 QQmlContextData *contextData = QQmlContextData::get(context);
997 contextData->addObject(object);
1001 \enum QQmlEngine::ObjectOwnership
1003 Ownership controls whether or not QML automatically destroys the
1004 QObject when the object is garbage collected by the JavaScript
1005 engine. The two ownership options are:
1007 \value CppOwnership The object is owned by C++ code, and will
1008 never be deleted by QML. The JavaScript destroy() method cannot be
1009 used on objects with CppOwnership. This option is similar to
1010 QScriptEngine::QtOwnership.
1012 \value JavaScriptOwnership The object is owned by JavaScript.
1013 When the object is returned to QML as the return value of a method
1014 call or property access, QML will track it, and delete the object
1015 if there are no remaining JavaScript references to it and it has no
1016 QObject::parent(). An object tracked by one QQmlEngine
1017 will be deleted during that QQmlEngine's destructor, and thus
1018 JavaScript references between objects with JavaScriptOwnership from
1019 two different engines will not be valid after the deletion of one of
1020 those engines. This option is similar to QScriptEngine::ScriptOwnership.
1022 Generally an application doesn't need to set an object's ownership
1023 explicitly. QML uses a heuristic to set the default object
1024 ownership. By default, an object that is created by QML has
1025 JavaScriptOwnership. The exception to this are the root objects
1026 created by calling QQmlComponent::create() or
1027 QQmlComponent::beginCreate() which have CppOwnership by
1028 default. The ownership of these root-level objects is considered to
1029 have been transferred to the C++ caller.
1031 Objects not-created by QML have CppOwnership by default. The
1032 exception to this is objects returned from a C++ method call. The
1033 ownership of these objects is passed to JavaScript.
1035 Calling setObjectOwnership() overrides the default ownership
1036 heuristic used by QML.
1040 Sets the \a ownership of \a object.
1042 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
1047 QQmlData *ddata = QQmlData::get(object, true);
1051 ddata->indestructible = (ownership == CppOwnership)?true:false;
1052 ddata->explicitIndestructibleSet = true;
1056 Returns the ownership of \a object.
1058 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
1061 return CppOwnership;
1063 QQmlData *ddata = QQmlData::get(object, false);
1065 return CppOwnership;
1067 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
1070 bool QQmlEngine::event(QEvent *e)
1073 if (e->type() == QEvent::User)
1074 d->doDeleteInEngineThread();
1076 return QJSEngine::event(e);
1079 void QQmlEnginePrivate::doDeleteInEngineThread()
1081 QFieldList<Deletable, &Deletable::next> list;
1083 list.copyAndClear(toDeleteInEngineThread);
1086 while (Deletable *d = list.takeFirst())
1090 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
1092 QQmlData *data = QQmlData::get(object);
1094 if (data && data->compiledData && data->deferredIdx) {
1095 QQmlObjectCreatingProfiler prof;
1097 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
1098 prof.setTypeName(type ? type->qmlTypeName()
1099 : QString::fromUtf8(object->metaObject()->className()));
1100 if (data->outerContext)
1101 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
1103 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
1105 QQmlComponentPrivate::ConstructionState state;
1106 QQmlComponentPrivate::beginDeferred(ep, object, &state);
1108 // Release the reference for the deferral action (we still have one from construction)
1109 data->compiledData->release();
1110 data->compiledData = 0;
1112 QQmlComponentPrivate::complete(ep, &state);
1116 QQmlContext *qmlContext(const QObject *obj)
1118 return QQmlEngine::contextForObject(obj);
1121 QQmlEngine *qmlEngine(const QObject *obj)
1123 QQmlData *data = QQmlData::get(obj, false);
1124 if (!data || !data->context)
1126 return data->context->engine;
1129 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1131 QQmlData *data = QQmlData::get(object);
1133 return 0; // Attached properties are only on objects created by QML
1135 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1139 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1143 rv = pf(const_cast<QObject *>(object));
1146 data->attachedProperties()->insert(id, rv);
1151 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1152 const QMetaObject *attachedMetaObject, bool create)
1155 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1157 if (*idCache == -1 || !object)
1160 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1163 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1165 #ifndef QQML_NO_DEBUG_PROTOCOL
1166 if (!QQmlEnginePrivate::qml_debugging_enabled
1168 qDebug("QML debugging is enabled. Only use this in a safe environment.");
1170 QQmlEnginePrivate::qml_debugging_enabled = true;
1175 class QQmlDataExtended {
1178 ~QQmlDataExtended();
1180 QHash<int, QObject *> attachedProperties;
1183 QQmlDataExtended::QQmlDataExtended()
1187 QQmlDataExtended::~QQmlDataExtended()
1191 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1194 layout(endpoint->next);
1196 int index = endpoint->sourceSignal;
1197 index = qMin(index, 0xFFFF - 1);
1199 endpoint->next = notifies[index];
1200 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1201 endpoint->prev = ¬ifies[index];
1202 notifies[index] = endpoint;
1205 void QQmlData::NotifyList::layout()
1207 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1210 QQmlNotifierEndpoint **old = notifies;
1211 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1212 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1213 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1214 sizeof(QQmlNotifierEndpoint*);
1215 memset(notifies + notifiesSize, 0, memsetSize);
1217 if (notifies != old) {
1218 for (int ii = 0; ii < notifiesSize; ++ii)
1220 notifies[ii]->prev = ¬ifies[ii];
1223 notifiesSize = maximumTodoIndex + 1;
1228 maximumTodoIndex = 0;
1232 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1235 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1236 notifyList->connectionMask = 0;
1237 notifyList->maximumTodoIndex = 0;
1238 notifyList->notifiesSize = 0;
1239 notifyList->todo = 0;
1240 notifyList->notifies = 0;
1243 Q_ASSERT(!endpoint->isConnected());
1245 index = qMin(index, 0xFFFF - 1);
1246 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1248 if (index < notifyList->notifiesSize) {
1250 endpoint->next = notifyList->notifies[index];
1251 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1252 endpoint->prev = ¬ifyList->notifies[index];
1253 notifyList->notifies[index] = endpoint;
1256 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1258 endpoint->next = notifyList->todo;
1259 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1260 endpoint->prev = ¬ifyList->todo;
1261 notifyList->todo = endpoint;
1265 bool QQml_isSignalConnected(QObject *obj, int signal_index, int index)
1267 QQmlData *data = QQmlData::get(obj);
1268 return QObjectPrivate::get(obj)->isSignalConnected(signal_index) || (data && data->signalHasEndpoint(index));
1272 index MUST be the index returned by QMetaMethod::index()
1273 This is different than the index returned by QObjectPrivate::signalIndex()
1275 bool QQmlData::signalHasEndpoint(int index)
1277 return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
1280 QHash<int, QObject *> *QQmlData::attachedProperties() const
1282 if (!extendedData) extendedData = new QQmlDataExtended;
1283 return &extendedData->attachedProperties;
1286 void QQmlData::destroyed(QObject *object)
1288 if (nextContextObject)
1289 nextContextObject->prevContextObject = prevContextObject;
1290 if (prevContextObject)
1291 *prevContextObject = nextContextObject;
1293 QQmlAbstractBinding *binding = bindings;
1295 QQmlAbstractBinding *next = binding->nextBinding();
1296 binding->setAddedToObject(false);
1297 binding->setNextBinding(0);
1303 compiledData->release();
1307 QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1308 while (signalHandler) {
1309 if (signalHandler->isEvaluating()) {
1310 // The object is being deleted during signal handler evaluation.
1311 // This will cause a crash due to invalid memory access when the
1312 // evaluation has completed.
1313 // Abort with a friendly message instead.
1314 QString locationString;
1315 QQmlBoundSignalExpression *expr = signalHandler->expression();
1317 QString fileName = expr->sourceFile();
1318 if (fileName.isEmpty())
1319 fileName = QStringLiteral("<Unknown File>");
1320 locationString.append(fileName);
1321 locationString.append(QString::fromLatin1(":%0: ").arg(expr->lineNumber()));
1322 QString source = expr->expression();
1323 if (source.size() > 100) {
1324 source.truncate(96);
1325 source.append(QStringLiteral(" ..."));
1327 locationString.append(source);
1329 locationString = QStringLiteral("<Unknown Location>");
1331 qFatal("Object %p destroyed while one of its QML signal handlers is in progress.\n"
1332 "Most likely the object was deleted synchronously (use QObject::deleteLater() "
1333 "instead), or the application is running a nested event loop.\n"
1334 "This behavior is NOT supported!\n"
1335 "%s", object, qPrintable(locationString));
1338 QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1339 signalHandler->m_prevSignal = 0;
1340 signalHandler->m_nextSignal = 0;
1341 delete signalHandler;
1342 signalHandler = next;
1349 propertyCache->release();
1351 if (ownContext && context)
1355 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1356 *guard = (QObject *)0;
1357 guard->objectDestroyed(object);
1361 while (notifyList->todo)
1362 notifyList->todo->disconnect();
1363 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1364 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1367 free(notifyList->notifies);
1373 delete extendedData;
1375 // Dispose the handle.
1376 // We don't simply clear it (and wait for next gc cycle to dispose
1377 // via the weak qobject reference callback) as this affects the
1378 // outcomes of v8's gc statistical analysis heuristics, which can
1379 // cause unnecessary growth of the old pointer space js heap area.
1380 qPersistentDispose(v8object);
1386 DEFINE_BOOL_CONFIG_OPTION(parentTest, QML_PARENT_TEST);
1388 void QQmlData::parentChanged(QObject *object, QObject *parent)
1391 if (parentFrozen && !QObjectPrivate::get(object)->wasDeleted) {
1395 { QDebug dbg(&on); dbg << object; on = on.left(on.length() - 1); }
1396 { QDebug dbg(&pn); dbg << parent; pn = pn.left(pn.length() - 1); }
1398 qFatal("Object %s has had its parent frozen by QML and cannot be changed.\n"
1399 "User code is attempting to change it to %s.\n"
1400 "This behavior is NOT supported!", qPrintable(on), qPrintable(pn));
1405 bool QQmlData::hasBindingBit(int bit) const
1407 if (bindingBitsSize > bit)
1408 return bindingBits[bit / 32] & (1 << (bit % 32));
1413 void QQmlData::clearBindingBit(int bit)
1415 if (bindingBitsSize > bit)
1416 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1419 void QQmlData::setBindingBit(QObject *obj, int bit)
1421 if (bindingBitsSize <= bit) {
1422 int props = QQmlMetaObject(obj).propertyCount();
1423 Q_ASSERT(bit < props);
1425 int arraySize = (props + 31) / 32;
1426 int oldArraySize = bindingBitsSize / 32;
1428 bindingBits = (quint32 *)realloc(bindingBits,
1429 arraySize * sizeof(quint32));
1431 memset(bindingBits + oldArraySize,
1433 sizeof(quint32) * (arraySize - oldArraySize));
1435 bindingBitsSize = arraySize * 32;
1438 bindingBits[bit / 32] |= (1 << (bit % 32));
1441 void QQmlEnginePrivate::sendQuit()
1445 if (q->receivers(SIGNAL(quit())) == 0) {
1446 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1450 static void dumpwarning(const QQmlError &error)
1452 QMessageLogger(error.url().toString().toLatin1().constData(),
1453 error.line(), 0).warning().nospace()
1454 << qPrintable(error.toString());
1457 static void dumpwarning(const QList<QQmlError> &errors)
1459 for (int ii = 0; ii < errors.count(); ++ii)
1460 dumpwarning(errors.at(ii));
1463 void QQmlEnginePrivate::warning(const QQmlError &error)
1466 q->warnings(QList<QQmlError>() << error);
1467 if (outputWarningsToStdErr)
1471 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1474 q->warnings(errors);
1475 if (outputWarningsToStdErr)
1476 dumpwarning(errors);
1479 void QQmlEnginePrivate::warning(QQmlDelayedError *error)
1482 warning(error->error(q));
1485 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1488 QQmlEnginePrivate::get(engine)->warning(error);
1493 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1496 QQmlEnginePrivate::get(engine)->warning(error);
1501 void QQmlEnginePrivate::warning(QQmlEngine *engine, QQmlDelayedError *error)
1504 QQmlEnginePrivate::get(engine)->warning(error);
1506 dumpwarning(error->error(0));
1509 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1512 engine->warning(error);
1517 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1520 engine->warning(error);
1526 This function should be called prior to evaluation of any js expression,
1527 so that scarce resources are not freed prematurely (eg, if there is a
1528 nested javascript expression).
1530 void QQmlEnginePrivate::referenceScarceResources()
1532 scarceResourcesRefCount += 1;
1536 This function should be called after evaluation of the js expression is
1537 complete, and so the scarce resources may be freed safely.
1539 void QQmlEnginePrivate::dereferenceScarceResources()
1541 Q_ASSERT(scarceResourcesRefCount > 0);
1542 scarceResourcesRefCount -= 1;
1544 // if the refcount is zero, then evaluation of the "top level"
1545 // expression must have completed. We can safely release the
1546 // scarce resources.
1547 if (scarceResourcesRefCount == 0) {
1548 // iterate through the list and release them all.
1549 // note that the actual SRD is owned by the JS engine,
1550 // so we cannot delete the SRD; but we can free the
1551 // memory used by the variant in the SRD.
1552 while (ScarceResourceData *sr = scarceResources.first()) {
1553 sr->data = QVariant();
1554 scarceResources.remove(sr);
1560 Adds \a path as a directory where the engine searches for
1561 installed modules in a URL-based directory structure.
1562 The \a path may be a local filesystem directory or a URL.
1564 The newly added \a path will be first in the importPathList().
1566 \sa setImportPathList(), {QML Modules}
1568 void QQmlEngine::addImportPath(const QString& path)
1571 d->importDatabase.addImportPath(path);
1575 Returns the list of directories where the engine searches for
1576 installed modules in a URL-based directory structure.
1578 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1579 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1580 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1581 provided by that module. A \c qmldir file is required for defining the
1582 type version mapping and possibly QML extensions plugins.
1584 By default, the list contains the directory of the application executable,
1585 paths specified in the \c QML_IMPORT_PATH environment variable,
1586 and the builtin \c ImportsPath from QLibraryInfo.
1588 \sa addImportPath(), setImportPathList()
1590 QStringList QQmlEngine::importPathList() const
1592 Q_D(const QQmlEngine);
1593 return d->importDatabase.importPathList();
1597 Sets \a paths as the list of directories where the engine searches for
1598 installed modules in a URL-based directory structure.
1600 By default, the list contains the directory of the application executable,
1601 paths specified in the \c QML_IMPORT_PATH environment variable,
1602 and the builtin \c ImportsPath from QLibraryInfo.
1604 \sa importPathList(), addImportPath()
1606 void QQmlEngine::setImportPathList(const QStringList &paths)
1609 d->importDatabase.setImportPathList(paths);
1614 Adds \a path as a directory where the engine searches for
1615 native plugins for imported modules (referenced in the \c qmldir file).
1617 By default, the list contains only \c ., i.e. the engine searches
1618 in the directory of the \c qmldir file itself.
1620 The newly added \a path will be first in the pluginPathList().
1622 \sa setPluginPathList()
1624 void QQmlEngine::addPluginPath(const QString& path)
1627 d->importDatabase.addPluginPath(path);
1632 Returns the list of directories where the engine searches for
1633 native plugins for imported modules (referenced in the \c qmldir file).
1635 By default, the list contains only \c ., i.e. the engine searches
1636 in the directory of the \c qmldir file itself.
1638 \sa addPluginPath(), setPluginPathList()
1640 QStringList QQmlEngine::pluginPathList() const
1642 Q_D(const QQmlEngine);
1643 return d->importDatabase.pluginPathList();
1647 Sets the list of directories where the engine searches for
1648 native plugins for imported modules (referenced in the \c qmldir file)
1651 By default, the list contains only \c ., i.e. the engine searches
1652 in the directory of the \c qmldir file itself.
1654 \sa pluginPathList(), addPluginPath()
1656 void QQmlEngine::setPluginPathList(const QStringList &paths)
1659 d->importDatabase.setPluginPathList(paths);
1663 Imports the plugin named \a filePath with the \a uri provided.
1664 Returns true if the plugin was successfully imported; otherwise returns false.
1666 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1668 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1670 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1673 return d->importDatabase.importPlugin(filePath, uri, errors);
1677 \property QQmlEngine::offlineStoragePath
1678 \brief the directory for storing offline user data
1680 Returns the directory where SQL and other offline
1683 QQuickWebView and the SQL databases created with openDatabase()
1686 The default is QML/OfflineStorage in the platform-standard
1687 user application data directory.
1689 Note that the path may not currently exist on the filesystem, so
1690 callers wanting to \e create new files at this location should create
1691 it first - see QDir::mkpath().
1693 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1696 d->offlineStoragePath = dir;
1699 QString QQmlEngine::offlineStoragePath() const
1701 Q_D(const QQmlEngine);
1702 return d->offlineStoragePath;
1705 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1709 if (!mo->superClass()) {
1710 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1711 propertyCache.insert(mo, rv);
1714 QQmlPropertyCache *super = cache(mo->superClass());
1715 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1716 propertyCache.insert(mo, rv);
1721 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1724 QList<QQmlType *> types;
1726 int maxMinorVersion = 0;
1728 const QMetaObject *metaObject = type->metaObject();
1730 while (metaObject) {
1731 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1732 type->majorVersion(), minorVersion);
1734 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1740 metaObject = metaObject->superClass();
1743 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1745 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1749 QQmlPropertyCache *raw = cache(type->metaObject());
1751 bool hasCopied = false;
1753 for (int ii = 0; ii < types.count(); ++ii) {
1754 QQmlType *currentType = types.at(ii);
1758 int rev = currentType->metaObjectRevision();
1759 int moIndex = types.count() - 1 - ii;
1761 if (raw->allowedRevisionCache[moIndex] != rev) {
1766 raw->allowedRevisionCache[moIndex] = rev;
1770 // Test revision compatibility - the basic rule is:
1771 // * Anything that is excluded, cannot overload something that is not excluded *
1773 // Signals override:
1774 // * other signals and methods of the same name.
1775 // * properties named on<Signal Name>
1776 // * automatic <property name>Changed notify signals
1778 // Methods override:
1779 // * other methods of the same name
1781 // Properties override:
1782 // * other elements of the same name
1784 bool overloadError = false;
1785 QString overloadName;
1788 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1789 !overloadError && iter != raw->stringCache.end();
1792 QQmlPropertyData *d = *iter;
1793 if (raw->isAllowedInRevision(d))
1794 continue; // Not excluded - no problems
1796 // check that a regular "name" overload isn't happening
1797 QQmlPropertyData *current = d;
1798 while (!overloadError && current) {
1799 current = d->overrideData(current);
1800 if (current && raw->isAllowedInRevision(current))
1801 overloadError = true;
1806 if (overloadError) {
1807 if (hasCopied) raw->release();
1809 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."));
1813 if (!hasCopied) raw->addref();
1814 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1816 if (minorVersion != maxMinorVersion) {
1818 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1824 QQmlMetaType::ModuleApiInstance *
1825 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1827 Locker locker(this);
1829 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1831 a = new QQmlMetaType::ModuleApiInstance;
1832 a->scriptCallback = module.script;
1833 a->qobjectCallback = module.qobject;
1834 a->instanceMetaObject = module.instanceMetaObject;
1835 moduleApiInstances.insert(module, a);
1841 bool QQmlEnginePrivate::isQObject(int t)
1843 Locker locker(this);
1844 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1847 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1849 Locker locker(this);
1850 int t = v.userType();
1851 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1853 return *(QObject **)(v.constData());
1855 return QQmlMetaType::toQObject(v, ok);
1859 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1861 Locker locker(this);
1862 if (m_compositeTypes.contains(t))
1863 return QQmlMetaType::Object;
1864 else if (m_qmlLists.contains(t))
1865 return QQmlMetaType::List;
1867 return QQmlMetaType::typeCategory(t);
1870 bool QQmlEnginePrivate::isList(int t) const
1872 Locker locker(this);
1873 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1876 int QQmlEnginePrivate::listType(int t) const
1878 Locker locker(this);
1879 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1880 if (iter != m_qmlLists.end())
1883 return QQmlMetaType::listType(t);
1886 QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
1888 Locker locker(this);
1889 QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1890 if (iter != m_compositeTypes.end()) {
1891 return QQmlMetaObject((*iter)->rootPropertyCache);
1893 QQmlType *type = QQmlMetaType::qmlType(t);
1894 return QQmlMetaObject(type?type->baseMetaObject():0);
1898 QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
1900 Locker locker(this);
1901 QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1902 if (iter != m_compositeTypes.end()) {
1903 return QQmlMetaObject((*iter)->rootPropertyCache);
1905 QQmlType *type = QQmlMetaType::qmlType(t);
1906 return QQmlMetaObject(type?type->metaObject():0);
1910 QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
1912 Locker locker(this);
1913 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1914 if (iter != m_compositeTypes.end()) {
1915 return (*iter)->rootPropertyCache;
1917 QQmlType *type = QQmlMetaType::qmlType(t);
1919 return type?cache(type->metaObject()):0;
1923 QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t)
1925 Locker locker(this);
1926 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1927 if (iter != m_compositeTypes.end()) {
1928 return (*iter)->rootPropertyCache;
1930 QQmlType *type = QQmlMetaType::qmlType(t);
1932 return type?cache(type->baseMetaObject()):0;
1936 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1938 QByteArray name = data->rootPropertyCache->className();
1940 QByteArray ptr = name + '*';
1941 QByteArray lst = "QQmlListProperty<" + name + '>';
1943 int ptr_type = QMetaType::registerNormalizedType(ptr,
1944 qMetaTypeDeleteHelper<QObject*>,
1945 qMetaTypeCreateHelper<QObject*>,
1946 qMetaTypeDestructHelper<QObject*>,
1947 qMetaTypeConstructHelper<QObject*>,
1949 static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QObject*>::Flags),
1951 int lst_type = QMetaType::registerNormalizedType(lst,
1952 qMetaTypeDeleteHelper<QQmlListProperty<QObject> >,
1953 qMetaTypeCreateHelper<QQmlListProperty<QObject> >,
1954 qMetaTypeDestructHelper<QQmlListProperty<QObject> >,
1955 qMetaTypeConstructHelper<QQmlListProperty<QObject> >,
1956 sizeof(QQmlListProperty<QObject>),
1957 static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<QObject> >::Flags),
1958 static_cast<QMetaObject*>(0));
1960 data->metaTypeId = ptr_type;
1961 data->listMetaTypeId = lst_type;
1962 data->isRegisteredWithEngine = true;
1964 Locker locker(this);
1965 m_qmlLists.insert(lst_type, ptr_type);
1966 // The QQmlCompiledData is not referenced here, but it is removed from this
1967 // hash in the QQmlCompiledData destructor
1968 m_compositeTypes.insert(ptr_type, data);
1971 void QQmlEnginePrivate::unregisterCompositeType(QQmlCompiledData *data)
1973 int ptr_type = data->metaTypeId;
1974 int lst_type = data->listMetaTypeId;
1976 Locker locker(this);
1977 m_qmlLists.remove(lst_type);
1978 m_compositeTypes.remove(ptr_type);
1981 bool QQmlEnginePrivate::isTypeLoaded(const QUrl &url) const
1983 return typeLoader.isTypeLoaded(url);
1986 bool QQmlEnginePrivate::isScriptLoaded(const QUrl &url) const
1988 return typeLoader.isScriptLoaded(url);
1991 bool QQml_isFileCaseCorrect(const QString &fileName)
1993 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1994 QFileInfo info(fileName);
1995 const QString absolute = info.absoluteFilePath();
1997 #if defined(Q_OS_MAC)
1998 const QString canonical = info.canonicalFilePath();
1999 #elif defined(Q_OS_WIN)
2000 wchar_t buffer[1024];
2002 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
2003 if (rv == 0 || rv >= 1024) return true;
2004 rv = ::GetLongPathName(buffer, buffer, 1024);
2005 if (rv == 0 || rv >= 1024) return true;
2007 const QString canonical = QString::fromWCharArray(buffer);
2010 const int absoluteLength = absolute.length();
2011 const int canonicalLength = canonical.length();
2013 const int length = qMin(absoluteLength, canonicalLength);
2014 for (int ii = 0; ii < length; ++ii) {
2015 const QChar &a = absolute.at(absoluteLength - 1 - ii);
2016 const QChar &c = canonical.at(canonicalLength - 1 - ii);
2018 if (a.toLower() != c.toLower())
2030 \fn QQmlEngine *qmlEngine(const QObject *object)
2033 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
2034 QQmlEngine::contextForObject(object)->engine(), but more efficient.
2038 \fn QQmlContext *qmlContext(const QObject *object)
2041 Returns the QQmlContext associated with \a object, if any. This is equivalent to
2042 QQmlEngine::contextForObject(object).