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 "qqmlimageprovider.h"
63 #include "qqmldirparser_p.h"
64 #include "qqmlextensioninterface.h"
65 #include "qqmllist_p.h"
66 #include "qqmltypenamecache_p.h"
67 #include "qqmlnotifier_p.h"
68 #include <private/qqmlprofilerservice_p.h>
69 #include <private/qquickapplication_p.h>
70 #include <private/qv8debugservice_p.h>
71 #include <private/qdebugmessageservice_p.h>
72 #include "qqmlincubator.h"
73 #include <private/qv8profilerservice_p.h>
74 #include <private/qqmlboundsignal_p.h>
76 #include <QtCore/qstandardpaths.h>
77 #include <QtCore/qsettings.h>
79 #include <QtCore/qmetaobject.h>
80 #include <QNetworkAccessManager>
82 #include <QMetaObject>
83 #include <QtCore/qcoreapplication.h>
84 #include <QtCore/qdir.h>
85 #include <QtCore/qmutex.h>
86 #include <QtNetwork/qnetworkconfigmanager.h>
88 #include <private/qobject_p.h>
90 #include <private/qqmllocale_p.h>
92 #ifdef Q_OS_WIN // for %APPDATA%
93 #include <qt_windows.h>
97 #define CSIDL_APPDATA 0x001a // <username>\Application Data
100 Q_DECLARE_METATYPE(QQmlProperty)
104 void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
106 QQmlEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
107 QQmlValueTypeFactory::registerBaseTypes(uri, versionMajor, versionMinor);
111 \qmlclass QtObject QObject
112 \ingroup qml-utility-elements
114 \brief The QtObject element is the most basic element in QML.
116 The QtObject element is a non-visual element which contains only the
119 It can be useful to create a QtObject if you need an extremely
120 lightweight element to enclose a set of custom properties:
122 \snippet doc/src/snippets/qml/qtobject.qml 0
124 It can also be useful for C++ integration, as it is just a plain
125 QObject. See the QObject documentation for further details.
128 \qmlproperty string QtObject::objectName
129 This property holds the QObject::objectName for this specific object instance.
131 This allows a C++ application to locate an item within a QML component
132 using the QObject::findChild() method. For example, the following C++
133 application locates the child \l Rectangle item and dynamically changes its
142 width: 200; height: 200
156 view.setSource(QUrl::fromLocalFile("MyRect.qml"));
159 QQuickItem *item = view.rootObject()->findChild<QQuickItem*>("myRect");
161 item->setProperty("color", QColor(Qt::yellow));
165 bool QQmlEnginePrivate::qml_debugging_enabled = false;
167 void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
169 qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
170 qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
171 qmlRegisterType<QQuickListElement>(uri, versionMajor, versionMinor,"ListElement");
172 qmlRegisterCustomType<QQuickListModel>(uri, versionMajor, versionMinor,"ListModel", new QQuickListModelParser);
173 qmlRegisterType<QQuickWorkerScript>(uri,versionMajor,versionMinor,"WorkerScript");
176 void QQmlEnginePrivate::defineModule()
178 registerBaseTypes("QtQuick", 2, 0);
179 qmlRegisterUncreatableType<QQuickApplication>("QtQuick",2,0,"Application", QQuickApplication::tr("Application is an abstract class"));
180 qmlRegisterUncreatableType<QQmlLocale>("QtQuick",2,0,"Locale",QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
184 \qmlclass Qt QQmlEnginePrivate
185 \ingroup qml-utility-elements
186 \brief The QML global Qt object provides useful enums and functions from Qt.
188 \keyword QmlGlobalQtObject
190 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
192 The \c Qt object is a global object with utility functions, properties and enums.
194 It is not instantiable; to use it, call the members of the global \c Qt object directly.
201 color: Qt.rgba(1, 0, 0, 1)
202 text: Qt.md5("hello, world")
209 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
210 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
214 The Qt object also contains helper functions for creating objects of specific
215 data types. This is primarily useful when setting the properties of an item
216 when the property has one of the following types:
219 \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()}
220 \li \c rect - use \l{Qt::rect()}{Qt.rect()}
221 \li \c point - use \l{Qt::point()}{Qt.point()}
222 \li \c size - use \l{Qt::size()}{Qt.size()}
223 \li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
226 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
228 \section1 Date/Time Formatters
230 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
233 \li \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
234 \li \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
235 \li \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
238 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
241 \section1 Dynamic Object Creation
242 The following functions on the global object allow you to dynamically create QML
243 items from files or strings. See \l{Dynamic Object Management in QML} for an overview
247 \li \l{Qt::createComponent()}{object Qt.createComponent(url)}
248 \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
254 \qmlproperty object Qt::application
257 The \c application object provides access to global application state
258 properties shared by many QML components.
264 \li \c application.active
266 This read-only property indicates whether the application is the top-most and focused
267 application, and the user is able to interact with the application. The property
268 is false when the application is in the background, the device keylock or screen
269 saver is active, the screen backlight is turned off, or the global system dialog
270 is being displayed on top of the application. It can be used for stopping and
271 pausing animations, timers and active processing of data in order to save device
272 battery power and free device memory and processor load when the application is not
276 \li \c application.layoutDirection
278 This read-only property can be used to query the default layout direction of the
279 application. On system start-up, the default layout direction depends on the
280 application's language. The property has a value of \c Qt.RightToLeft in locales
281 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
282 where the reading direction flows from left to right. You can bind to this
283 property to customize your application layouts to support both layout directions.
288 \li Qt.LeftToRight - Text and graphics elements should be positioned
290 \li Qt.RightToLeft - Text and graphics elements should be positioned
295 \li \c application.inputPanel
297 This read-only property allows access to application's QInputPanel object
298 and all its properties and slots. See the QInputPanel documentation for
299 further details. Deprecated in favor of Qt.InputMethod
302 The following example uses the \c application object to indicate
303 whether the application is currently active:
305 \snippet doc/src/snippets/qml/application.qml document
307 \qmlproperty object Qt::inputMethod
310 The \c inputMethod object allows access to application's QInputMethod object
311 and all its properties and slots. See the QInputMethod documentation for
317 \qmlmethod object Qt::include(string url, jsobject callback)
319 Includes another JavaScript file. This method can only be used from within JavaScript files,
320 and not regular QML files.
322 This imports all functions from \a url into the current script's namespace.
324 Qt.include() returns an object that describes the status of the operation. The object has
325 a single property, \c {status}, that is set to one of the following values:
328 \header \li Symbol \li Value \li Description
329 \row \li result.OK \li 0 \li The include completed successfully.
330 \row \li result.LOADING \li 1 \li Data is being loaded from the network.
331 \row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
332 \row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
333 An additional \c exception property will be set in this case.
336 The \c status property will be updated as the operation progresses.
338 If provided, \a callback is invoked when the operation completes. The callback is passed
339 the same object as is returned from the Qt.include() call.
341 // Qt.include() is implemented in qv8include.cpp
344 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
345 : propertyCapture(0), rootContext(0), isDebugging(false),
346 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
347 cleanup(0), erroredBindings(0), inProgressCreations(0),
348 workerScriptEngine(0), activeVME(0),
349 networkAccessManager(0), networkAccessManagerFactory(0),
350 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
351 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
355 QQmlEnginePrivate::~QQmlEnginePrivate()
357 if (inProgressCreations)
358 qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
361 QQmlCleanup *c = cleanup;
363 if (cleanup) cleanup->prev = &cleanup;
369 doDeleteInEngineThread();
371 if (incubationController) incubationController->d = 0;
372 incubationController = 0;
377 for(QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
379 for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
381 for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
383 for(QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
384 delete (*iter)->qobjectApi;
389 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
391 QObjectPrivate *p = QObjectPrivate::get(o);
392 if (p->declarativeData) {
393 QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
394 if (d->ownContext && d->context) {
395 d->context->destroy();
401 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
403 static_cast<QQmlData *>(d)->destroyed(o);
406 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
408 static_cast<QQmlData *>(d)->parentChanged(o, p);
411 void QQmlData::objectNameChanged(QAbstractDeclarativeData *d, QObject *o)
413 static_cast<QQmlData *>(d)->objectNameChanged(o);
416 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **)
418 QQmlData *ddata = QQmlData::get(object, false);
419 if (!ddata) return; // Probably being deleted
421 QQmlNotifierEndpoint *ep = ddata->notify(index);
422 if (ep) QQmlNotifier::emitNotify(ep);
425 void QQmlEnginePrivate::init()
429 static bool firstTime = true;
431 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component");
436 qRegisterMetaType<QVariant>("QVariant");
437 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
438 qRegisterMetaType<QJSValue>("QJSValue");
439 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
440 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
441 qRegisterMetaType<QList<int> >("QList<int>");
442 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
446 v8engine()->setEngine(q);
448 rootContext = new QQmlContext(q,true);
450 if (QCoreApplication::instance()->thread() == q->thread() &&
451 QQmlEngineDebugService::isDebuggingEnabled()) {
453 QQmlEngineDebugService::instance()->addEngine(q);
454 QV8DebugService::initialize(v8engine());
455 QV8ProfilerService::initialize();
456 QQmlProfilerService::initialize();
457 QDebugMessageService::instance();
460 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
461 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator()) +
462 QDir::separator() + QLatin1String("QML") +
463 QDir::separator() + QLatin1String("OfflineStorage");
466 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
469 if (!workerScriptEngine)
470 workerScriptEngine = new QQuickWorkerScriptEngine(q);
471 return workerScriptEngine;
478 \brief The QQmlEngine class provides an environment for instantiating QML components.
481 Each QML component is instantiated in a QQmlContext.
482 QQmlContext's are essential for passing data to QML
483 components. In QML, contexts are arranged hierarchically and this
484 hierarchy is managed by the QQmlEngine.
486 Prior to creating any QML components, an application must have
487 created a QQmlEngine to gain access to a QML context. The
488 following example shows how to create a simple Text item.
492 QQmlComponent component(&engine);
493 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
494 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
496 //add item to view, etc
500 In this case, the Text item will be created in the engine's
501 \l {QQmlEngine::rootContext()}{root context}.
503 Note that the QtQuick 1 version is called QDeclarativeEngine.
505 \sa QQmlComponent QQmlContext
509 Create a new QQmlEngine with the given \a parent.
511 QQmlEngine::QQmlEngine(QObject *parent)
512 : QJSEngine(*new QQmlEnginePrivate(this), parent)
519 Destroys the QQmlEngine.
521 Any QQmlContext's created on this engine will be
522 invalidated, but not destroyed (unless they are parented to the
525 QQmlEngine::~QQmlEngine()
528 if (d->isDebugging) {
529 QQmlEngineDebugService::instance()->remEngine(this);
532 // if we are the parent of any of the qobject module api instances,
533 // we need to remove them from our internal list, in order to prevent
534 // a segfault in engine private dtor.
535 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
536 QObject *currQObjectApi = 0;
537 QQmlMetaType::ModuleApiInstance *currInstance = 0;
538 foreach (const QQmlMetaType::ModuleApi &key, keys) {
539 currInstance = d->moduleApiInstances.value(key);
540 currQObjectApi = currInstance->qobjectApi;
541 if (this->children().contains(currQObjectApi)) {
542 delete currQObjectApi;
544 d->moduleApiInstances.remove(key);
548 // ensure we clean up QObjects with JS ownership
551 if (d->incubationController)
552 d->incubationController->d = 0;
555 /*! \fn void QQmlEngine::quit()
556 This signal is emitted when the QML loaded by the engine would like to quit.
559 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
560 This signal is emitted when \a warnings messages are generated by QML.
564 Clears the engine's internal component cache.
566 This function causes the property metadata of all components previously
567 loaded by the engine to be destroyed. All previously loaded components and
568 the property bindings for all extant objects created from those components will
571 This function returns the engine to a state where it does not contain any loaded
572 component data. This may be useful in order to reload a smaller subset of the
573 previous component set, or to load a new version of a previously loaded component.
575 Once the component cache has been cleared, components must be loaded before
576 any new objects can be created.
578 void QQmlEngine::clearComponentCache()
581 d->typeLoader.clearCache();
585 Returns the engine's root context.
587 The root context is automatically created by the QQmlEngine.
588 Data that should be available to all QML component instances
589 instantiated by the engine should be put in the root context.
591 Additional data that should only be available to a subset of
592 component instances should be added to sub-contexts parented to the
595 QQmlContext *QQmlEngine::rootContext() const
597 Q_D(const QQmlEngine);
598 return d->rootContext;
602 Sets the \a factory to use for creating QNetworkAccessManager(s).
604 QNetworkAccessManager is used for all network access by QML. By
605 implementing a factory it is possible to create custom
606 QNetworkAccessManager with specialized caching, proxy and cookie
609 The factory must be set before executing the engine.
611 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
614 QMutexLocker locker(&d->mutex);
615 d->networkAccessManagerFactory = factory;
619 Returns the current QQmlNetworkAccessManagerFactory.
621 \sa setNetworkAccessManagerFactory()
623 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
625 Q_D(const QQmlEngine);
626 return d->networkAccessManagerFactory;
629 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
632 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
634 void *args[] = { 0 };
635 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
639 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
641 QMutexLocker locker(&mutex);
642 QNetworkAccessManager *nam;
643 if (networkAccessManagerFactory) {
644 nam = networkAccessManagerFactory->create(parent);
646 nam = new QNetworkAccessManager(parent);
652 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
654 Q_Q(const QQmlEngine);
655 if (!networkAccessManager)
656 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
657 return networkAccessManager;
661 Returns a common QNetworkAccessManager which can be used by any QML
662 element instantiated by this engine.
664 If a QQmlNetworkAccessManagerFactory has been set and a
665 QNetworkAccessManager has not yet been created, the
666 QQmlNetworkAccessManagerFactory will be used to create the
667 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
668 will have no proxy or cache set.
670 \sa setNetworkAccessManagerFactory()
672 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
674 Q_D(const QQmlEngine);
675 return d->getNetworkAccessManager();
680 Sets the \a provider to use for images requested via the \e
681 image: url scheme, with host \a providerId. The QQmlEngine
682 takes ownership of \a provider.
684 Image providers enable support for pixmap and threaded image
685 requests. See the QQmlImageProvider documentation for details on
686 implementing and using image providers.
688 All required image providers should be added to the engine before any
689 QML sources files are loaded.
691 \sa removeImageProvider()
693 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProvider *provider)
696 QMutexLocker locker(&d->mutex);
697 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProvider>(provider));
701 Returns the QQmlImageProvider set for \a providerId.
703 Returns the provider if it was found; otherwise returns 0.
705 QQmlImageProvider *QQmlEngine::imageProvider(const QString &providerId) const
707 Q_D(const QQmlEngine);
708 QMutexLocker locker(&d->mutex);
709 return d->imageProviders.value(providerId).data();
713 Removes the QQmlImageProvider for \a providerId.
715 \sa addImageProvider()
717 void QQmlEngine::removeImageProvider(const QString &providerId)
720 QMutexLocker locker(&d->mutex);
721 d->imageProviders.take(providerId);
724 QQmlImageProvider::ImageType QQmlEnginePrivate::getImageProviderType(const QUrl &url)
726 QMutexLocker locker(&mutex);
727 QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
730 return provider->imageType();
731 return QQmlImageProvider::Invalid;
734 QQuickTextureFactory *QQmlEnginePrivate::getTextureFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
736 QMutexLocker locker(&mutex);
737 QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
740 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
741 return provider->requestTexture(imageId, size, req_size);
746 QImage QQmlEnginePrivate::getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
748 QMutexLocker locker(&mutex);
750 QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
753 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
754 image = provider->requestImage(imageId, size, req_size);
759 QPixmap QQmlEnginePrivate::getPixmapFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
761 QMutexLocker locker(&mutex);
763 QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
766 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
767 pixmap = provider->requestPixmap(imageId, size, req_size);
773 Return the base URL for this engine. The base URL is only used to
774 resolve components when a relative URL is passed to the
775 QQmlComponent constructor.
777 If a base URL has not been explicitly set, this method returns the
778 application's current working directory.
782 QUrl QQmlEngine::baseUrl() const
784 Q_D(const QQmlEngine);
785 if (d->baseUrl.isEmpty()) {
786 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
793 Set the base URL for this engine to \a url.
797 void QQmlEngine::setBaseUrl(const QUrl &url)
804 Returns true if warning messages will be output to stderr in addition
805 to being emitted by the warnings() signal, otherwise false.
807 The default value is true.
809 bool QQmlEngine::outputWarningsToStandardError() const
811 Q_D(const QQmlEngine);
812 return d->outputWarningsToStdErr;
816 Set whether warning messages will be output to stderr to \a enabled.
818 If \a enabled is true, any warning messages generated by QML will be
819 output to stderr and emitted by the warnings() signal. If \a enabled
820 is false, on the warnings() signal will be emitted. This allows
821 applications to handle warning output themselves.
823 The default value is true.
825 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
828 d->outputWarningsToStdErr = enabled;
832 Attempt to free unused memory.
834 void QQmlEngine::collectGarbage()
840 Returns the QQmlContext for the \a object, or 0 if no
841 context has been set.
843 When the QQmlEngine instantiates a QObject, the context is
846 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
851 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
854 static_cast<QQmlData *>(priv->declarativeData);
858 else if (data->outerContext)
859 return data->outerContext->asQQmlContext();
865 Sets the QQmlContext for the \a object to \a context.
866 If the \a object already has a context, a warning is
867 output, but the context is not changed.
869 When the QQmlEngine instantiates a QObject, the context is
872 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
874 if (!object || !context)
877 QQmlData *data = QQmlData::get(object, true);
879 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
883 QQmlContextData *contextData = QQmlContextData::get(context);
884 contextData->addObject(object);
888 \enum QQmlEngine::ObjectOwnership
890 Ownership controls whether or not QML automatically destroys the
891 QObject when the object is garbage collected by the JavaScript
892 engine. The two ownership options are:
894 \value CppOwnership The object is owned by C++ code, and will
895 never be deleted by QML. The JavaScript destroy() method cannot be
896 used on objects with CppOwnership. This option is similar to
897 QScriptEngine::QtOwnership.
899 \value JavaScriptOwnership The object is owned by JavaScript.
900 When the object is returned to QML as the return value of a method
901 call or property access, QML will delete the object if there are no
902 remaining JavaScript references to it and it has no
903 QObject::parent(). This option is similar to
904 QScriptEngine::ScriptOwnership.
906 Generally an application doesn't need to set an object's ownership
907 explicitly. QML uses a heuristic to set the default object
908 ownership. By default, an object that is created by QML has
909 JavaScriptOwnership. The exception to this are the root objects
910 created by calling QQmlComponent::create() or
911 QQmlComponent::beginCreate() which have CppOwnership by
912 default. The ownership of these root-level objects is considered to
913 have been transferred to the C++ caller.
915 Objects not-created by QML have CppOwnership by default. The
916 exception to this is objects returned from a C++ method call. The
917 ownership of these objects is passed to JavaScript.
919 Calling setObjectOwnership() overrides the default ownership
920 heuristic used by QML.
924 Sets the \a ownership of \a object.
926 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
931 QQmlData *ddata = QQmlData::get(object, true);
935 ddata->indestructible = (ownership == CppOwnership)?true:false;
936 ddata->explicitIndestructibleSet = true;
940 Returns the ownership of \a object.
942 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
947 QQmlData *ddata = QQmlData::get(object, false);
951 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
954 bool QQmlEngine::event(QEvent *e)
957 if (e->type() == QEvent::User)
958 d->doDeleteInEngineThread();
960 return QJSEngine::event(e);
963 void QQmlEnginePrivate::doDeleteInEngineThread()
965 QFieldList<Deletable, &Deletable::next> list;
967 list.copyAndClear(toDeleteInEngineThread);
970 while (Deletable *d = list.takeFirst())
974 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
976 QQmlData *data = QQmlData::get(object);
978 if (data && data->deferredComponent) {
979 QQmlObjectCreatingProfiler prof;
981 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
982 prof.setTypeName(type ? type->qmlTypeName()
983 : QString::fromUtf8(object->metaObject()->className()));
984 if (data->outerContext)
985 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
987 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
989 QQmlComponentPrivate::ConstructionState state;
990 QQmlComponentPrivate::beginDeferred(ep, object, &state);
992 data->deferredComponent->release();
993 data->deferredComponent = 0;
995 QQmlComponentPrivate::complete(ep, &state);
999 QQmlContext *qmlContext(const QObject *obj)
1001 return QQmlEngine::contextForObject(obj);
1004 QQmlEngine *qmlEngine(const QObject *obj)
1006 QQmlData *data = QQmlData::get(obj, false);
1007 if (!data || !data->context)
1009 return data->context->engine;
1012 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1014 QQmlData *data = QQmlData::get(object);
1016 return 0; // Attached properties are only on objects created by QML
1018 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1022 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1026 rv = pf(const_cast<QObject *>(object));
1029 data->attachedProperties()->insert(id, rv);
1034 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1035 const QMetaObject *attachedMetaObject, bool create)
1038 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1040 if (*idCache == -1 || !object)
1043 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1046 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1048 #ifndef QQML_NO_DEBUG_PROTOCOL
1049 if (!QQmlEnginePrivate::qml_debugging_enabled
1051 qDebug("QML debugging is enabled. Only use this in a safe environment.");
1053 QQmlEnginePrivate::qml_debugging_enabled = true;
1058 class QQmlDataExtended {
1061 ~QQmlDataExtended();
1063 QHash<int, QObject *> attachedProperties;
1064 QQmlNotifier objectNameNotifier;
1067 QQmlDataExtended::QQmlDataExtended()
1071 QQmlDataExtended::~QQmlDataExtended()
1075 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1078 layout(endpoint->next);
1080 int index = endpoint->sourceSignal;
1081 index = qMin(index, 0xFFFF - 1);
1083 endpoint->next = notifies[index];
1084 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1085 endpoint->prev = ¬ifies[index];
1086 notifies[index] = endpoint;
1089 void QQmlData::NotifyList::layout()
1091 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1094 QQmlNotifierEndpoint **old = notifies;
1095 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1096 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1097 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1098 sizeof(QQmlNotifierEndpoint*);
1099 memset(notifies + notifiesSize, 0, memsetSize);
1101 if (notifies != old) {
1102 for (int ii = 0; ii < notifiesSize; ++ii)
1104 notifies[ii]->prev = ¬ifies[ii];
1107 notifiesSize = maximumTodoIndex + 1;
1112 maximumTodoIndex = 0;
1116 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1119 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1120 notifyList->connectionMask = 0;
1121 notifyList->maximumTodoIndex = 0;
1122 notifyList->notifiesSize = 0;
1123 notifyList->todo = 0;
1124 notifyList->notifies = 0;
1127 Q_ASSERT(!endpoint->isConnected());
1129 index = qMin(index, 0xFFFF - 1);
1130 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1132 if (index < notifyList->notifiesSize) {
1134 endpoint->next = notifyList->notifies[index];
1135 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1136 endpoint->prev = ¬ifyList->notifies[index];
1137 notifyList->notifies[index] = endpoint;
1140 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1142 endpoint->next = notifyList->todo;
1143 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1144 endpoint->prev = ¬ifyList->todo;
1145 notifyList->todo = endpoint;
1149 QQmlNotifier *QQmlData::objectNameNotifier() const
1151 if (!extendedData) extendedData = new QQmlDataExtended;
1152 return &extendedData->objectNameNotifier;
1155 QHash<int, QObject *> *QQmlData::attachedProperties() const
1157 if (!extendedData) extendedData = new QQmlDataExtended;
1158 return &extendedData->attachedProperties;
1161 void QQmlData::destroyed(QObject *object)
1163 if (deferredComponent)
1164 deferredComponent->release();
1166 if (nextContextObject)
1167 nextContextObject->prevContextObject = prevContextObject;
1168 if (prevContextObject)
1169 *prevContextObject = nextContextObject;
1171 QQmlAbstractBinding *binding = bindings;
1173 QQmlAbstractBinding *next = binding->m_nextBinding;
1174 binding->m_prevBinding = 0;
1175 binding->m_nextBinding = 0;
1180 QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1181 while (signalHandler) {
1182 QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1183 signalHandler->m_prevSignal = 0;
1184 signalHandler->m_nextSignal = 0;
1185 delete signalHandler;
1186 signalHandler = next;
1193 propertyCache->release();
1195 if (ownContext && context)
1199 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1200 *guard = (QObject *)0;
1201 guard->objectDestroyed(object);
1205 while (notifyList->todo)
1206 notifyList->todo->disconnect();
1207 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1208 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1211 free(notifyList->notifies);
1216 delete extendedData;
1218 v8object.Clear(); // The WeakReference handler will clean the actual handle
1224 void QQmlData::parentChanged(QObject *object, QObject *parent)
1230 void QQmlData::objectNameChanged(QObject *)
1232 if (extendedData) objectNameNotifier()->notify();
1235 bool QQmlData::hasBindingBit(int bit) const
1237 if (bindingBitsSize > bit)
1238 return bindingBits[bit / 32] & (1 << (bit % 32));
1243 void QQmlData::clearBindingBit(int bit)
1245 if (bindingBitsSize > bit)
1246 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1249 void QQmlData::setBindingBit(QObject *obj, int bit)
1251 if (bindingBitsSize <= bit) {
1252 int props = obj->metaObject()->propertyCount();
1253 Q_ASSERT(bit < props);
1255 int arraySize = (props + 31) / 32;
1256 int oldArraySize = bindingBitsSize / 32;
1258 bindingBits = (quint32 *)realloc(bindingBits,
1259 arraySize * sizeof(quint32));
1261 memset(bindingBits + oldArraySize,
1263 sizeof(quint32) * (arraySize - oldArraySize));
1265 bindingBitsSize = arraySize * 32;
1268 bindingBits[bit / 32] |= (1 << (bit % 32));
1271 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
1273 if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
1274 if (url.authority().isEmpty())
1275 return QLatin1Char(':') + url.path();
1278 return url.toLocalFile();
1282 static QString toLocalFile(const QString &url)
1284 if (!url.startsWith(QLatin1String("file://"), Qt::CaseInsensitive))
1287 QString file = url.mid(7);
1289 //XXX TODO: handle windows hostnames: "//servername/path/to/file.txt"
1291 // magic for drives on windows
1292 if (file.length() > 2 && file.at(0) == QLatin1Char('/') && file.at(2) == QLatin1Char(':'))
1298 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QString& url)
1300 if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) {
1301 if (url.length() > 4)
1302 return QLatin1Char(':') + url.mid(4);
1306 return toLocalFile(url);
1309 void QQmlEnginePrivate::sendQuit()
1313 if (q->receivers(SIGNAL(quit())) == 0) {
1314 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1318 static void dumpwarning(const QQmlError &error)
1320 qWarning().nospace() << qPrintable(error.toString());
1323 static void dumpwarning(const QList<QQmlError> &errors)
1325 for (int ii = 0; ii < errors.count(); ++ii)
1326 dumpwarning(errors.at(ii));
1329 void QQmlEnginePrivate::warning(const QQmlError &error)
1332 q->warnings(QList<QQmlError>() << error);
1333 if (outputWarningsToStdErr)
1337 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1340 q->warnings(errors);
1341 if (outputWarningsToStdErr)
1342 dumpwarning(errors);
1345 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1348 QQmlEnginePrivate::get(engine)->warning(error);
1353 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1356 QQmlEnginePrivate::get(engine)->warning(error);
1361 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1364 engine->warning(error);
1369 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1372 engine->warning(error);
1378 This function should be called prior to evaluation of any js expression,
1379 so that scarce resources are not freed prematurely (eg, if there is a
1380 nested javascript expression).
1382 void QQmlEnginePrivate::referenceScarceResources()
1384 scarceResourcesRefCount += 1;
1388 This function should be called after evaluation of the js expression is
1389 complete, and so the scarce resources may be freed safely.
1391 void QQmlEnginePrivate::dereferenceScarceResources()
1393 Q_ASSERT(scarceResourcesRefCount > 0);
1394 scarceResourcesRefCount -= 1;
1396 // if the refcount is zero, then evaluation of the "top level"
1397 // expression must have completed. We can safely release the
1398 // scarce resources.
1399 if (scarceResourcesRefCount == 0) {
1400 // iterate through the list and release them all.
1401 // note that the actual SRD is owned by the JS engine,
1402 // so we cannot delete the SRD; but we can free the
1403 // memory used by the variant in the SRD.
1404 while (ScarceResourceData *sr = scarceResources.first()) {
1405 sr->data = QVariant();
1406 scarceResources.remove(sr);
1412 Adds \a path as a directory where the engine searches for
1413 installed modules in a URL-based directory structure.
1414 The \a path may be a local filesystem directory or a URL.
1416 The newly added \a path will be first in the importPathList().
1418 \sa setImportPathList(), {QML Modules}
1420 void QQmlEngine::addImportPath(const QString& path)
1423 d->importDatabase.addImportPath(path);
1427 Returns the list of directories where the engine searches for
1428 installed modules in a URL-based directory structure.
1430 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1431 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1432 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1433 provided by that module. A \c qmldir file is required for defining the
1434 type version mapping and possibly QML extensions plugins.
1436 By default, the list contains the directory of the application executable,
1437 paths specified in the \c QML_IMPORT_PATH environment variable,
1438 and the builtin \c ImportsPath from QLibraryInfo.
1440 \sa addImportPath() setImportPathList()
1442 QStringList QQmlEngine::importPathList() const
1444 Q_D(const QQmlEngine);
1445 return d->importDatabase.importPathList();
1449 Sets \a paths as the list of directories where the engine searches for
1450 installed modules in a URL-based directory structure.
1452 By default, the list contains the directory of the application executable,
1453 paths specified in the \c QML_IMPORT_PATH environment variable,
1454 and the builtin \c ImportsPath from QLibraryInfo.
1456 \sa importPathList() addImportPath()
1458 void QQmlEngine::setImportPathList(const QStringList &paths)
1461 d->importDatabase.setImportPathList(paths);
1466 Adds \a path as a directory where the engine searches for
1467 native plugins for imported modules (referenced in the \c qmldir file).
1469 By default, the list contains only \c ., i.e. the engine searches
1470 in the directory of the \c qmldir file itself.
1472 The newly added \a path will be first in the pluginPathList().
1474 \sa setPluginPathList()
1476 void QQmlEngine::addPluginPath(const QString& path)
1479 d->importDatabase.addPluginPath(path);
1484 Returns the list of directories where the engine searches for
1485 native plugins for imported modules (referenced in the \c qmldir file).
1487 By default, the list contains only \c ., i.e. the engine searches
1488 in the directory of the \c qmldir file itself.
1490 \sa addPluginPath() setPluginPathList()
1492 QStringList QQmlEngine::pluginPathList() const
1494 Q_D(const QQmlEngine);
1495 return d->importDatabase.pluginPathList();
1499 Sets the list of directories where the engine searches for
1500 native plugins for imported modules (referenced in the \c qmldir file)
1503 By default, the list contains only \c ., i.e. the engine searches
1504 in the directory of the \c qmldir file itself.
1506 \sa pluginPathList() addPluginPath()
1508 void QQmlEngine::setPluginPathList(const QStringList &paths)
1511 d->importDatabase.setPluginPathList(paths);
1515 Imports the plugin named \a filePath with the \a uri provided.
1516 Returns true if the plugin was successfully imported; otherwise returns false.
1518 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1520 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1522 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1525 return d->importDatabase.importPlugin(filePath, uri, errors);
1529 Imports the plugin named \a filePath with the \a uri provided.
1530 Returns true if the plugin was successfully imported; otherwise returns false.
1532 On failure and if non-null, *\a errorString will be set to a message describing the failure.
1534 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1536 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1539 QList<QQmlError> errors;
1540 bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1541 if (!errors.isEmpty()) {
1543 for (int i = 0; i < errors.size(); ++i) {
1544 builtError = QString(QLatin1String("%1\n %2"))
1546 .arg(errors.at(i).toString());
1548 *errorString = builtError;
1554 \property QQmlEngine::offlineStoragePath
1555 \brief the directory for storing offline user data
1557 Returns the directory where SQL and other offline
1560 QQuickWebView and the SQL databases created with openDatabase()
1563 The default is QML/OfflineStorage in the platform-standard
1564 user application data directory.
1566 Note that the path may not currently exist on the filesystem, so
1567 callers wanting to \e create new files at this location should create
1568 it first - see QDir::mkpath().
1570 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1573 d->offlineStoragePath = dir;
1576 QString QQmlEngine::offlineStoragePath() const
1578 Q_D(const QQmlEngine);
1579 return d->offlineStoragePath;
1582 static void voidptr_destructor(void *v)
1584 void **ptr = (void **)v;
1588 static void *voidptr_constructor(const void *v)
1593 return new void*(*(void **)v);
1597 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1601 if (!mo->superClass()) {
1602 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1603 propertyCache.insert(mo, rv);
1606 QQmlPropertyCache *super = cache(mo->superClass());
1607 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1608 propertyCache.insert(mo, rv);
1613 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1616 QList<QQmlType *> types;
1618 int maxMinorVersion = 0;
1620 const QMetaObject *metaObject = type->metaObject();
1622 while (metaObject) {
1623 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1624 type->majorVersion(), minorVersion);
1626 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1632 metaObject = metaObject->superClass();
1635 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1637 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1641 QQmlPropertyCache *raw = cache(type->metaObject());
1643 bool hasCopied = false;
1645 for (int ii = 0; ii < types.count(); ++ii) {
1646 QQmlType *currentType = types.at(ii);
1650 int rev = currentType->metaObjectRevision();
1651 int moIndex = types.count() - 1 - ii;
1653 if (raw->allowedRevisionCache[moIndex] != rev) {
1658 raw->allowedRevisionCache[moIndex] = rev;
1662 // Test revision compatibility - the basic rule is:
1663 // * Anything that is excluded, cannot overload something that is not excluded *
1665 // Signals override:
1666 // * other signals and methods of the same name.
1667 // * properties named on<Signal Name>
1668 // * automatic <property name>Changed notify signals
1670 // Methods override:
1671 // * other methods of the same name
1673 // Properties override:
1674 // * other elements of the same name
1676 bool overloadError = false;
1677 QString overloadName;
1680 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1681 !overloadError && iter != raw->stringCache.end();
1684 QQmlPropertyData *d = *iter;
1685 if (raw->isAllowedInRevision(d))
1686 continue; // Not excluded - no problems
1688 // check that a regular "name" overload isn't happening
1689 QQmlPropertyData *current = d;
1690 while (!overloadError && current) {
1691 current = d->overrideData(current);
1692 if (current && raw->isAllowedInRevision(current))
1693 overloadError = true;
1698 if (overloadError) {
1699 if (hasCopied) raw->release();
1701 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."));
1705 if (!hasCopied) raw->addref();
1706 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1708 if (minorVersion != maxMinorVersion) {
1710 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1716 QQmlMetaType::ModuleApiInstance *
1717 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1719 Locker locker(this);
1721 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1723 a = new QQmlMetaType::ModuleApiInstance;
1724 a->scriptCallback = module.script;
1725 a->qobjectCallback = module.qobject;
1726 a->instanceMetaObject = module.instanceMetaObject;
1727 moduleApiInstances.insert(module, a);
1733 bool QQmlEnginePrivate::isQObject(int t)
1735 Locker locker(this);
1736 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1739 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1741 Locker locker(this);
1742 int t = v.userType();
1743 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1745 return *(QObject **)(v.constData());
1747 return QQmlMetaType::toQObject(v, ok);
1751 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1753 Locker locker(this);
1754 if (m_compositeTypes.contains(t))
1755 return QQmlMetaType::Object;
1756 else if (m_qmlLists.contains(t))
1757 return QQmlMetaType::List;
1759 return QQmlMetaType::typeCategory(t);
1762 bool QQmlEnginePrivate::isList(int t) const
1764 Locker locker(this);
1765 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1768 int QQmlEnginePrivate::listType(int t) const
1770 Locker locker(this);
1771 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1772 if (iter != m_qmlLists.end())
1775 return QQmlMetaType::listType(t);
1778 const QMetaObject *QQmlEnginePrivate::rawMetaObjectForType(int t) const
1780 Locker locker(this);
1781 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1782 if (iter != m_compositeTypes.end()) {
1783 return (*iter)->root;
1785 QQmlType *type = QQmlMetaType::qmlType(t);
1786 return type?type->baseMetaObject():0;
1790 const QMetaObject *QQmlEnginePrivate::metaObjectForType(int t) const
1792 Locker locker(this);
1793 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1794 if (iter != m_compositeTypes.end()) {
1795 return (*iter)->root;
1797 QQmlType *type = QQmlMetaType::qmlType(t);
1798 return type?type->metaObject():0;
1802 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1804 QByteArray name = data->root->className();
1806 QByteArray ptr = name + '*';
1807 QByteArray lst = "QQmlListProperty<" + name + '>';
1809 int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
1810 voidptr_constructor);
1811 int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
1812 voidptr_constructor);
1816 Locker locker(this);
1817 m_qmlLists.insert(lst_type, ptr_type);
1818 m_compositeTypes.insert(ptr_type, data);
1821 bool QQml_isFileCaseCorrect(const QString &fileName)
1823 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1824 QFileInfo info(fileName);
1825 const QString absolute = info.absoluteFilePath();
1827 #if defined(Q_OS_MAC)
1828 const QString canonical = info.canonicalFilePath();
1829 #elif defined(Q_OS_WIN)
1830 wchar_t buffer[1024];
1832 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1833 if (rv == 0 || rv >= 1024) return true;
1834 rv = ::GetLongPathName(buffer, buffer, 1024);
1835 if (rv == 0 || rv >= 1024) return true;
1837 const QString canonical = QString::fromWCharArray(buffer);
1840 const int absoluteLength = absolute.length();
1841 const int canonicalLength = canonical.length();
1843 const int length = qMin(absoluteLength, canonicalLength);
1844 for (int ii = 0; ii < length; ++ii) {
1845 const QChar &a = absolute.at(absoluteLength - 1 - ii);
1846 const QChar &c = canonical.at(canonicalLength - 1 - ii);
1848 if (a.toLower() != c.toLower())
1860 \fn QQmlEngine *qmlEngine(const QObject *object)
1863 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
1864 QQmlEngine::contextForObject(object)->engine(), but more efficient.
1868 \fn QQmlContext *qmlContext(const QObject *object)
1871 Returns the QQmlContext associated with \a object, if any. This is equivalent to
1872 QQmlEngine::contextForObject(object).