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 <QtNetwork/qnetworkconfigmanager.h>
85 #include <private/qobject_p.h>
86 #include <private/qmetaobject_p.h>
88 #include <private/qqmllocale_p.h>
90 #ifdef Q_OS_WIN // for %APPDATA%
91 #include <qt_windows.h>
95 #define CSIDL_APPDATA 0x001a // <username>\Application Data
98 Q_DECLARE_METATYPE(QQmlProperty)
102 void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
104 QQmlEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
105 QQmlValueTypeFactory::registerBaseTypes(uri, versionMajor, versionMinor);
109 \qmlclass QtObject QObject
110 \ingroup qml-utility-elements
112 \brief The QtObject element is the most basic element in QML.
114 The QtObject element is a non-visual element which contains only the
117 It can be useful to create a QtObject if you need an extremely
118 lightweight element to enclose a set of custom properties:
120 \snippet doc/src/snippets/qml/qtobject.qml 0
122 It can also be useful for C++ integration, as it is just a plain
123 QObject. See the QObject documentation for further details.
126 \qmlproperty string QtObject::objectName
127 This property holds the QObject::objectName for this specific object instance.
129 This allows a C++ application to locate an item within a QML component
130 using the QObject::findChild() method. For example, the following C++
131 application locates the child \l Rectangle item and dynamically changes its
140 width: 200; height: 200
154 view.setSource(QUrl::fromLocalFile("MyRect.qml"));
157 QQuickItem *item = view.rootObject()->findChild<QQuickItem*>("myRect");
159 item->setProperty("color", QColor(Qt::yellow));
163 bool QQmlEnginePrivate::qml_debugging_enabled = false;
165 void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
167 qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
168 qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
169 qmlRegisterType<QQuickListElement>(uri, versionMajor, versionMinor,"ListElement");
170 qmlRegisterCustomType<QQuickListModel>(uri, versionMajor, versionMinor,"ListModel", new QQuickListModelParser);
171 qmlRegisterType<QQuickWorkerScript>(uri,versionMajor,versionMinor,"WorkerScript");
174 void QQmlEnginePrivate::defineModule()
176 registerBaseTypes("QtQuick", 2, 0);
177 qmlRegisterUncreatableType<QQmlLocale>("QtQuick",2,0,"Locale",QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
182 \class QQmlImageProviderBase
183 \brief The QQmlImageProviderBase class is used to register image providers in the QML engine.
186 Image providers must be registered with the QML engine. The only information the QML
187 engine knows about image providers is the type of image data they provide. To use an
188 image provider to acquire image data, you must cast the QQmlImageProviderBase pointer
189 to a QQuickImageProvider pointer.
191 \sa QQuickImageProvider, QQuickTextureFactory
195 \enum QQmlImageProviderBase::ImageType
197 Defines the type of image supported by this image provider.
199 \value Image The Image Provider provides QImage images.
200 The QQuickImageProvider::requestImage() method will be called for all image requests.
201 \value Pixmap The Image Provider provides QPixmap images.
202 The QQuickImageProvider::requestPixmap() method will be called for all image requests.
203 \value Texture The Image Provider provides QSGTextureProvider based images.
204 The QQuickImageProvider::requestTexture() method will be called for all image requests. \omitvalue
208 QQmlImageProviderBase::QQmlImageProviderBase()
213 QQmlImageProviderBase::~QQmlImageProviderBase()
219 \qmlclass Qt QQmlEnginePrivate
220 \ingroup qml-utility-elements
221 \brief The QML global Qt object provides useful enums and functions from Qt.
223 \keyword QmlGlobalQtObject
225 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
227 The \c Qt object is a global object with utility functions, properties and enums.
229 It is not instantiable; to use it, call the members of the global \c Qt object directly.
236 color: Qt.rgba(1, 0, 0, 1)
237 text: Qt.md5("hello, world")
244 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
245 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
249 The Qt object also contains helper functions for creating objects of specific
250 data types. This is primarily useful when setting the properties of an item
251 when the property has one of the following types:
254 \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()}
255 \li \c rect - use \l{Qt::rect()}{Qt.rect()}
256 \li \c point - use \l{Qt::point()}{Qt.point()}
257 \li \c size - use \l{Qt::size()}{Qt.size()}
258 \li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
261 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
263 \section1 Date/Time Formatters
265 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
268 \li \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
269 \li \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
270 \li \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
273 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
276 \section1 Dynamic Object Creation
277 The following functions on the global object allow you to dynamically create QML
278 items from files or strings. See \l{Dynamic Object Management in QML} for an overview
282 \li \l{Qt::createComponent()}{object Qt.createComponent(url)}
283 \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
289 \qmlproperty object Qt::application
292 The \c application object provides access to global application state
293 properties shared by many QML components.
299 \li \c application.active
301 This read-only property indicates whether the application is the top-most and focused
302 application, and the user is able to interact with the application. The property
303 is false when the application is in the background, the device keylock or screen
304 saver is active, the screen backlight is turned off, or the global system dialog
305 is being displayed on top of the application. It can be used for stopping and
306 pausing animations, timers and active processing of data in order to save device
307 battery power and free device memory and processor load when the application is not
311 \li \c application.layoutDirection
313 This read-only property can be used to query the default layout direction of the
314 application. On system start-up, the default layout direction depends on the
315 application's language. The property has a value of \c Qt.RightToLeft in locales
316 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
317 where the reading direction flows from left to right. You can bind to this
318 property to customize your application layouts to support both layout directions.
323 \li Qt.LeftToRight - Text and graphics elements should be positioned
325 \li Qt.RightToLeft - Text and graphics elements should be positioned
329 The following example uses the \c application object to indicate
330 whether the application is currently active:
332 \snippet doc/src/snippets/qml/application.qml document
334 \qmlproperty object Qt::inputMethod
337 The \c inputMethod object allows access to application's QInputMethod object
338 and all its properties and slots. See the QInputMethod documentation for
344 \qmlmethod object Qt::include(string url, jsobject callback)
346 Includes another JavaScript file. This method can only be used from within JavaScript files,
347 and not regular QML files.
349 This imports all functions from \a url into the current script's namespace.
351 Qt.include() returns an object that describes the status of the operation. The object has
352 a single property, \c {status}, that is set to one of the following values:
355 \header \li Symbol \li Value \li Description
356 \row \li result.OK \li 0 \li The include completed successfully.
357 \row \li result.LOADING \li 1 \li Data is being loaded from the network.
358 \row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
359 \row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
360 An additional \c exception property will be set in this case.
363 The \c status property will be updated as the operation progresses.
365 If provided, \a callback is invoked when the operation completes. The callback is passed
366 the same object as is returned from the Qt.include() call.
368 // Qt.include() is implemented in qv8include.cpp
371 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
372 : propertyCapture(0), rootContext(0), isDebugging(false),
373 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
374 cleanup(0), erroredBindings(0), inProgressCreations(0),
375 workerScriptEngine(0), activeVME(0),
376 networkAccessManager(0), networkAccessManagerFactory(0),
377 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
378 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
382 QQmlEnginePrivate::~QQmlEnginePrivate()
384 if (inProgressCreations)
385 qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
388 QQmlCleanup *c = cleanup;
390 if (cleanup) cleanup->prev = &cleanup;
396 doDeleteInEngineThread();
398 if (incubationController) incubationController->d = 0;
399 incubationController = 0;
404 for(QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
406 for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
408 for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
410 for(QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
411 delete (*iter)->qobjectApi;
416 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
418 QObjectPrivate *p = QObjectPrivate::get(o);
419 if (p->declarativeData) {
420 QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
421 if (d->ownContext && d->context) {
422 d->context->destroy();
428 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
430 static_cast<QQmlData *>(d)->destroyed(o);
433 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
435 static_cast<QQmlData *>(d)->parentChanged(o, p);
438 void QQmlData::objectNameChanged(QAbstractDeclarativeData *d, QObject *o)
440 static_cast<QQmlData *>(d)->objectNameChanged(o);
443 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **a)
445 QQmlData *ddata = QQmlData::get(object, false);
446 if (!ddata) return; // Probably being deleted
448 QQmlNotifierEndpoint *ep = ddata->notify(index);
449 if (ep) QQmlNotifier::emitNotify(ep, a);
452 int QQmlData::receivers(QAbstractDeclarativeData *d, const QObject *, int index)
454 return static_cast<QQmlData *>(d)->endpointCount(index);
457 int QQmlData::endpointCount(int index)
460 QQmlNotifierEndpoint *ep = notify(index);
471 void QQmlEnginePrivate::init()
475 static bool firstTime = true;
477 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component");
483 qRegisterMetaType<QVariant>("QVariant");
484 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
485 qRegisterMetaType<QJSValue>("QJSValue");
486 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
487 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
488 qRegisterMetaType<QList<int> >("QList<int>");
489 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
491 v8engine()->setEngine(q);
493 rootContext = new QQmlContext(q,true);
495 if (QCoreApplication::instance()->thread() == q->thread() &&
496 QQmlEngineDebugService::isDebuggingEnabled()) {
498 QQmlEngineDebugService::instance()->addEngine(q);
499 QV8DebugService::initialize(v8engine());
500 QV8ProfilerService::initialize();
501 QQmlProfilerService::initialize();
502 QDebugMessageService::instance();
505 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
506 if (!dataLocation.isEmpty())
507 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator())
508 + QDir::separator() + QLatin1String("QML")
509 + QDir::separator() + QLatin1String("OfflineStorage");
512 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
515 if (!workerScriptEngine)
516 workerScriptEngine = new QQuickWorkerScriptEngine(q);
517 return workerScriptEngine;
524 \brief The QQmlEngine class provides an environment for instantiating QML components.
527 Each QML component is instantiated in a QQmlContext.
528 QQmlContext's are essential for passing data to QML
529 components. In QML, contexts are arranged hierarchically and this
530 hierarchy is managed by the QQmlEngine.
532 Prior to creating any QML components, an application must have
533 created a QQmlEngine to gain access to a QML context. The
534 following example shows how to create a simple Text item.
538 QQmlComponent component(&engine);
539 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
540 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
542 //add item to view, etc
546 In this case, the Text item will be created in the engine's
547 \l {QQmlEngine::rootContext()}{root context}.
549 Note that the QtQuick 1 version is called QDeclarativeEngine.
551 \sa QQmlComponent, QQmlContext
555 Create a new QQmlEngine with the given \a parent.
557 QQmlEngine::QQmlEngine(QObject *parent)
558 : QJSEngine(*new QQmlEnginePrivate(this), parent)
565 Destroys the QQmlEngine.
567 Any QQmlContext's created on this engine will be
568 invalidated, but not destroyed (unless they are parented to the
571 QQmlEngine::~QQmlEngine()
574 if (d->isDebugging) {
575 QQmlEngineDebugService::instance()->remEngine(this);
578 // Emit onDestruction signals for the root context before
579 // we destroy the contexts, engine, Module APIs etc. that
580 // may be required to handle the destruction signal.
581 QQmlContextData::get(rootContext())->emitDestruction();
583 // if we are the parent of any of the qobject module api instances,
584 // we need to remove them from our internal list, in order to prevent
585 // a segfault in engine private dtor.
586 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
587 QObject *currQObjectApi = 0;
588 QQmlMetaType::ModuleApiInstance *currInstance = 0;
589 foreach (const QQmlMetaType::ModuleApi &key, keys) {
590 currInstance = d->moduleApiInstances.value(key);
591 currQObjectApi = currInstance->qobjectApi;
592 if (this->children().contains(currQObjectApi)) {
593 delete currQObjectApi;
595 d->moduleApiInstances.remove(key);
599 if (d->incubationController)
600 d->incubationController->d = 0;
603 /*! \fn void QQmlEngine::quit()
604 This signal is emitted when the QML loaded by the engine would like to quit.
607 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
608 This signal is emitted when \a warnings messages are generated by QML.
612 Clears the engine's internal component cache.
614 This function causes the property metadata of all components previously
615 loaded by the engine to be destroyed. All previously loaded components and
616 the property bindings for all extant objects created from those components will
619 This function returns the engine to a state where it does not contain any loaded
620 component data. This may be useful in order to reload a smaller subset of the
621 previous component set, or to load a new version of a previously loaded component.
623 Once the component cache has been cleared, components must be loaded before
624 any new objects can be created.
626 void QQmlEngine::clearComponentCache()
629 d->typeLoader.clearCache();
633 Returns the engine's root context.
635 The root context is automatically created by the QQmlEngine.
636 Data that should be available to all QML component instances
637 instantiated by the engine should be put in the root context.
639 Additional data that should only be available to a subset of
640 component instances should be added to sub-contexts parented to the
643 QQmlContext *QQmlEngine::rootContext() const
645 Q_D(const QQmlEngine);
646 return d->rootContext;
650 Sets the \a factory to use for creating QNetworkAccessManager(s).
652 QNetworkAccessManager is used for all network access by QML. By
653 implementing a factory it is possible to create custom
654 QNetworkAccessManager with specialized caching, proxy and cookie
657 The factory must be set before executing the engine.
659 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
662 QMutexLocker locker(&d->mutex);
663 d->networkAccessManagerFactory = factory;
667 Returns the current QQmlNetworkAccessManagerFactory.
669 \sa setNetworkAccessManagerFactory()
671 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
673 Q_D(const QQmlEngine);
674 return d->networkAccessManagerFactory;
677 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
680 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
682 void *args[] = { 0 };
683 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
687 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
689 QMutexLocker locker(&mutex);
690 QNetworkAccessManager *nam;
691 if (networkAccessManagerFactory) {
692 nam = networkAccessManagerFactory->create(parent);
694 nam = new QNetworkAccessManager(parent);
700 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
702 Q_Q(const QQmlEngine);
703 if (!networkAccessManager)
704 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
705 return networkAccessManager;
709 Returns a common QNetworkAccessManager which can be used by any QML
710 element instantiated by this engine.
712 If a QQmlNetworkAccessManagerFactory has been set and a
713 QNetworkAccessManager has not yet been created, the
714 QQmlNetworkAccessManagerFactory will be used to create the
715 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
716 will have no proxy or cache set.
718 \sa setNetworkAccessManagerFactory()
720 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
722 Q_D(const QQmlEngine);
723 return d->getNetworkAccessManager();
728 Sets the \a provider to use for images requested via the \e
729 image: url scheme, with host \a providerId. The QQmlEngine
730 takes ownership of \a provider.
732 Image providers enable support for pixmap and threaded image
733 requests. See the QQuickImageProvider documentation for details on
734 implementing and using image providers.
736 All required image providers should be added to the engine before any
737 QML sources files are loaded.
739 \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
741 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
744 QMutexLocker locker(&d->mutex);
745 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
749 Returns the image provider set for \a providerId.
751 Returns the provider if it was found; otherwise returns 0.
753 \sa QQuickImageProvider
755 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
757 Q_D(const QQmlEngine);
758 QMutexLocker locker(&d->mutex);
759 return d->imageProviders.value(providerId).data();
763 Removes the image provider for \a providerId.
765 \sa addImageProvider(), QQuickImageProvider
767 void QQmlEngine::removeImageProvider(const QString &providerId)
770 QMutexLocker locker(&d->mutex);
771 d->imageProviders.take(providerId);
775 Return the base URL for this engine. The base URL is only used to
776 resolve components when a relative URL is passed to the
777 QQmlComponent constructor.
779 If a base URL has not been explicitly set, this method returns the
780 application's current working directory.
784 QUrl QQmlEngine::baseUrl() const
786 Q_D(const QQmlEngine);
787 if (d->baseUrl.isEmpty()) {
788 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
795 Set the base URL for this engine to \a url.
799 void QQmlEngine::setBaseUrl(const QUrl &url)
806 Returns true if warning messages will be output to stderr in addition
807 to being emitted by the warnings() signal, otherwise false.
809 The default value is true.
811 bool QQmlEngine::outputWarningsToStandardError() const
813 Q_D(const QQmlEngine);
814 return d->outputWarningsToStdErr;
818 Set whether warning messages will be output to stderr to \a enabled.
820 If \a enabled is true, any warning messages generated by QML will be
821 output to stderr and emitted by the warnings() signal. If \a enabled
822 is false, on the warnings() signal will be emitted. This allows
823 applications to handle warning output themselves.
825 The default value is true.
827 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
830 d->outputWarningsToStdErr = enabled;
834 Attempt to free unused memory.
836 void QQmlEngine::collectGarbage()
842 Returns the QQmlContext for the \a object, or 0 if no
843 context has been set.
845 When the QQmlEngine instantiates a QObject, the context is
848 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
853 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
856 static_cast<QQmlData *>(priv->declarativeData);
860 else if (data->outerContext)
861 return data->outerContext->asQQmlContext();
867 Sets the QQmlContext for the \a object to \a context.
868 If the \a object already has a context, a warning is
869 output, but the context is not changed.
871 When the QQmlEngine instantiates a QObject, the context is
874 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
876 if (!object || !context)
879 QQmlData *data = QQmlData::get(object, true);
881 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
885 QQmlContextData *contextData = QQmlContextData::get(context);
886 contextData->addObject(object);
890 \enum QQmlEngine::ObjectOwnership
892 Ownership controls whether or not QML automatically destroys the
893 QObject when the object is garbage collected by the JavaScript
894 engine. The two ownership options are:
896 \value CppOwnership The object is owned by C++ code, and will
897 never be deleted by QML. The JavaScript destroy() method cannot be
898 used on objects with CppOwnership. This option is similar to
899 QScriptEngine::QtOwnership.
901 \value JavaScriptOwnership The object is owned by JavaScript.
902 When the object is returned to QML as the return value of a method
903 call or property access, QML will track it, and delete the object
904 if there are no remaining JavaScript references to it and it has no
905 QObject::parent(). An object tracked by one QQmlEngine
906 will be deleted during that QQmlEngine's destructor, and thus
907 JavaScript references between objects with JavaScriptOwnership from
908 two different engines will not be valid after the deletion of one of
909 those engines. This option is similar to QScriptEngine::ScriptOwnership.
911 Generally an application doesn't need to set an object's ownership
912 explicitly. QML uses a heuristic to set the default object
913 ownership. By default, an object that is created by QML has
914 JavaScriptOwnership. The exception to this are the root objects
915 created by calling QQmlComponent::create() or
916 QQmlComponent::beginCreate() which have CppOwnership by
917 default. The ownership of these root-level objects is considered to
918 have been transferred to the C++ caller.
920 Objects not-created by QML have CppOwnership by default. The
921 exception to this is objects returned from a C++ method call. The
922 ownership of these objects is passed to JavaScript.
924 Calling setObjectOwnership() overrides the default ownership
925 heuristic used by QML.
929 Sets the \a ownership of \a object.
931 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
936 QQmlData *ddata = QQmlData::get(object, true);
940 ddata->indestructible = (ownership == CppOwnership)?true:false;
941 ddata->explicitIndestructibleSet = true;
945 Returns the ownership of \a object.
947 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
952 QQmlData *ddata = QQmlData::get(object, false);
956 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
959 bool QQmlEngine::event(QEvent *e)
962 if (e->type() == QEvent::User)
963 d->doDeleteInEngineThread();
965 return QJSEngine::event(e);
968 void QQmlEnginePrivate::doDeleteInEngineThread()
970 QFieldList<Deletable, &Deletable::next> list;
972 list.copyAndClear(toDeleteInEngineThread);
975 while (Deletable *d = list.takeFirst())
979 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
981 QQmlData *data = QQmlData::get(object);
983 if (data && data->deferredComponent) {
984 QQmlObjectCreatingProfiler prof;
986 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
987 prof.setTypeName(type ? type->qmlTypeName()
988 : QString::fromUtf8(object->metaObject()->className()));
989 if (data->outerContext)
990 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
992 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
994 QQmlComponentPrivate::ConstructionState state;
995 QQmlComponentPrivate::beginDeferred(ep, object, &state);
997 data->deferredComponent->release();
998 data->deferredComponent = 0;
1000 QQmlComponentPrivate::complete(ep, &state);
1004 QQmlContext *qmlContext(const QObject *obj)
1006 return QQmlEngine::contextForObject(obj);
1009 QQmlEngine *qmlEngine(const QObject *obj)
1011 QQmlData *data = QQmlData::get(obj, false);
1012 if (!data || !data->context)
1014 return data->context->engine;
1017 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1019 QQmlData *data = QQmlData::get(object);
1021 return 0; // Attached properties are only on objects created by QML
1023 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1027 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1031 rv = pf(const_cast<QObject *>(object));
1034 data->attachedProperties()->insert(id, rv);
1039 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1040 const QMetaObject *attachedMetaObject, bool create)
1043 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1045 if (*idCache == -1 || !object)
1048 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1051 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1053 #ifndef QQML_NO_DEBUG_PROTOCOL
1054 if (!QQmlEnginePrivate::qml_debugging_enabled
1056 qDebug("QML debugging is enabled. Only use this in a safe environment.");
1058 QQmlEnginePrivate::qml_debugging_enabled = true;
1063 class QQmlDataExtended {
1066 ~QQmlDataExtended();
1068 QHash<int, QObject *> attachedProperties;
1069 QQmlNotifier objectNameNotifier;
1072 QQmlDataExtended::QQmlDataExtended()
1076 QQmlDataExtended::~QQmlDataExtended()
1080 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1083 layout(endpoint->next);
1085 int index = endpoint->sourceSignal;
1086 index = qMin(index, 0xFFFF - 1);
1088 endpoint->next = notifies[index];
1089 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1090 endpoint->prev = ¬ifies[index];
1091 notifies[index] = endpoint;
1094 void QQmlData::NotifyList::layout()
1096 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1099 QQmlNotifierEndpoint **old = notifies;
1100 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1101 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1102 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1103 sizeof(QQmlNotifierEndpoint*);
1104 memset(notifies + notifiesSize, 0, memsetSize);
1106 if (notifies != old) {
1107 for (int ii = 0; ii < notifiesSize; ++ii)
1109 notifies[ii]->prev = ¬ifies[ii];
1112 notifiesSize = maximumTodoIndex + 1;
1117 maximumTodoIndex = 0;
1121 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1124 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1125 notifyList->connectionMask = 0;
1126 notifyList->maximumTodoIndex = 0;
1127 notifyList->notifiesSize = 0;
1128 notifyList->todo = 0;
1129 notifyList->notifies = 0;
1132 Q_ASSERT(!endpoint->isConnected());
1134 index = qMin(index, 0xFFFF - 1);
1135 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1137 if (index < notifyList->notifiesSize) {
1139 endpoint->next = notifyList->notifies[index];
1140 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1141 endpoint->prev = ¬ifyList->notifies[index];
1142 notifyList->notifies[index] = endpoint;
1145 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1147 endpoint->next = notifyList->todo;
1148 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1149 endpoint->prev = ¬ifyList->todo;
1150 notifyList->todo = endpoint;
1154 bool QQml_isSignalConnected(QObject *obj, int signal_index, int index)
1156 QQmlData *data = QQmlData::get(obj);
1157 return QObjectPrivate::get(obj)->isSignalConnected(signal_index) || (data && data->signalHasEndpoint(index));
1161 index MUST be the index returned by QMetaMethod::index()
1162 This is different than the index returned by QObjectPrivate::signalIndex()
1164 bool QQmlData::signalHasEndpoint(int index)
1166 return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
1169 QQmlNotifier *QQmlData::objectNameNotifier() const
1171 if (!extendedData) extendedData = new QQmlDataExtended;
1172 return &extendedData->objectNameNotifier;
1175 QHash<int, QObject *> *QQmlData::attachedProperties() const
1177 if (!extendedData) extendedData = new QQmlDataExtended;
1178 return &extendedData->attachedProperties;
1181 void QQmlData::destroyed(QObject *object)
1183 if (deferredComponent)
1184 deferredComponent->release();
1186 if (nextContextObject)
1187 nextContextObject->prevContextObject = prevContextObject;
1188 if (prevContextObject)
1189 *prevContextObject = nextContextObject;
1191 QQmlAbstractBinding *binding = bindings;
1193 QQmlAbstractBinding *next = binding->m_nextBinding;
1194 binding->m_prevBinding = 0;
1195 binding->m_nextBinding = 0;
1200 QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1201 while (signalHandler) {
1202 QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1203 signalHandler->m_prevSignal = 0;
1204 signalHandler->m_nextSignal = 0;
1205 delete signalHandler;
1206 signalHandler = next;
1213 propertyCache->release();
1215 if (ownContext && context)
1219 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1220 *guard = (QObject *)0;
1221 guard->objectDestroyed(object);
1225 while (notifyList->todo)
1226 notifyList->todo->disconnect();
1227 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1228 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1231 free(notifyList->notifies);
1237 delete extendedData;
1239 v8object.Clear(); // The WeakReference handler will clean the actual handle
1245 void QQmlData::parentChanged(QObject *object, QObject *parent)
1251 void QQmlData::objectNameChanged(QObject *)
1253 if (extendedData) objectNameNotifier()->notify();
1256 bool QQmlData::hasBindingBit(int bit) const
1258 if (bindingBitsSize > bit)
1259 return bindingBits[bit / 32] & (1 << (bit % 32));
1264 void QQmlData::clearBindingBit(int bit)
1266 if (bindingBitsSize > bit)
1267 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1270 void QQmlData::setBindingBit(QObject *obj, int bit)
1272 if (bindingBitsSize <= bit) {
1273 int props = obj->metaObject()->propertyCount();
1274 Q_ASSERT(bit < props);
1276 int arraySize = (props + 31) / 32;
1277 int oldArraySize = bindingBitsSize / 32;
1279 bindingBits = (quint32 *)realloc(bindingBits,
1280 arraySize * sizeof(quint32));
1282 memset(bindingBits + oldArraySize,
1284 sizeof(quint32) * (arraySize - oldArraySize));
1286 bindingBitsSize = arraySize * 32;
1289 bindingBits[bit / 32] |= (1 << (bit % 32));
1292 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
1294 if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
1295 if (url.authority().isEmpty())
1296 return QLatin1Char(':') + url.path();
1299 return url.toLocalFile();
1303 static QString toLocalFile(const QString &url)
1305 if (!url.startsWith(QLatin1String("file://"), Qt::CaseInsensitive))
1308 QString file = url.mid(7);
1310 //XXX TODO: handle windows hostnames: "//servername/path/to/file.txt"
1312 // magic for drives on windows
1313 if (file.length() > 2 && file.at(0) == QLatin1Char('/') && file.at(2) == QLatin1Char(':'))
1319 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QString& url)
1321 if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) {
1322 if (url.length() > 4)
1323 return QLatin1Char(':') + url.mid(4);
1327 return toLocalFile(url);
1330 void QQmlEnginePrivate::sendQuit()
1334 if (q->receivers(SIGNAL(quit())) == 0) {
1335 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1339 static void dumpwarning(const QQmlError &error)
1341 qWarning().nospace() << qPrintable(error.toString());
1344 static void dumpwarning(const QList<QQmlError> &errors)
1346 for (int ii = 0; ii < errors.count(); ++ii)
1347 dumpwarning(errors.at(ii));
1350 void QQmlEnginePrivate::warning(const QQmlError &error)
1353 q->warnings(QList<QQmlError>() << error);
1354 if (outputWarningsToStdErr)
1358 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1361 q->warnings(errors);
1362 if (outputWarningsToStdErr)
1363 dumpwarning(errors);
1366 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1369 QQmlEnginePrivate::get(engine)->warning(error);
1374 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1377 QQmlEnginePrivate::get(engine)->warning(error);
1382 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1385 engine->warning(error);
1390 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1393 engine->warning(error);
1399 This function should be called prior to evaluation of any js expression,
1400 so that scarce resources are not freed prematurely (eg, if there is a
1401 nested javascript expression).
1403 void QQmlEnginePrivate::referenceScarceResources()
1405 scarceResourcesRefCount += 1;
1409 This function should be called after evaluation of the js expression is
1410 complete, and so the scarce resources may be freed safely.
1412 void QQmlEnginePrivate::dereferenceScarceResources()
1414 Q_ASSERT(scarceResourcesRefCount > 0);
1415 scarceResourcesRefCount -= 1;
1417 // if the refcount is zero, then evaluation of the "top level"
1418 // expression must have completed. We can safely release the
1419 // scarce resources.
1420 if (scarceResourcesRefCount == 0) {
1421 // iterate through the list and release them all.
1422 // note that the actual SRD is owned by the JS engine,
1423 // so we cannot delete the SRD; but we can free the
1424 // memory used by the variant in the SRD.
1425 while (ScarceResourceData *sr = scarceResources.first()) {
1426 sr->data = QVariant();
1427 scarceResources.remove(sr);
1433 Adds \a path as a directory where the engine searches for
1434 installed modules in a URL-based directory structure.
1435 The \a path may be a local filesystem directory or a URL.
1437 The newly added \a path will be first in the importPathList().
1439 \sa setImportPathList(), {QML Modules}
1441 void QQmlEngine::addImportPath(const QString& path)
1444 d->importDatabase.addImportPath(path);
1448 Returns the list of directories where the engine searches for
1449 installed modules in a URL-based directory structure.
1451 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1452 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1453 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1454 provided by that module. A \c qmldir file is required for defining the
1455 type version mapping and possibly QML extensions plugins.
1457 By default, the list contains the directory of the application executable,
1458 paths specified in the \c QML_IMPORT_PATH environment variable,
1459 and the builtin \c ImportsPath from QLibraryInfo.
1461 \sa addImportPath(), setImportPathList()
1463 QStringList QQmlEngine::importPathList() const
1465 Q_D(const QQmlEngine);
1466 return d->importDatabase.importPathList();
1470 Sets \a paths as the list of directories where the engine searches for
1471 installed modules in a URL-based directory structure.
1473 By default, the list contains the directory of the application executable,
1474 paths specified in the \c QML_IMPORT_PATH environment variable,
1475 and the builtin \c ImportsPath from QLibraryInfo.
1477 \sa importPathList(), addImportPath()
1479 void QQmlEngine::setImportPathList(const QStringList &paths)
1482 d->importDatabase.setImportPathList(paths);
1487 Adds \a path as a directory where the engine searches for
1488 native plugins for imported modules (referenced in the \c qmldir file).
1490 By default, the list contains only \c ., i.e. the engine searches
1491 in the directory of the \c qmldir file itself.
1493 The newly added \a path will be first in the pluginPathList().
1495 \sa setPluginPathList()
1497 void QQmlEngine::addPluginPath(const QString& path)
1500 d->importDatabase.addPluginPath(path);
1505 Returns the list of directories where the engine searches for
1506 native plugins for imported modules (referenced in the \c qmldir file).
1508 By default, the list contains only \c ., i.e. the engine searches
1509 in the directory of the \c qmldir file itself.
1511 \sa addPluginPath(), setPluginPathList()
1513 QStringList QQmlEngine::pluginPathList() const
1515 Q_D(const QQmlEngine);
1516 return d->importDatabase.pluginPathList();
1520 Sets the list of directories where the engine searches for
1521 native plugins for imported modules (referenced in the \c qmldir file)
1524 By default, the list contains only \c ., i.e. the engine searches
1525 in the directory of the \c qmldir file itself.
1527 \sa pluginPathList(), addPluginPath()
1529 void QQmlEngine::setPluginPathList(const QStringList &paths)
1532 d->importDatabase.setPluginPathList(paths);
1536 Imports the plugin named \a filePath with the \a uri provided.
1537 Returns true if the plugin was successfully imported; otherwise returns false.
1539 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1541 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1543 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1546 return d->importDatabase.importPlugin(filePath, uri, errors);
1550 Imports the plugin named \a filePath with the \a uri provided.
1551 Returns true if the plugin was successfully imported; otherwise returns false.
1553 On failure and if non-null, *\a errorString will be set to a message describing the failure.
1555 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1557 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1560 QList<QQmlError> errors;
1561 bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1562 if (!errors.isEmpty()) {
1564 for (int i = 0; i < errors.size(); ++i) {
1565 builtError = QString(QLatin1String("%1\n %2"))
1567 .arg(errors.at(i).toString());
1569 *errorString = builtError;
1575 \property QQmlEngine::offlineStoragePath
1576 \brief the directory for storing offline user data
1578 Returns the directory where SQL and other offline
1581 QQuickWebView and the SQL databases created with openDatabase()
1584 The default is QML/OfflineStorage in the platform-standard
1585 user application data directory.
1587 Note that the path may not currently exist on the filesystem, so
1588 callers wanting to \e create new files at this location should create
1589 it first - see QDir::mkpath().
1591 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1594 d->offlineStoragePath = dir;
1597 QString QQmlEngine::offlineStoragePath() const
1599 Q_D(const QQmlEngine);
1600 return d->offlineStoragePath;
1603 static void voidptr_destructor(void *v)
1605 void **ptr = (void **)v;
1609 static void *voidptr_constructor(const void *v)
1614 return new void*(*(void **)v);
1618 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1622 if (!mo->superClass()) {
1623 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1624 propertyCache.insert(mo, rv);
1627 QQmlPropertyCache *super = cache(mo->superClass());
1628 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1629 propertyCache.insert(mo, rv);
1634 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1637 QList<QQmlType *> types;
1639 int maxMinorVersion = 0;
1641 const QMetaObject *metaObject = type->metaObject();
1643 while (metaObject) {
1644 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1645 type->majorVersion(), minorVersion);
1647 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1653 metaObject = metaObject->superClass();
1656 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1658 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1662 QQmlPropertyCache *raw = cache(type->metaObject());
1664 bool hasCopied = false;
1666 for (int ii = 0; ii < types.count(); ++ii) {
1667 QQmlType *currentType = types.at(ii);
1671 int rev = currentType->metaObjectRevision();
1672 int moIndex = types.count() - 1 - ii;
1674 if (raw->allowedRevisionCache[moIndex] != rev) {
1679 raw->allowedRevisionCache[moIndex] = rev;
1683 // Test revision compatibility - the basic rule is:
1684 // * Anything that is excluded, cannot overload something that is not excluded *
1686 // Signals override:
1687 // * other signals and methods of the same name.
1688 // * properties named on<Signal Name>
1689 // * automatic <property name>Changed notify signals
1691 // Methods override:
1692 // * other methods of the same name
1694 // Properties override:
1695 // * other elements of the same name
1697 bool overloadError = false;
1698 QString overloadName;
1701 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1702 !overloadError && iter != raw->stringCache.end();
1705 QQmlPropertyData *d = *iter;
1706 if (raw->isAllowedInRevision(d))
1707 continue; // Not excluded - no problems
1709 // check that a regular "name" overload isn't happening
1710 QQmlPropertyData *current = d;
1711 while (!overloadError && current) {
1712 current = d->overrideData(current);
1713 if (current && raw->isAllowedInRevision(current))
1714 overloadError = true;
1719 if (overloadError) {
1720 if (hasCopied) raw->release();
1722 error.setDescription(QLatin1String("Type ") + type->qmlTypeName() + QLatin1String(" ") + QString::number(type->majorVersion()) + QLatin1String(".") + QString::number(minorVersion) + QLatin1String(" contains an illegal property \"") + overloadName + QLatin1String("\". This is an error in the type's implementation."));
1726 if (!hasCopied) raw->addref();
1727 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1729 if (minorVersion != maxMinorVersion) {
1731 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1737 QQmlMetaType::ModuleApiInstance *
1738 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1740 Locker locker(this);
1742 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1744 a = new QQmlMetaType::ModuleApiInstance;
1745 a->scriptCallback = module.script;
1746 a->qobjectCallback = module.qobject;
1747 a->instanceMetaObject = module.instanceMetaObject;
1748 moduleApiInstances.insert(module, a);
1754 bool QQmlEnginePrivate::isQObject(int t)
1756 Locker locker(this);
1757 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1760 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1762 Locker locker(this);
1763 int t = v.userType();
1764 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1766 return *(QObject **)(v.constData());
1768 return QQmlMetaType::toQObject(v, ok);
1772 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1774 Locker locker(this);
1775 if (m_compositeTypes.contains(t))
1776 return QQmlMetaType::Object;
1777 else if (m_qmlLists.contains(t))
1778 return QQmlMetaType::List;
1780 return QQmlMetaType::typeCategory(t);
1783 bool QQmlEnginePrivate::isList(int t) const
1785 Locker locker(this);
1786 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1789 int QQmlEnginePrivate::listType(int t) const
1791 Locker locker(this);
1792 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1793 if (iter != m_qmlLists.end())
1796 return QQmlMetaType::listType(t);
1799 const QMetaObject *QQmlEnginePrivate::rawMetaObjectForType(int t) const
1801 Locker locker(this);
1802 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1803 if (iter != m_compositeTypes.end()) {
1804 return (*iter)->root;
1806 QQmlType *type = QQmlMetaType::qmlType(t);
1807 return type?type->baseMetaObject():0;
1811 const QMetaObject *QQmlEnginePrivate::metaObjectForType(int t) const
1813 Locker locker(this);
1814 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1815 if (iter != m_compositeTypes.end()) {
1816 return (*iter)->root;
1818 QQmlType *type = QQmlMetaType::qmlType(t);
1819 return type?type->metaObject():0;
1823 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1825 QByteArray name = data->root->className();
1827 QByteArray ptr = name + '*';
1828 QByteArray lst = "QQmlListProperty<" + name + '>';
1830 int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
1831 voidptr_constructor);
1832 int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
1833 voidptr_constructor);
1837 Locker locker(this);
1838 m_qmlLists.insert(lst_type, ptr_type);
1839 m_compositeTypes.insert(ptr_type, data);
1842 bool QQml_isFileCaseCorrect(const QString &fileName)
1844 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1845 QFileInfo info(fileName);
1846 const QString absolute = info.absoluteFilePath();
1848 #if defined(Q_OS_MAC)
1849 const QString canonical = info.canonicalFilePath();
1850 #elif defined(Q_OS_WIN)
1851 wchar_t buffer[1024];
1853 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1854 if (rv == 0 || rv >= 1024) return true;
1855 rv = ::GetLongPathName(buffer, buffer, 1024);
1856 if (rv == 0 || rv >= 1024) return true;
1858 const QString canonical = QString::fromWCharArray(buffer);
1861 const int absoluteLength = absolute.length();
1862 const int canonicalLength = canonical.length();
1864 const int length = qMin(absoluteLength, canonicalLength);
1865 for (int ii = 0; ii < length; ++ii) {
1866 const QChar &a = absolute.at(absoluteLength - 1 - ii);
1867 const QChar &c = canonical.at(canonicalLength - 1 - ii);
1869 if (a.toLower() != c.toLower())
1881 \fn QQmlEngine *qmlEngine(const QObject *object)
1884 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
1885 QQmlEngine::contextForObject(object)->engine(), but more efficient.
1889 \fn QQmlContext *qmlContext(const QObject *object)
1892 Returns the QQmlContext associated with \a object, if any. This is equivalent to
1893 QQmlEngine::contextForObject(object).