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();
426 // Mark this object as in the process of deletion to
427 // prevent it resolving in bindings
428 QQmlData::markAsDeleted(o);
432 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
434 static_cast<QQmlData *>(d)->destroyed(o);
437 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
439 static_cast<QQmlData *>(d)->parentChanged(o, p);
442 void QQmlData::objectNameChanged(QAbstractDeclarativeData *d, QObject *o)
444 static_cast<QQmlData *>(d)->objectNameChanged(o);
447 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **a)
449 QQmlData *ddata = QQmlData::get(object, false);
450 if (!ddata) return; // Probably being deleted
452 QQmlNotifierEndpoint *ep = ddata->notify(index);
453 if (ep) QQmlNotifier::emitNotify(ep, a);
456 int QQmlData::receivers(QAbstractDeclarativeData *d, const QObject *, int index)
458 return static_cast<QQmlData *>(d)->endpointCount(index);
461 int QQmlData::endpointCount(int index)
464 QQmlNotifierEndpoint *ep = notify(index);
475 void QQmlData::markAsDeleted(QObject *o)
477 QQmlData::setQueuedForDeletion(o);
479 QObjectPrivate *p = QObjectPrivate::get(o);
480 for (QList<QObject *>::iterator it = p->children.begin(), end = p->children.end(); it != end; ++it) {
481 QQmlData::markAsDeleted(*it);
485 void QQmlEnginePrivate::init()
489 static bool firstTime = true;
491 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component");
497 qRegisterMetaType<QVariant>("QVariant");
498 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
499 qRegisterMetaType<QJSValue>("QJSValue");
500 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
501 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
502 qRegisterMetaType<QList<int> >("QList<int>");
503 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
505 v8engine()->setEngine(q);
507 rootContext = new QQmlContext(q,true);
509 if (QCoreApplication::instance()->thread() == q->thread() &&
510 QQmlEngineDebugService::isDebuggingEnabled()) {
512 QQmlEngineDebugService::instance()->addEngine(q);
513 QV8DebugService::initialize(v8engine());
514 QV8ProfilerService::initialize();
515 QQmlProfilerService::initialize();
516 QDebugMessageService::instance();
519 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
520 if (!dataLocation.isEmpty())
521 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator())
522 + QDir::separator() + QLatin1String("QML")
523 + QDir::separator() + QLatin1String("OfflineStorage");
526 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
529 if (!workerScriptEngine)
530 workerScriptEngine = new QQuickWorkerScriptEngine(q);
531 return workerScriptEngine;
538 \brief The QQmlEngine class provides an environment for instantiating QML components.
541 Each QML component is instantiated in a QQmlContext.
542 QQmlContext's are essential for passing data to QML
543 components. In QML, contexts are arranged hierarchically and this
544 hierarchy is managed by the QQmlEngine.
546 Prior to creating any QML components, an application must have
547 created a QQmlEngine to gain access to a QML context. The
548 following example shows how to create a simple Text item.
552 QQmlComponent component(&engine);
553 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
554 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
556 //add item to view, etc
560 In this case, the Text item will be created in the engine's
561 \l {QQmlEngine::rootContext()}{root context}.
563 Note that the QtQuick 1 version is called QDeclarativeEngine.
565 \sa QQmlComponent, QQmlContext
569 Create a new QQmlEngine with the given \a parent.
571 QQmlEngine::QQmlEngine(QObject *parent)
572 : QJSEngine(*new QQmlEnginePrivate(this), parent)
579 Destroys the QQmlEngine.
581 Any QQmlContext's created on this engine will be
582 invalidated, but not destroyed (unless they are parented to the
585 QQmlEngine::~QQmlEngine()
588 if (d->isDebugging) {
589 QQmlEngineDebugService::instance()->remEngine(this);
592 // Emit onDestruction signals for the root context before
593 // we destroy the contexts, engine, Module APIs etc. that
594 // may be required to handle the destruction signal.
595 QQmlContextData::get(rootContext())->emitDestruction();
597 // if we are the parent of any of the qobject module api instances,
598 // we need to remove them from our internal list, in order to prevent
599 // a segfault in engine private dtor.
600 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
601 QObject *currQObjectApi = 0;
602 QQmlMetaType::ModuleApiInstance *currInstance = 0;
603 foreach (const QQmlMetaType::ModuleApi &key, keys) {
604 currInstance = d->moduleApiInstances.value(key);
605 currQObjectApi = currInstance->qobjectApi;
606 if (this->children().contains(currQObjectApi)) {
607 delete currQObjectApi;
609 d->moduleApiInstances.remove(key);
613 if (d->incubationController)
614 d->incubationController->d = 0;
617 /*! \fn void QQmlEngine::quit()
618 This signal is emitted when the QML loaded by the engine would like to quit.
621 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
622 This signal is emitted when \a warnings messages are generated by QML.
626 Clears the engine's internal component cache.
628 This function causes the property metadata of all components previously
629 loaded by the engine to be destroyed. All previously loaded components and
630 the property bindings for all extant objects created from those components will
633 This function returns the engine to a state where it does not contain any loaded
634 component data. This may be useful in order to reload a smaller subset of the
635 previous component set, or to load a new version of a previously loaded component.
637 Once the component cache has been cleared, components must be loaded before
638 any new objects can be created.
640 void QQmlEngine::clearComponentCache()
643 d->typeLoader.clearCache();
647 Returns the engine's root context.
649 The root context is automatically created by the QQmlEngine.
650 Data that should be available to all QML component instances
651 instantiated by the engine should be put in the root context.
653 Additional data that should only be available to a subset of
654 component instances should be added to sub-contexts parented to the
657 QQmlContext *QQmlEngine::rootContext() const
659 Q_D(const QQmlEngine);
660 return d->rootContext;
664 Sets the \a factory to use for creating QNetworkAccessManager(s).
666 QNetworkAccessManager is used for all network access by QML. By
667 implementing a factory it is possible to create custom
668 QNetworkAccessManager with specialized caching, proxy and cookie
671 The factory must be set before executing the engine.
673 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
676 QMutexLocker locker(&d->mutex);
677 d->networkAccessManagerFactory = factory;
681 Returns the current QQmlNetworkAccessManagerFactory.
683 \sa setNetworkAccessManagerFactory()
685 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
687 Q_D(const QQmlEngine);
688 return d->networkAccessManagerFactory;
691 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
694 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
696 void *args[] = { 0 };
697 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
701 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
703 QMutexLocker locker(&mutex);
704 QNetworkAccessManager *nam;
705 if (networkAccessManagerFactory) {
706 nam = networkAccessManagerFactory->create(parent);
708 nam = new QNetworkAccessManager(parent);
714 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
716 Q_Q(const QQmlEngine);
717 if (!networkAccessManager)
718 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
719 return networkAccessManager;
723 Returns a common QNetworkAccessManager which can be used by any QML
724 element instantiated by this engine.
726 If a QQmlNetworkAccessManagerFactory has been set and a
727 QNetworkAccessManager has not yet been created, the
728 QQmlNetworkAccessManagerFactory will be used to create the
729 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
730 will have no proxy or cache set.
732 \sa setNetworkAccessManagerFactory()
734 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
736 Q_D(const QQmlEngine);
737 return d->getNetworkAccessManager();
742 Sets the \a provider to use for images requested via the \e
743 image: url scheme, with host \a providerId. The QQmlEngine
744 takes ownership of \a provider.
746 Image providers enable support for pixmap and threaded image
747 requests. See the QQuickImageProvider documentation for details on
748 implementing and using image providers.
750 All required image providers should be added to the engine before any
751 QML sources files are loaded.
753 \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
755 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
758 QMutexLocker locker(&d->mutex);
759 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
763 Returns the image provider set for \a providerId.
765 Returns the provider if it was found; otherwise returns 0.
767 \sa QQuickImageProvider
769 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
771 Q_D(const QQmlEngine);
772 QMutexLocker locker(&d->mutex);
773 return d->imageProviders.value(providerId).data();
777 Removes the image provider for \a providerId.
779 \sa addImageProvider(), QQuickImageProvider
781 void QQmlEngine::removeImageProvider(const QString &providerId)
784 QMutexLocker locker(&d->mutex);
785 d->imageProviders.take(providerId);
789 Return the base URL for this engine. The base URL is only used to
790 resolve components when a relative URL is passed to the
791 QQmlComponent constructor.
793 If a base URL has not been explicitly set, this method returns the
794 application's current working directory.
798 QUrl QQmlEngine::baseUrl() const
800 Q_D(const QQmlEngine);
801 if (d->baseUrl.isEmpty()) {
802 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
809 Set the base URL for this engine to \a url.
813 void QQmlEngine::setBaseUrl(const QUrl &url)
820 Returns true if warning messages will be output to stderr in addition
821 to being emitted by the warnings() signal, otherwise false.
823 The default value is true.
825 bool QQmlEngine::outputWarningsToStandardError() const
827 Q_D(const QQmlEngine);
828 return d->outputWarningsToStdErr;
832 Set whether warning messages will be output to stderr to \a enabled.
834 If \a enabled is true, any warning messages generated by QML will be
835 output to stderr and emitted by the warnings() signal. If \a enabled
836 is false, on the warnings() signal will be emitted. This allows
837 applications to handle warning output themselves.
839 The default value is true.
841 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
844 d->outputWarningsToStdErr = enabled;
848 Attempt to free unused memory.
850 void QQmlEngine::collectGarbage()
856 Returns the QQmlContext for the \a object, or 0 if no
857 context has been set.
859 When the QQmlEngine instantiates a QObject, the context is
862 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
867 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
870 static_cast<QQmlData *>(priv->declarativeData);
874 else if (data->outerContext)
875 return data->outerContext->asQQmlContext();
881 Sets the QQmlContext for the \a object to \a context.
882 If the \a object already has a context, a warning is
883 output, but the context is not changed.
885 When the QQmlEngine instantiates a QObject, the context is
888 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
890 if (!object || !context)
893 QQmlData *data = QQmlData::get(object, true);
895 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
899 QQmlContextData *contextData = QQmlContextData::get(context);
900 contextData->addObject(object);
904 \enum QQmlEngine::ObjectOwnership
906 Ownership controls whether or not QML automatically destroys the
907 QObject when the object is garbage collected by the JavaScript
908 engine. The two ownership options are:
910 \value CppOwnership The object is owned by C++ code, and will
911 never be deleted by QML. The JavaScript destroy() method cannot be
912 used on objects with CppOwnership. This option is similar to
913 QScriptEngine::QtOwnership.
915 \value JavaScriptOwnership The object is owned by JavaScript.
916 When the object is returned to QML as the return value of a method
917 call or property access, QML will track it, and delete the object
918 if there are no remaining JavaScript references to it and it has no
919 QObject::parent(). An object tracked by one QQmlEngine
920 will be deleted during that QQmlEngine's destructor, and thus
921 JavaScript references between objects with JavaScriptOwnership from
922 two different engines will not be valid after the deletion of one of
923 those engines. This option is similar to QScriptEngine::ScriptOwnership.
925 Generally an application doesn't need to set an object's ownership
926 explicitly. QML uses a heuristic to set the default object
927 ownership. By default, an object that is created by QML has
928 JavaScriptOwnership. The exception to this are the root objects
929 created by calling QQmlComponent::create() or
930 QQmlComponent::beginCreate() which have CppOwnership by
931 default. The ownership of these root-level objects is considered to
932 have been transferred to the C++ caller.
934 Objects not-created by QML have CppOwnership by default. The
935 exception to this is objects returned from a C++ method call. The
936 ownership of these objects is passed to JavaScript.
938 Calling setObjectOwnership() overrides the default ownership
939 heuristic used by QML.
943 Sets the \a ownership of \a object.
945 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
950 QQmlData *ddata = QQmlData::get(object, true);
954 ddata->indestructible = (ownership == CppOwnership)?true:false;
955 ddata->explicitIndestructibleSet = true;
959 Returns the ownership of \a object.
961 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
966 QQmlData *ddata = QQmlData::get(object, false);
970 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
973 bool QQmlEngine::event(QEvent *e)
976 if (e->type() == QEvent::User)
977 d->doDeleteInEngineThread();
979 return QJSEngine::event(e);
982 void QQmlEnginePrivate::doDeleteInEngineThread()
984 QFieldList<Deletable, &Deletable::next> list;
986 list.copyAndClear(toDeleteInEngineThread);
989 while (Deletable *d = list.takeFirst())
993 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
995 QQmlData *data = QQmlData::get(object);
997 if (data && data->deferredComponent) {
998 QQmlObjectCreatingProfiler prof;
1000 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
1001 prof.setTypeName(type ? type->qmlTypeName()
1002 : QString::fromUtf8(object->metaObject()->className()));
1003 if (data->outerContext)
1004 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
1006 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
1008 QQmlComponentPrivate::ConstructionState state;
1009 QQmlComponentPrivate::beginDeferred(ep, object, &state);
1011 data->deferredComponent->release();
1012 data->deferredComponent = 0;
1014 QQmlComponentPrivate::complete(ep, &state);
1018 QQmlContext *qmlContext(const QObject *obj)
1020 return QQmlEngine::contextForObject(obj);
1023 QQmlEngine *qmlEngine(const QObject *obj)
1025 QQmlData *data = QQmlData::get(obj, false);
1026 if (!data || !data->context)
1028 return data->context->engine;
1031 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1033 QQmlData *data = QQmlData::get(object);
1035 return 0; // Attached properties are only on objects created by QML
1037 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1041 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1045 rv = pf(const_cast<QObject *>(object));
1048 data->attachedProperties()->insert(id, rv);
1053 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1054 const QMetaObject *attachedMetaObject, bool create)
1057 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1059 if (*idCache == -1 || !object)
1062 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1065 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1067 #ifndef QQML_NO_DEBUG_PROTOCOL
1068 if (!QQmlEnginePrivate::qml_debugging_enabled
1070 qDebug("QML debugging is enabled. Only use this in a safe environment.");
1072 QQmlEnginePrivate::qml_debugging_enabled = true;
1077 class QQmlDataExtended {
1080 ~QQmlDataExtended();
1082 QHash<int, QObject *> attachedProperties;
1083 QQmlNotifier objectNameNotifier;
1086 QQmlDataExtended::QQmlDataExtended()
1090 QQmlDataExtended::~QQmlDataExtended()
1094 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1097 layout(endpoint->next);
1099 int index = endpoint->sourceSignal;
1100 index = qMin(index, 0xFFFF - 1);
1102 endpoint->next = notifies[index];
1103 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1104 endpoint->prev = ¬ifies[index];
1105 notifies[index] = endpoint;
1108 void QQmlData::NotifyList::layout()
1110 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1113 QQmlNotifierEndpoint **old = notifies;
1114 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1115 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1116 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1117 sizeof(QQmlNotifierEndpoint*);
1118 memset(notifies + notifiesSize, 0, memsetSize);
1120 if (notifies != old) {
1121 for (int ii = 0; ii < notifiesSize; ++ii)
1123 notifies[ii]->prev = ¬ifies[ii];
1126 notifiesSize = maximumTodoIndex + 1;
1131 maximumTodoIndex = 0;
1135 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1138 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1139 notifyList->connectionMask = 0;
1140 notifyList->maximumTodoIndex = 0;
1141 notifyList->notifiesSize = 0;
1142 notifyList->todo = 0;
1143 notifyList->notifies = 0;
1146 Q_ASSERT(!endpoint->isConnected());
1148 index = qMin(index, 0xFFFF - 1);
1149 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1151 if (index < notifyList->notifiesSize) {
1153 endpoint->next = notifyList->notifies[index];
1154 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1155 endpoint->prev = ¬ifyList->notifies[index];
1156 notifyList->notifies[index] = endpoint;
1159 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1161 endpoint->next = notifyList->todo;
1162 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1163 endpoint->prev = ¬ifyList->todo;
1164 notifyList->todo = endpoint;
1168 bool QQml_isSignalConnected(QObject *obj, int signal_index, int index)
1170 QQmlData *data = QQmlData::get(obj);
1171 return QObjectPrivate::get(obj)->isSignalConnected(signal_index) || (data && data->signalHasEndpoint(index));
1175 index MUST be the index returned by QMetaMethod::index()
1176 This is different than the index returned by QObjectPrivate::signalIndex()
1178 bool QQmlData::signalHasEndpoint(int index)
1180 return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
1183 QQmlNotifier *QQmlData::objectNameNotifier() const
1185 if (!extendedData) extendedData = new QQmlDataExtended;
1186 return &extendedData->objectNameNotifier;
1189 QHash<int, QObject *> *QQmlData::attachedProperties() const
1191 if (!extendedData) extendedData = new QQmlDataExtended;
1192 return &extendedData->attachedProperties;
1195 void QQmlData::destroyed(QObject *object)
1197 if (deferredComponent)
1198 deferredComponent->release();
1200 if (nextContextObject)
1201 nextContextObject->prevContextObject = prevContextObject;
1202 if (prevContextObject)
1203 *prevContextObject = nextContextObject;
1205 QQmlAbstractBinding *binding = bindings;
1207 QQmlAbstractBinding *next = binding->m_nextBinding;
1208 binding->m_prevBinding = 0;
1209 binding->m_nextBinding = 0;
1214 QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1215 while (signalHandler) {
1216 QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1217 signalHandler->m_prevSignal = 0;
1218 signalHandler->m_nextSignal = 0;
1219 delete signalHandler;
1220 signalHandler = next;
1227 propertyCache->release();
1229 if (ownContext && context)
1233 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1234 *guard = (QObject *)0;
1235 guard->objectDestroyed(object);
1239 while (notifyList->todo)
1240 notifyList->todo->disconnect();
1241 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1242 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1245 free(notifyList->notifies);
1251 delete extendedData;
1253 v8object.Clear(); // The WeakReference handler will clean the actual handle
1259 void QQmlData::parentChanged(QObject *object, QObject *parent)
1265 void QQmlData::objectNameChanged(QObject *)
1267 if (extendedData) objectNameNotifier()->notify();
1270 bool QQmlData::hasBindingBit(int bit) const
1272 if (bindingBitsSize > bit)
1273 return bindingBits[bit / 32] & (1 << (bit % 32));
1278 void QQmlData::clearBindingBit(int bit)
1280 if (bindingBitsSize > bit)
1281 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1284 void QQmlData::setBindingBit(QObject *obj, int bit)
1286 if (bindingBitsSize <= bit) {
1287 int props = obj->metaObject()->propertyCount();
1288 Q_ASSERT(bit < props);
1290 int arraySize = (props + 31) / 32;
1291 int oldArraySize = bindingBitsSize / 32;
1293 bindingBits = (quint32 *)realloc(bindingBits,
1294 arraySize * sizeof(quint32));
1296 memset(bindingBits + oldArraySize,
1298 sizeof(quint32) * (arraySize - oldArraySize));
1300 bindingBitsSize = arraySize * 32;
1303 bindingBits[bit / 32] |= (1 << (bit % 32));
1306 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
1308 if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
1309 if (url.authority().isEmpty())
1310 return QLatin1Char(':') + url.path();
1313 return url.toLocalFile();
1317 static QString toLocalFile(const QString &url)
1319 if (!url.startsWith(QLatin1String("file://"), Qt::CaseInsensitive))
1322 QString file = url.mid(7);
1324 //XXX TODO: handle windows hostnames: "//servername/path/to/file.txt"
1326 // magic for drives on windows
1327 if (file.length() > 2 && file.at(0) == QLatin1Char('/') && file.at(2) == QLatin1Char(':'))
1333 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QString& url)
1335 if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) {
1336 if (url.length() > 4)
1337 return QLatin1Char(':') + url.mid(4);
1341 return toLocalFile(url);
1344 void QQmlEnginePrivate::sendQuit()
1348 if (q->receivers(SIGNAL(quit())) == 0) {
1349 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1353 static void dumpwarning(const QQmlError &error)
1355 qWarning().nospace() << qPrintable(error.toString());
1358 static void dumpwarning(const QList<QQmlError> &errors)
1360 for (int ii = 0; ii < errors.count(); ++ii)
1361 dumpwarning(errors.at(ii));
1364 void QQmlEnginePrivate::warning(const QQmlError &error)
1367 q->warnings(QList<QQmlError>() << error);
1368 if (outputWarningsToStdErr)
1372 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1375 q->warnings(errors);
1376 if (outputWarningsToStdErr)
1377 dumpwarning(errors);
1380 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1383 QQmlEnginePrivate::get(engine)->warning(error);
1388 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1391 QQmlEnginePrivate::get(engine)->warning(error);
1396 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1399 engine->warning(error);
1404 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1407 engine->warning(error);
1413 This function should be called prior to evaluation of any js expression,
1414 so that scarce resources are not freed prematurely (eg, if there is a
1415 nested javascript expression).
1417 void QQmlEnginePrivate::referenceScarceResources()
1419 scarceResourcesRefCount += 1;
1423 This function should be called after evaluation of the js expression is
1424 complete, and so the scarce resources may be freed safely.
1426 void QQmlEnginePrivate::dereferenceScarceResources()
1428 Q_ASSERT(scarceResourcesRefCount > 0);
1429 scarceResourcesRefCount -= 1;
1431 // if the refcount is zero, then evaluation of the "top level"
1432 // expression must have completed. We can safely release the
1433 // scarce resources.
1434 if (scarceResourcesRefCount == 0) {
1435 // iterate through the list and release them all.
1436 // note that the actual SRD is owned by the JS engine,
1437 // so we cannot delete the SRD; but we can free the
1438 // memory used by the variant in the SRD.
1439 while (ScarceResourceData *sr = scarceResources.first()) {
1440 sr->data = QVariant();
1441 scarceResources.remove(sr);
1447 Adds \a path as a directory where the engine searches for
1448 installed modules in a URL-based directory structure.
1449 The \a path may be a local filesystem directory or a URL.
1451 The newly added \a path will be first in the importPathList().
1453 \sa setImportPathList(), {QML Modules}
1455 void QQmlEngine::addImportPath(const QString& path)
1458 d->importDatabase.addImportPath(path);
1462 Returns the list of directories where the engine searches for
1463 installed modules in a URL-based directory structure.
1465 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1466 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1467 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1468 provided by that module. A \c qmldir file is required for defining the
1469 type version mapping and possibly QML extensions plugins.
1471 By default, the list contains the directory of the application executable,
1472 paths specified in the \c QML_IMPORT_PATH environment variable,
1473 and the builtin \c ImportsPath from QLibraryInfo.
1475 \sa addImportPath(), setImportPathList()
1477 QStringList QQmlEngine::importPathList() const
1479 Q_D(const QQmlEngine);
1480 return d->importDatabase.importPathList();
1484 Sets \a paths as the list of directories where the engine searches for
1485 installed modules in a URL-based directory structure.
1487 By default, the list contains the directory of the application executable,
1488 paths specified in the \c QML_IMPORT_PATH environment variable,
1489 and the builtin \c ImportsPath from QLibraryInfo.
1491 \sa importPathList(), addImportPath()
1493 void QQmlEngine::setImportPathList(const QStringList &paths)
1496 d->importDatabase.setImportPathList(paths);
1501 Adds \a path as a directory where the engine searches for
1502 native plugins for imported modules (referenced in the \c qmldir file).
1504 By default, the list contains only \c ., i.e. the engine searches
1505 in the directory of the \c qmldir file itself.
1507 The newly added \a path will be first in the pluginPathList().
1509 \sa setPluginPathList()
1511 void QQmlEngine::addPluginPath(const QString& path)
1514 d->importDatabase.addPluginPath(path);
1519 Returns the list of directories where the engine searches for
1520 native plugins for imported modules (referenced in the \c qmldir file).
1522 By default, the list contains only \c ., i.e. the engine searches
1523 in the directory of the \c qmldir file itself.
1525 \sa addPluginPath(), setPluginPathList()
1527 QStringList QQmlEngine::pluginPathList() const
1529 Q_D(const QQmlEngine);
1530 return d->importDatabase.pluginPathList();
1534 Sets the list of directories where the engine searches for
1535 native plugins for imported modules (referenced in the \c qmldir file)
1538 By default, the list contains only \c ., i.e. the engine searches
1539 in the directory of the \c qmldir file itself.
1541 \sa pluginPathList(), addPluginPath()
1543 void QQmlEngine::setPluginPathList(const QStringList &paths)
1546 d->importDatabase.setPluginPathList(paths);
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, the \a errors list will have any errors which occurred prepended to it.
1555 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1557 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1560 return d->importDatabase.importPlugin(filePath, uri, errors);
1564 Imports the plugin named \a filePath with the \a uri provided.
1565 Returns true if the plugin was successfully imported; otherwise returns false.
1567 On failure and if non-null, *\a errorString will be set to a message describing the failure.
1569 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1571 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1574 QList<QQmlError> errors;
1575 bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1576 if (!errors.isEmpty()) {
1578 for (int i = 0; i < errors.size(); ++i) {
1579 builtError = QString(QLatin1String("%1\n %2"))
1581 .arg(errors.at(i).toString());
1583 *errorString = builtError;
1589 \property QQmlEngine::offlineStoragePath
1590 \brief the directory for storing offline user data
1592 Returns the directory where SQL and other offline
1595 QQuickWebView and the SQL databases created with openDatabase()
1598 The default is QML/OfflineStorage in the platform-standard
1599 user application data directory.
1601 Note that the path may not currently exist on the filesystem, so
1602 callers wanting to \e create new files at this location should create
1603 it first - see QDir::mkpath().
1605 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1608 d->offlineStoragePath = dir;
1611 QString QQmlEngine::offlineStoragePath() const
1613 Q_D(const QQmlEngine);
1614 return d->offlineStoragePath;
1617 static void voidptr_destructor(void *v)
1619 void **ptr = (void **)v;
1623 static void *voidptr_constructor(const void *v)
1628 return new void*(*(void **)v);
1632 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1636 if (!mo->superClass()) {
1637 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1638 propertyCache.insert(mo, rv);
1641 QQmlPropertyCache *super = cache(mo->superClass());
1642 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1643 propertyCache.insert(mo, rv);
1648 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1651 QList<QQmlType *> types;
1653 int maxMinorVersion = 0;
1655 const QMetaObject *metaObject = type->metaObject();
1657 while (metaObject) {
1658 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1659 type->majorVersion(), minorVersion);
1661 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1667 metaObject = metaObject->superClass();
1670 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1672 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1676 QQmlPropertyCache *raw = cache(type->metaObject());
1678 bool hasCopied = false;
1680 for (int ii = 0; ii < types.count(); ++ii) {
1681 QQmlType *currentType = types.at(ii);
1685 int rev = currentType->metaObjectRevision();
1686 int moIndex = types.count() - 1 - ii;
1688 if (raw->allowedRevisionCache[moIndex] != rev) {
1693 raw->allowedRevisionCache[moIndex] = rev;
1697 // Test revision compatibility - the basic rule is:
1698 // * Anything that is excluded, cannot overload something that is not excluded *
1700 // Signals override:
1701 // * other signals and methods of the same name.
1702 // * properties named on<Signal Name>
1703 // * automatic <property name>Changed notify signals
1705 // Methods override:
1706 // * other methods of the same name
1708 // Properties override:
1709 // * other elements of the same name
1711 bool overloadError = false;
1712 QString overloadName;
1715 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1716 !overloadError && iter != raw->stringCache.end();
1719 QQmlPropertyData *d = *iter;
1720 if (raw->isAllowedInRevision(d))
1721 continue; // Not excluded - no problems
1723 // check that a regular "name" overload isn't happening
1724 QQmlPropertyData *current = d;
1725 while (!overloadError && current) {
1726 current = d->overrideData(current);
1727 if (current && raw->isAllowedInRevision(current))
1728 overloadError = true;
1733 if (overloadError) {
1734 if (hasCopied) raw->release();
1736 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."));
1740 if (!hasCopied) raw->addref();
1741 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1743 if (minorVersion != maxMinorVersion) {
1745 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1751 QQmlMetaType::ModuleApiInstance *
1752 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1754 Locker locker(this);
1756 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1758 a = new QQmlMetaType::ModuleApiInstance;
1759 a->scriptCallback = module.script;
1760 a->qobjectCallback = module.qobject;
1761 a->instanceMetaObject = module.instanceMetaObject;
1762 moduleApiInstances.insert(module, a);
1768 bool QQmlEnginePrivate::isQObject(int t)
1770 Locker locker(this);
1771 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1774 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1776 Locker locker(this);
1777 int t = v.userType();
1778 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1780 return *(QObject **)(v.constData());
1782 return QQmlMetaType::toQObject(v, ok);
1786 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1788 Locker locker(this);
1789 if (m_compositeTypes.contains(t))
1790 return QQmlMetaType::Object;
1791 else if (m_qmlLists.contains(t))
1792 return QQmlMetaType::List;
1794 return QQmlMetaType::typeCategory(t);
1797 bool QQmlEnginePrivate::isList(int t) const
1799 Locker locker(this);
1800 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1803 int QQmlEnginePrivate::listType(int t) const
1805 Locker locker(this);
1806 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1807 if (iter != m_qmlLists.end())
1810 return QQmlMetaType::listType(t);
1813 const QMetaObject *QQmlEnginePrivate::rawMetaObjectForType(int t) const
1815 Locker locker(this);
1816 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1817 if (iter != m_compositeTypes.end()) {
1818 return (*iter)->root;
1820 QQmlType *type = QQmlMetaType::qmlType(t);
1821 return type?type->baseMetaObject():0;
1825 const QMetaObject *QQmlEnginePrivate::metaObjectForType(int t) const
1827 Locker locker(this);
1828 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1829 if (iter != m_compositeTypes.end()) {
1830 return (*iter)->root;
1832 QQmlType *type = QQmlMetaType::qmlType(t);
1833 return type?type->metaObject():0;
1837 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1839 QByteArray name = data->root->className();
1841 QByteArray ptr = name + '*';
1842 QByteArray lst = "QQmlListProperty<" + name + '>';
1844 int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
1845 voidptr_constructor);
1846 int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
1847 voidptr_constructor);
1851 Locker locker(this);
1852 m_qmlLists.insert(lst_type, ptr_type);
1853 m_compositeTypes.insert(ptr_type, data);
1856 bool QQml_isFileCaseCorrect(const QString &fileName)
1858 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1859 QFileInfo info(fileName);
1860 const QString absolute = info.absoluteFilePath();
1862 #if defined(Q_OS_MAC)
1863 const QString canonical = info.canonicalFilePath();
1864 #elif defined(Q_OS_WIN)
1865 wchar_t buffer[1024];
1867 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1868 if (rv == 0 || rv >= 1024) return true;
1869 rv = ::GetLongPathName(buffer, buffer, 1024);
1870 if (rv == 0 || rv >= 1024) return true;
1872 const QString canonical = QString::fromWCharArray(buffer);
1875 const int absoluteLength = absolute.length();
1876 const int canonicalLength = canonical.length();
1878 const int length = qMin(absoluteLength, canonicalLength);
1879 for (int ii = 0; ii < length; ++ii) {
1880 const QChar &a = absolute.at(absoluteLength - 1 - ii);
1881 const QChar &c = canonical.at(canonicalLength - 1 - ii);
1883 if (a.toLower() != c.toLower())
1895 \fn QQmlEngine *qmlEngine(const QObject *object)
1898 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
1899 QQmlEngine::contextForObject(object)->engine(), but more efficient.
1903 \fn QQmlContext *qmlContext(const QObject *object)
1906 Returns the QQmlContext associated with \a object, if any. This is equivalent to
1907 QQmlEngine::contextForObject(object).