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
357 The following example uses the \c application object to indicate
358 whether the application is currently active:
360 \snippet doc/snippets/qml/application.qml document
362 \qmlproperty object Qt::inputMethod
365 The \c inputMethod object allows access to application's QInputMethod object
366 and all its properties and slots. See the QInputMethod documentation for
372 \qmlmethod object Qt::include(string url, jsobject callback)
374 Includes another JavaScript file. This method can only be used from within JavaScript files,
375 and not regular QML files.
377 This imports all functions from \a url into the current script's namespace.
379 Qt.include() returns an object that describes the status of the operation. The object has
380 a single property, \c {status}, that is set to one of the following values:
383 \header \li Symbol \li Value \li Description
384 \row \li result.OK \li 0 \li The include completed successfully.
385 \row \li result.LOADING \li 1 \li Data is being loaded from the network.
386 \row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
387 \row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
388 An additional \c exception property will be set in this case.
391 The \c status property will be updated as the operation progresses.
393 If provided, \a callback is invoked when the operation completes. The callback is passed
394 the same object as is returned from the Qt.include() call.
396 // Qt.include() is implemented in qv8include.cpp
399 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
400 : propertyCapture(0), rootContext(0), isDebugging(false),
401 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
402 cleanup(0), erroredBindings(0), inProgressCreations(0),
403 workerScriptEngine(0), activeVME(0),
404 networkAccessManager(0), networkAccessManagerFactory(0),
405 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
406 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
410 QQmlEnginePrivate::~QQmlEnginePrivate()
412 if (inProgressCreations)
413 qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
416 QQmlCleanup *c = cleanup;
418 if (cleanup) cleanup->prev = &cleanup;
424 doDeleteInEngineThread();
426 if (incubationController) incubationController->d = 0;
427 incubationController = 0;
432 for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
434 for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
436 for(QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
437 delete (*iter)->qobjectApi;
442 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
444 QObjectPrivate *p = QObjectPrivate::get(o);
445 if (p->declarativeData) {
446 QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
447 if (d->ownContext && d->context) {
448 d->context->destroy();
452 // Mark this object as in the process of deletion to
453 // prevent it resolving in bindings
454 QQmlData::markAsDeleted(o);
458 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
460 static_cast<QQmlData *>(d)->destroyed(o);
463 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
465 static_cast<QQmlData *>(d)->parentChanged(o, p);
468 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **a)
470 QQmlData *ddata = QQmlData::get(object, false);
471 if (!ddata) return; // Probably being deleted
473 // In general, QML only supports QObject's that live on the same thread as the QQmlEngine
474 // that they're exposed to. However, to make writing "worker objects" that calculate data
475 // in a separate thread easier, QML allows a QObject that lives in the same thread as the
476 // QQmlEngine to emit signals from a different thread. These signals are then automatically
477 // marshalled back onto the QObject's thread and handled by QML from there. This is tested
478 // by the qqmlecmascript::threadSignal() autotest.
479 if (ddata->notifyList &&
480 QThread::currentThreadId() != QObjectPrivate::get(object)->threadData->threadId) {
482 QMetaMethod m = object->metaObject()->method(index);
483 QList<QByteArray> parameterTypes = m.parameterTypes();
485 int *types = (int *)malloc((parameterTypes.count() + 1) * sizeof(int));
486 void **args = (void **) malloc((parameterTypes.count() + 1) *sizeof(void *));
488 types[0] = 0; // return type
489 args[0] = 0; // return value
491 for (int ii = 0; ii < parameterTypes.count(); ++ii) {
492 const QByteArray &typeName = parameterTypes.at(ii);
493 if (typeName.endsWith('*'))
494 types[ii + 1] = QMetaType::VoidStar;
496 types[ii + 1] = QMetaType::type(typeName);
498 if (!types[ii + 1]) {
499 qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
500 "(Make sure '%s' is registered using qRegisterMetaType().)",
501 typeName.constData(), typeName.constData());
507 args[ii + 1] = QMetaType::create(types[ii + 1], a[ii + 1]);
510 QMetaCallEvent *ev = new QMetaCallEvent(index, 0, 0, object, index,
511 parameterTypes.count() + 1, types, args);
512 QCoreApplication::postEvent(object, ev);
515 QQmlNotifierEndpoint *ep = ddata->notify(index);
516 if (ep) QQmlNotifier::emitNotify(ep, a);
520 int QQmlData::receivers(QAbstractDeclarativeData *d, const QObject *, int index)
522 return static_cast<QQmlData *>(d)->endpointCount(index);
525 int QQmlData::endpointCount(int index)
528 QQmlNotifierEndpoint *ep = notify(index);
539 void QQmlData::markAsDeleted(QObject *o)
541 QQmlData::setQueuedForDeletion(o);
543 QObjectPrivate *p = QObjectPrivate::get(o);
544 for (QList<QObject *>::iterator it = p->children.begin(), end = p->children.end(); it != end; ++it) {
545 QQmlData::markAsDeleted(*it);
549 void QQmlData::setQueuedForDeletion(QObject *object)
552 if (QObjectPrivate *priv = QObjectPrivate::get(object)) {
553 if (!priv->wasDeleted && priv->declarativeData) {
554 QQmlData *ddata = QQmlData::get(object, false);
555 if (ddata->ownContext && ddata->context)
556 ddata->context->emitDestruction();
557 ddata->isQueuedForDeletion = true;
563 void QQmlEnginePrivate::init()
567 static bool firstTime = true;
569 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component");
575 qRegisterMetaType<QVariant>("QVariant");
576 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
577 qRegisterMetaType<QJSValue>("QJSValue");
578 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
579 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
580 qRegisterMetaType<QList<int> >("QList<int>");
581 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
583 v8engine()->setEngine(q);
585 rootContext = new QQmlContext(q,true);
587 if (QCoreApplication::instance()->thread() == q->thread() &&
588 QQmlEngineDebugService::isDebuggingEnabled()) {
590 QQmlEngineDebugService::instance()->addEngine(q);
591 QV8DebugService::initialize(v8engine());
592 QV8ProfilerService::initialize();
593 QQmlProfilerService::initialize();
594 QDebugMessageService::instance();
597 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
598 if (!dataLocation.isEmpty())
599 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator())
600 + QDir::separator() + QLatin1String("QML")
601 + QDir::separator() + QLatin1String("OfflineStorage");
604 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
607 if (!workerScriptEngine)
608 workerScriptEngine = new QQuickWorkerScriptEngine(q);
609 return workerScriptEngine;
616 \brief The QQmlEngine class provides an environment for instantiating QML components.
619 Each QML component is instantiated in a QQmlContext.
620 QQmlContext's are essential for passing data to QML
621 components. In QML, contexts are arranged hierarchically and this
622 hierarchy is managed by the QQmlEngine.
624 Prior to creating any QML components, an application must have
625 created a QQmlEngine to gain access to a QML context. The
626 following example shows how to create a simple Text item.
630 QQmlComponent component(&engine);
631 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
632 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
634 //add item to view, etc
638 In this case, the Text item will be created in the engine's
639 \l {QQmlEngine::rootContext()}{root context}.
641 Note that the QtQuick 1 version is called QDeclarativeEngine.
643 \sa QQmlComponent, QQmlContext
647 Create a new QQmlEngine with the given \a parent.
649 QQmlEngine::QQmlEngine(QObject *parent)
650 : QJSEngine(*new QQmlEnginePrivate(this), parent)
657 Destroys the QQmlEngine.
659 Any QQmlContext's created on this engine will be
660 invalidated, but not destroyed (unless they are parented to the
663 QQmlEngine::~QQmlEngine()
666 if (d->isDebugging) {
667 QQmlEngineDebugService::instance()->remEngine(this);
670 // Emit onDestruction signals for the root context before
671 // we destroy the contexts, engine, Module APIs etc. that
672 // may be required to handle the destruction signal.
673 QQmlContextData::get(rootContext())->emitDestruction();
675 // if we are the parent of any of the qobject module api instances,
676 // we need to remove them from our internal list, in order to prevent
677 // a segfault in engine private dtor.
678 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
679 QObject *currQObjectApi = 0;
680 QQmlMetaType::ModuleApiInstance *currInstance = 0;
681 foreach (const QQmlMetaType::ModuleApi &key, keys) {
682 currInstance = d->moduleApiInstances.value(key);
683 currQObjectApi = currInstance->qobjectApi;
684 if (this->children().contains(currQObjectApi)) {
685 delete currQObjectApi;
687 d->moduleApiInstances.remove(key);
691 if (d->incubationController)
692 d->incubationController->d = 0;
695 /*! \fn void QQmlEngine::quit()
696 This signal is emitted when the QML loaded by the engine would like to quit.
699 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
700 This signal is emitted when \a warnings messages are generated by QML.
704 Clears the engine's internal component cache.
706 This function causes the property metadata of all components previously
707 loaded by the engine to be destroyed. All previously loaded components and
708 the property bindings for all extant objects created from those components will
711 This function returns the engine to a state where it does not contain any loaded
712 component data. This may be useful in order to reload a smaller subset of the
713 previous component set, or to load a new version of a previously loaded component.
715 Once the component cache has been cleared, components must be loaded before
716 any new objects can be created.
718 \sa trimComponentCache()
720 void QQmlEngine::clearComponentCache()
727 Trims the engine's internal component cache.
729 This function causes the property metadata of any loaded components which are
730 not currently in use to be destroyed.
732 A component is considered to be in use if there are any extant instances of
733 the component itself, any instances of other components that use the component,
734 or any objects instantiated by any of those components.
736 \sa clearComponentCache()
738 void QQmlEngine::trimComponentCache()
745 Returns the engine's root context.
747 The root context is automatically created by the QQmlEngine.
748 Data that should be available to all QML component instances
749 instantiated by the engine should be put in the root context.
751 Additional data that should only be available to a subset of
752 component instances should be added to sub-contexts parented to the
755 QQmlContext *QQmlEngine::rootContext() const
757 Q_D(const QQmlEngine);
758 return d->rootContext;
762 Sets the \a factory to use for creating QNetworkAccessManager(s).
764 QNetworkAccessManager is used for all network access by QML. By
765 implementing a factory it is possible to create custom
766 QNetworkAccessManager with specialized caching, proxy and cookie
769 The factory must be set before executing the engine.
771 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
774 QMutexLocker locker(&d->mutex);
775 d->networkAccessManagerFactory = factory;
779 Returns the current QQmlNetworkAccessManagerFactory.
781 \sa setNetworkAccessManagerFactory()
783 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
785 Q_D(const QQmlEngine);
786 return d->networkAccessManagerFactory;
789 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
792 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
794 void *args[] = { 0 };
795 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
799 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
801 QMutexLocker locker(&mutex);
802 QNetworkAccessManager *nam;
803 if (networkAccessManagerFactory) {
804 nam = networkAccessManagerFactory->create(parent);
806 nam = new QNetworkAccessManager(parent);
812 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
814 Q_Q(const QQmlEngine);
815 if (!networkAccessManager)
816 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
817 return networkAccessManager;
821 Returns a common QNetworkAccessManager which can be used by any QML
822 element instantiated by this engine.
824 If a QQmlNetworkAccessManagerFactory has been set and a
825 QNetworkAccessManager has not yet been created, the
826 QQmlNetworkAccessManagerFactory will be used to create the
827 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
828 will have no proxy or cache set.
830 \sa setNetworkAccessManagerFactory()
832 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
834 Q_D(const QQmlEngine);
835 return d->getNetworkAccessManager();
840 Sets the \a provider to use for images requested via the \e
841 image: url scheme, with host \a providerId. The QQmlEngine
842 takes ownership of \a provider.
844 Image providers enable support for pixmap and threaded image
845 requests. See the QQuickImageProvider documentation for details on
846 implementing and using image providers.
848 All required image providers should be added to the engine before any
849 QML sources files are loaded.
851 \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
853 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
856 QMutexLocker locker(&d->mutex);
857 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
861 Returns the image provider set for \a providerId.
863 Returns the provider if it was found; otherwise returns 0.
865 \sa QQuickImageProvider
867 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
869 Q_D(const QQmlEngine);
870 QMutexLocker locker(&d->mutex);
871 return d->imageProviders.value(providerId).data();
875 Removes the image provider for \a providerId.
877 \sa addImageProvider(), QQuickImageProvider
879 void QQmlEngine::removeImageProvider(const QString &providerId)
882 QMutexLocker locker(&d->mutex);
883 d->imageProviders.take(providerId);
887 Return the base URL for this engine. The base URL is only used to
888 resolve components when a relative URL is passed to the
889 QQmlComponent constructor.
891 If a base URL has not been explicitly set, this method returns the
892 application's current working directory.
896 QUrl QQmlEngine::baseUrl() const
898 Q_D(const QQmlEngine);
899 if (d->baseUrl.isEmpty()) {
900 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
907 Set the base URL for this engine to \a url.
911 void QQmlEngine::setBaseUrl(const QUrl &url)
918 Returns true if warning messages will be output to stderr in addition
919 to being emitted by the warnings() signal, otherwise false.
921 The default value is true.
923 bool QQmlEngine::outputWarningsToStandardError() const
925 Q_D(const QQmlEngine);
926 return d->outputWarningsToStdErr;
930 Set whether warning messages will be output to stderr to \a enabled.
932 If \a enabled is true, any warning messages generated by QML will be
933 output to stderr and emitted by the warnings() signal. If \a enabled
934 is false, on the warnings() signal will be emitted. This allows
935 applications to handle warning output themselves.
937 The default value is true.
939 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
942 d->outputWarningsToStdErr = enabled;
946 Attempt to free unused memory.
948 void QQmlEngine::collectGarbage()
954 Returns the QQmlContext for the \a object, or 0 if no
955 context has been set.
957 When the QQmlEngine instantiates a QObject, the context is
960 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
965 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
968 static_cast<QQmlData *>(priv->declarativeData);
972 else if (data->outerContext)
973 return data->outerContext->asQQmlContext();
979 Sets the QQmlContext for the \a object to \a context.
980 If the \a object already has a context, a warning is
981 output, but the context is not changed.
983 When the QQmlEngine instantiates a QObject, the context is
986 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
988 if (!object || !context)
991 QQmlData *data = QQmlData::get(object, true);
993 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
997 QQmlContextData *contextData = QQmlContextData::get(context);
998 contextData->addObject(object);
1002 \enum QQmlEngine::ObjectOwnership
1004 Ownership controls whether or not QML automatically destroys the
1005 QObject when the object is garbage collected by the JavaScript
1006 engine. The two ownership options are:
1008 \value CppOwnership The object is owned by C++ code, and will
1009 never be deleted by QML. The JavaScript destroy() method cannot be
1010 used on objects with CppOwnership. This option is similar to
1011 QScriptEngine::QtOwnership.
1013 \value JavaScriptOwnership The object is owned by JavaScript.
1014 When the object is returned to QML as the return value of a method
1015 call or property access, QML will track it, and delete the object
1016 if there are no remaining JavaScript references to it and it has no
1017 QObject::parent(). An object tracked by one QQmlEngine
1018 will be deleted during that QQmlEngine's destructor, and thus
1019 JavaScript references between objects with JavaScriptOwnership from
1020 two different engines will not be valid after the deletion of one of
1021 those engines. This option is similar to QScriptEngine::ScriptOwnership.
1023 Generally an application doesn't need to set an object's ownership
1024 explicitly. QML uses a heuristic to set the default object
1025 ownership. By default, an object that is created by QML has
1026 JavaScriptOwnership. The exception to this are the root objects
1027 created by calling QQmlComponent::create() or
1028 QQmlComponent::beginCreate() which have CppOwnership by
1029 default. The ownership of these root-level objects is considered to
1030 have been transferred to the C++ caller.
1032 Objects not-created by QML have CppOwnership by default. The
1033 exception to this is objects returned from a C++ method call. The
1034 ownership of these objects is passed to JavaScript.
1036 Calling setObjectOwnership() overrides the default ownership
1037 heuristic used by QML.
1041 Sets the \a ownership of \a object.
1043 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
1048 QQmlData *ddata = QQmlData::get(object, true);
1052 ddata->indestructible = (ownership == CppOwnership)?true:false;
1053 ddata->explicitIndestructibleSet = true;
1057 Returns the ownership of \a object.
1059 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
1062 return CppOwnership;
1064 QQmlData *ddata = QQmlData::get(object, false);
1066 return CppOwnership;
1068 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
1071 bool QQmlEngine::event(QEvent *e)
1074 if (e->type() == QEvent::User)
1075 d->doDeleteInEngineThread();
1077 return QJSEngine::event(e);
1080 void QQmlEnginePrivate::doDeleteInEngineThread()
1082 QFieldList<Deletable, &Deletable::next> list;
1084 list.copyAndClear(toDeleteInEngineThread);
1087 while (Deletable *d = list.takeFirst())
1091 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
1093 QQmlData *data = QQmlData::get(object);
1095 if (data && data->compiledData && data->deferredIdx) {
1096 QQmlObjectCreatingProfiler prof;
1098 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
1099 prof.setTypeName(type ? type->qmlTypeName()
1100 : QString::fromUtf8(object->metaObject()->className()));
1101 if (data->outerContext)
1102 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
1104 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
1106 QQmlComponentPrivate::ConstructionState state;
1107 QQmlComponentPrivate::beginDeferred(ep, object, &state);
1109 // Release the reference for the deferral action (we still have one from construction)
1110 data->compiledData->release();
1111 data->compiledData = 0;
1113 QQmlComponentPrivate::complete(ep, &state);
1117 QQmlContext *qmlContext(const QObject *obj)
1119 return QQmlEngine::contextForObject(obj);
1122 QQmlEngine *qmlEngine(const QObject *obj)
1124 QQmlData *data = QQmlData::get(obj, false);
1125 if (!data || !data->context)
1127 return data->context->engine;
1130 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1132 QQmlData *data = QQmlData::get(object);
1134 return 0; // Attached properties are only on objects created by QML
1136 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1140 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1144 rv = pf(const_cast<QObject *>(object));
1147 data->attachedProperties()->insert(id, rv);
1152 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1153 const QMetaObject *attachedMetaObject, bool create)
1156 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1158 if (*idCache == -1 || !object)
1161 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1164 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1166 #ifndef QQML_NO_DEBUG_PROTOCOL
1167 if (!QQmlEnginePrivate::qml_debugging_enabled
1169 qDebug("QML debugging is enabled. Only use this in a safe environment.");
1171 QQmlEnginePrivate::qml_debugging_enabled = true;
1176 class QQmlDataExtended {
1179 ~QQmlDataExtended();
1181 QHash<int, QObject *> attachedProperties;
1184 QQmlDataExtended::QQmlDataExtended()
1188 QQmlDataExtended::~QQmlDataExtended()
1192 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1195 layout(endpoint->next);
1197 int index = endpoint->sourceSignal;
1198 index = qMin(index, 0xFFFF - 1);
1200 endpoint->next = notifies[index];
1201 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1202 endpoint->prev = ¬ifies[index];
1203 notifies[index] = endpoint;
1206 void QQmlData::NotifyList::layout()
1208 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1211 QQmlNotifierEndpoint **old = notifies;
1212 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1213 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1214 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1215 sizeof(QQmlNotifierEndpoint*);
1216 memset(notifies + notifiesSize, 0, memsetSize);
1218 if (notifies != old) {
1219 for (int ii = 0; ii < notifiesSize; ++ii)
1221 notifies[ii]->prev = ¬ifies[ii];
1224 notifiesSize = maximumTodoIndex + 1;
1229 maximumTodoIndex = 0;
1233 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1236 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1237 notifyList->connectionMask = 0;
1238 notifyList->maximumTodoIndex = 0;
1239 notifyList->notifiesSize = 0;
1240 notifyList->todo = 0;
1241 notifyList->notifies = 0;
1244 Q_ASSERT(!endpoint->isConnected());
1246 index = qMin(index, 0xFFFF - 1);
1247 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1249 if (index < notifyList->notifiesSize) {
1251 endpoint->next = notifyList->notifies[index];
1252 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1253 endpoint->prev = ¬ifyList->notifies[index];
1254 notifyList->notifies[index] = endpoint;
1257 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1259 endpoint->next = notifyList->todo;
1260 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1261 endpoint->prev = ¬ifyList->todo;
1262 notifyList->todo = endpoint;
1266 bool QQml_isSignalConnected(QObject *obj, int signal_index, int index)
1268 QQmlData *data = QQmlData::get(obj);
1269 return QObjectPrivate::get(obj)->isSignalConnected(signal_index) || (data && data->signalHasEndpoint(index));
1273 index MUST be the index returned by QMetaMethod::index()
1274 This is different than the index returned by QObjectPrivate::signalIndex()
1276 bool QQmlData::signalHasEndpoint(int index)
1278 return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
1281 QHash<int, QObject *> *QQmlData::attachedProperties() const
1283 if (!extendedData) extendedData = new QQmlDataExtended;
1284 return &extendedData->attachedProperties;
1287 void QQmlData::destroyed(QObject *object)
1289 if (nextContextObject)
1290 nextContextObject->prevContextObject = prevContextObject;
1291 if (prevContextObject)
1292 *prevContextObject = nextContextObject;
1294 QQmlAbstractBinding *binding = bindings;
1296 QQmlAbstractBinding *next = binding->m_nextBinding;
1297 binding->m_prevBinding = 0;
1298 binding->m_nextBinding = 0;
1304 compiledData->release();
1308 QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1309 while (signalHandler) {
1310 QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1311 signalHandler->m_prevSignal = 0;
1312 signalHandler->m_nextSignal = 0;
1313 delete signalHandler;
1314 signalHandler = next;
1321 propertyCache->release();
1323 if (ownContext && context)
1327 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1328 *guard = (QObject *)0;
1329 guard->objectDestroyed(object);
1333 while (notifyList->todo)
1334 notifyList->todo->disconnect();
1335 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1336 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1339 free(notifyList->notifies);
1345 delete extendedData;
1347 // Dispose the handle.
1348 // We don't simply clear it (and wait for next gc cycle to dispose
1349 // via the weak qobject reference callback) as this affects the
1350 // outcomes of v8's gc statistical analysis heuristics, which can
1351 // cause unnecessary growth of the old pointer space js heap area.
1352 qPersistentDispose(v8object);
1358 void QQmlData::parentChanged(QObject *object, QObject *parent)
1364 bool QQmlData::hasBindingBit(int bit) const
1366 if (bindingBitsSize > bit)
1367 return bindingBits[bit / 32] & (1 << (bit % 32));
1372 void QQmlData::clearBindingBit(int bit)
1374 if (bindingBitsSize > bit)
1375 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1378 void QQmlData::setBindingBit(QObject *obj, int bit)
1380 if (bindingBitsSize <= bit) {
1381 int props = obj->metaObject()->propertyCount();
1382 Q_ASSERT(bit < props);
1384 int arraySize = (props + 31) / 32;
1385 int oldArraySize = bindingBitsSize / 32;
1387 bindingBits = (quint32 *)realloc(bindingBits,
1388 arraySize * sizeof(quint32));
1390 memset(bindingBits + oldArraySize,
1392 sizeof(quint32) * (arraySize - oldArraySize));
1394 bindingBitsSize = arraySize * 32;
1397 bindingBits[bit / 32] |= (1 << (bit % 32));
1400 void QQmlEnginePrivate::sendQuit()
1404 if (q->receivers(SIGNAL(quit())) == 0) {
1405 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1409 static void dumpwarning(const QQmlError &error)
1411 QMessageLogger(error.url().toString().toLatin1().constData(),
1412 error.line(), 0).warning().nospace()
1413 << qPrintable(error.toString());
1416 static void dumpwarning(const QList<QQmlError> &errors)
1418 for (int ii = 0; ii < errors.count(); ++ii)
1419 dumpwarning(errors.at(ii));
1422 void QQmlEnginePrivate::warning(const QQmlError &error)
1425 q->warnings(QList<QQmlError>() << error);
1426 if (outputWarningsToStdErr)
1430 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1433 q->warnings(errors);
1434 if (outputWarningsToStdErr)
1435 dumpwarning(errors);
1438 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1441 QQmlEnginePrivate::get(engine)->warning(error);
1446 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1449 QQmlEnginePrivate::get(engine)->warning(error);
1454 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1457 engine->warning(error);
1462 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1465 engine->warning(error);
1471 This function should be called prior to evaluation of any js expression,
1472 so that scarce resources are not freed prematurely (eg, if there is a
1473 nested javascript expression).
1475 void QQmlEnginePrivate::referenceScarceResources()
1477 scarceResourcesRefCount += 1;
1481 This function should be called after evaluation of the js expression is
1482 complete, and so the scarce resources may be freed safely.
1484 void QQmlEnginePrivate::dereferenceScarceResources()
1486 Q_ASSERT(scarceResourcesRefCount > 0);
1487 scarceResourcesRefCount -= 1;
1489 // if the refcount is zero, then evaluation of the "top level"
1490 // expression must have completed. We can safely release the
1491 // scarce resources.
1492 if (scarceResourcesRefCount == 0) {
1493 // iterate through the list and release them all.
1494 // note that the actual SRD is owned by the JS engine,
1495 // so we cannot delete the SRD; but we can free the
1496 // memory used by the variant in the SRD.
1497 while (ScarceResourceData *sr = scarceResources.first()) {
1498 sr->data = QVariant();
1499 scarceResources.remove(sr);
1505 Adds \a path as a directory where the engine searches for
1506 installed modules in a URL-based directory structure.
1507 The \a path may be a local filesystem directory or a URL.
1509 The newly added \a path will be first in the importPathList().
1511 \sa setImportPathList(), {QML Modules}
1513 void QQmlEngine::addImportPath(const QString& path)
1516 d->importDatabase.addImportPath(path);
1520 Returns the list of directories where the engine searches for
1521 installed modules in a URL-based directory structure.
1523 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1524 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1525 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1526 provided by that module. A \c qmldir file is required for defining the
1527 type version mapping and possibly QML extensions plugins.
1529 By default, the list contains the directory of the application executable,
1530 paths specified in the \c QML_IMPORT_PATH environment variable,
1531 and the builtin \c ImportsPath from QLibraryInfo.
1533 \sa addImportPath(), setImportPathList()
1535 QStringList QQmlEngine::importPathList() const
1537 Q_D(const QQmlEngine);
1538 return d->importDatabase.importPathList();
1542 Sets \a paths as the list of directories where the engine searches for
1543 installed modules in a URL-based directory structure.
1545 By default, the list contains the directory of the application executable,
1546 paths specified in the \c QML_IMPORT_PATH environment variable,
1547 and the builtin \c ImportsPath from QLibraryInfo.
1549 \sa importPathList(), addImportPath()
1551 void QQmlEngine::setImportPathList(const QStringList &paths)
1554 d->importDatabase.setImportPathList(paths);
1559 Adds \a path as a directory where the engine searches for
1560 native plugins for imported modules (referenced in the \c qmldir file).
1562 By default, the list contains only \c ., i.e. the engine searches
1563 in the directory of the \c qmldir file itself.
1565 The newly added \a path will be first in the pluginPathList().
1567 \sa setPluginPathList()
1569 void QQmlEngine::addPluginPath(const QString& path)
1572 d->importDatabase.addPluginPath(path);
1577 Returns the list of directories where the engine searches for
1578 native plugins for imported modules (referenced in the \c qmldir file).
1580 By default, the list contains only \c ., i.e. the engine searches
1581 in the directory of the \c qmldir file itself.
1583 \sa addPluginPath(), setPluginPathList()
1585 QStringList QQmlEngine::pluginPathList() const
1587 Q_D(const QQmlEngine);
1588 return d->importDatabase.pluginPathList();
1592 Sets the list of directories where the engine searches for
1593 native plugins for imported modules (referenced in the \c qmldir file)
1596 By default, the list contains only \c ., i.e. the engine searches
1597 in the directory of the \c qmldir file itself.
1599 \sa pluginPathList(), addPluginPath()
1601 void QQmlEngine::setPluginPathList(const QStringList &paths)
1604 d->importDatabase.setPluginPathList(paths);
1608 Imports the plugin named \a filePath with the \a uri provided.
1609 Returns true if the plugin was successfully imported; otherwise returns false.
1611 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1613 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1615 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1618 return d->importDatabase.importPlugin(filePath, uri, errors);
1622 Imports the plugin named \a filePath with the \a uri provided.
1623 Returns true if the plugin was successfully imported; otherwise returns false.
1625 On failure and if non-null, *\a errorString will be set to a message describing the failure.
1627 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1629 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1632 QList<QQmlError> errors;
1633 bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1634 if (!errors.isEmpty()) {
1636 for (int i = 0; i < errors.size(); ++i) {
1637 builtError = QString(QLatin1String("%1\n %2"))
1639 .arg(errors.at(i).toString());
1641 *errorString = builtError;
1647 \property QQmlEngine::offlineStoragePath
1648 \brief the directory for storing offline user data
1650 Returns the directory where SQL and other offline
1653 QQuickWebView and the SQL databases created with openDatabase()
1656 The default is QML/OfflineStorage in the platform-standard
1657 user application data directory.
1659 Note that the path may not currently exist on the filesystem, so
1660 callers wanting to \e create new files at this location should create
1661 it first - see QDir::mkpath().
1663 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1666 d->offlineStoragePath = dir;
1669 QString QQmlEngine::offlineStoragePath() const
1671 Q_D(const QQmlEngine);
1672 return d->offlineStoragePath;
1675 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1679 if (!mo->superClass()) {
1680 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1681 propertyCache.insert(mo, rv);
1684 QQmlPropertyCache *super = cache(mo->superClass());
1685 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1686 propertyCache.insert(mo, rv);
1691 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1694 QList<QQmlType *> types;
1696 int maxMinorVersion = 0;
1698 const QMetaObject *metaObject = type->metaObject();
1700 while (metaObject) {
1701 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1702 type->majorVersion(), minorVersion);
1704 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1710 metaObject = metaObject->superClass();
1713 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1715 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1719 QQmlPropertyCache *raw = cache(type->metaObject());
1721 bool hasCopied = false;
1723 for (int ii = 0; ii < types.count(); ++ii) {
1724 QQmlType *currentType = types.at(ii);
1728 int rev = currentType->metaObjectRevision();
1729 int moIndex = types.count() - 1 - ii;
1731 if (raw->allowedRevisionCache[moIndex] != rev) {
1736 raw->allowedRevisionCache[moIndex] = rev;
1740 // Test revision compatibility - the basic rule is:
1741 // * Anything that is excluded, cannot overload something that is not excluded *
1743 // Signals override:
1744 // * other signals and methods of the same name.
1745 // * properties named on<Signal Name>
1746 // * automatic <property name>Changed notify signals
1748 // Methods override:
1749 // * other methods of the same name
1751 // Properties override:
1752 // * other elements of the same name
1754 bool overloadError = false;
1755 QString overloadName;
1758 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1759 !overloadError && iter != raw->stringCache.end();
1762 QQmlPropertyData *d = *iter;
1763 if (raw->isAllowedInRevision(d))
1764 continue; // Not excluded - no problems
1766 // check that a regular "name" overload isn't happening
1767 QQmlPropertyData *current = d;
1768 while (!overloadError && current) {
1769 current = d->overrideData(current);
1770 if (current && raw->isAllowedInRevision(current))
1771 overloadError = true;
1776 if (overloadError) {
1777 if (hasCopied) raw->release();
1779 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."));
1783 if (!hasCopied) raw->addref();
1784 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1786 if (minorVersion != maxMinorVersion) {
1788 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1794 QQmlMetaType::ModuleApiInstance *
1795 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1797 Locker locker(this);
1799 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1801 a = new QQmlMetaType::ModuleApiInstance;
1802 a->scriptCallback = module.script;
1803 a->qobjectCallback = module.qobject;
1804 a->instanceMetaObject = module.instanceMetaObject;
1805 moduleApiInstances.insert(module, a);
1811 bool QQmlEnginePrivate::isQObject(int t)
1813 Locker locker(this);
1814 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1817 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1819 Locker locker(this);
1820 int t = v.userType();
1821 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1823 return *(QObject **)(v.constData());
1825 return QQmlMetaType::toQObject(v, ok);
1829 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1831 Locker locker(this);
1832 if (m_compositeTypes.contains(t))
1833 return QQmlMetaType::Object;
1834 else if (m_qmlLists.contains(t))
1835 return QQmlMetaType::List;
1837 return QQmlMetaType::typeCategory(t);
1840 bool QQmlEnginePrivate::isList(int t) const
1842 Locker locker(this);
1843 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1846 int QQmlEnginePrivate::listType(int t) const
1848 Locker locker(this);
1849 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1850 if (iter != m_qmlLists.end())
1853 return QQmlMetaType::listType(t);
1856 const QMetaObject *QQmlEnginePrivate::rawMetaObjectForType(int t) const
1858 Locker locker(this);
1859 QHash<int, const QMetaObject *>::ConstIterator iter = m_compositeTypes.find(t);
1860 if (iter != m_compositeTypes.end()) {
1863 QQmlType *type = QQmlMetaType::qmlType(t);
1864 return type?type->baseMetaObject():0;
1868 const QMetaObject *QQmlEnginePrivate::metaObjectForType(int t) const
1870 Locker locker(this);
1871 QHash<int, const QMetaObject *>::ConstIterator iter = m_compositeTypes.find(t);
1872 if (iter != m_compositeTypes.end()) {
1875 QQmlType *type = QQmlMetaType::qmlType(t);
1876 return type?type->metaObject():0;
1880 void QQmlEnginePrivate::registerCompositeType(const QMetaObject *mo)
1882 QByteArray name = mo->className();
1884 QByteArray ptr = name + '*';
1885 QByteArray lst = "QQmlListProperty<" + name + '>';
1887 int ptr_type = QMetaType::registerNormalizedType(ptr,
1888 qMetaTypeDeleteHelper<QObject*>,
1889 qMetaTypeCreateHelper<QObject*>,
1890 qMetaTypeDestructHelper<QObject*>,
1891 qMetaTypeConstructHelper<QObject*>,
1893 static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QObject*>::Flags),
1895 int lst_type = QMetaType::registerNormalizedType(lst,
1896 qMetaTypeDeleteHelper<QQmlListProperty<QObject> >,
1897 qMetaTypeCreateHelper<QQmlListProperty<QObject> >,
1898 qMetaTypeDestructHelper<QQmlListProperty<QObject> >,
1899 qMetaTypeConstructHelper<QQmlListProperty<QObject> >,
1900 sizeof(QQmlListProperty<QObject>),
1901 static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<QObject> >::Flags),
1902 static_cast<QMetaObject*>(0));
1904 Locker locker(this);
1905 m_qmlLists.insert(lst_type, ptr_type);
1906 m_compositeTypes.insert(ptr_type, mo);
1909 void QQmlEnginePrivate::unregisterCompositeType(const QMetaObject *mo)
1911 QByteArray name = mo->className();
1913 QByteArray ptr = name + '*';
1914 QByteArray lst = "QQmlListProperty<" + name + '>';
1916 int ptr_type = QMetaType::type(ptr.constData());
1917 int lst_type = QMetaType::type(lst.constData());
1919 Locker locker(this);
1920 m_qmlLists.remove(lst_type);
1921 m_compositeTypes.remove(ptr_type);
1924 void QQmlEnginePrivate::clearCache()
1926 typeLoader.clearCache(this, &QQmlEnginePrivate::typeUnloaded);
1929 void QQmlEnginePrivate::trimCache()
1931 typeLoader.trimCache(this, &QQmlEnginePrivate::typeUnloaded);
1934 void QQmlEnginePrivate::typeUnloaded(QQmlTypeData *typeData)
1936 unregisterCompositeType(typeData->compiledData()->root);
1939 bool QQmlEnginePrivate::isTypeLoaded(const QUrl &url) const
1941 return typeLoader.isTypeLoaded(url);
1944 bool QQmlEnginePrivate::isScriptLoaded(const QUrl &url) const
1946 return typeLoader.isScriptLoaded(url);
1949 bool QQml_isFileCaseCorrect(const QString &fileName)
1951 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1952 QFileInfo info(fileName);
1953 const QString absolute = info.absoluteFilePath();
1955 #if defined(Q_OS_MAC)
1956 const QString canonical = info.canonicalFilePath();
1957 #elif defined(Q_OS_WIN)
1958 wchar_t buffer[1024];
1960 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1961 if (rv == 0 || rv >= 1024) return true;
1962 rv = ::GetLongPathName(buffer, buffer, 1024);
1963 if (rv == 0 || rv >= 1024) return true;
1965 const QString canonical = QString::fromWCharArray(buffer);
1968 const int absoluteLength = absolute.length();
1969 const int canonicalLength = canonical.length();
1971 const int length = qMin(absoluteLength, canonicalLength);
1972 for (int ii = 0; ii < length; ++ii) {
1973 const QChar &a = absolute.at(absoluteLength - 1 - ii);
1974 const QChar &c = canonical.at(canonicalLength - 1 - ii);
1976 if (a.toLower() != c.toLower())
1988 \fn QQmlEngine *qmlEngine(const QObject *object)
1991 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
1992 QQmlEngine::contextForObject(object)->engine(), but more efficient.
1996 \fn QQmlContext *qmlContext(const QObject *object)
1999 Returns the QQmlContext associated with \a object, if any. This is equivalent to
2000 QQmlEngine::contextForObject(object).