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 "qqmlbinding_p_p.h"
53 #include "qqmlvme_p.h"
54 #include <private/qqmlenginedebugservice_p.h>
55 #include "qqmlstringconverters_p.h"
56 #include "qqmlxmlhttprequest_p.h"
57 #include "qqmlscriptstring.h"
58 #include "qqmlglobal_p.h"
59 #include "qquicklistmodel_p.h"
60 #include "qquickworkerscript_p.h"
61 #include "qqmlcomponent_p.h"
62 #include "qqmlnetworkaccessmanagerfactory.h"
63 #include "qqmlimageprovider.h"
64 #include "qqmldirparser_p.h"
65 #include "qqmlextensioninterface.h"
66 #include "qqmllist_p.h"
67 #include "qqmltypenamecache_p.h"
68 #include "qqmlnotifier_p.h"
69 #include <private/qqmlprofilerservice_p.h>
70 #include <private/qquickapplication_p.h>
71 #include <private/qv8debugservice_p.h>
72 #include <private/qdebugmessageservice_p.h>
73 #include "qqmlincubator.h"
74 #include <private/qv8profilerservice_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 qmlRegisterType<QQmlBinding>();
180 qmlRegisterUncreatableType<QQuickApplication>("QtQuick",2,0,"Application", QQuickApplication::tr("Application is an abstract class"));
181 qmlRegisterUncreatableType<QQmlLocale>("QtQuick",2,0,"Locale",QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
185 \qmlclass Qt QQmlEnginePrivate
186 \ingroup qml-utility-elements
187 \brief The QML global Qt object provides useful enums and functions from Qt.
189 \keyword QmlGlobalQtObject
191 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
193 The \c Qt object is a global object with utility functions, properties and enums.
195 It is not instantiable; to use it, call the members of the global \c Qt object directly.
202 color: Qt.rgba(1, 0, 0, 1)
203 text: Qt.md5("hello, world")
210 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
211 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
215 The Qt object also contains helper functions for creating objects of specific
216 data types. This is primarily useful when setting the properties of an item
217 when the property has one of the following types:
220 \o \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()}
221 \o \c rect - use \l{Qt::rect()}{Qt.rect()}
222 \o \c point - use \l{Qt::point()}{Qt.point()}
223 \o \c size - use \l{Qt::size()}{Qt.size()}
224 \o \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
227 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
229 \section1 Date/Time Formatters
231 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
234 \o \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
235 \o \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
236 \o \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
239 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
242 \section1 Dynamic Object Creation
243 The following functions on the global object allow you to dynamically create QML
244 items from files or strings. See \l{Dynamic Object Management in QML} for an overview
248 \o \l{Qt::createComponent()}{object Qt.createComponent(url)}
249 \o \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
255 \qmlproperty object Qt::application
258 The \c application object provides access to global application state
259 properties shared by many QML components.
265 \o \c application.active
267 This read-only property indicates whether the application is the top-most and focused
268 application, and the user is able to interact with the application. The property
269 is false when the application is in the background, the device keylock or screen
270 saver is active, the screen backlight is turned off, or the global system dialog
271 is being displayed on top of the application. It can be used for stopping and
272 pausing animations, timers and active processing of data in order to save device
273 battery power and free device memory and processor load when the application is not
277 \o \c application.layoutDirection
279 This read-only property can be used to query the default layout direction of the
280 application. On system start-up, the default layout direction depends on the
281 application's language. The property has a value of \c Qt.RightToLeft in locales
282 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
283 where the reading direction flows from left to right. You can bind to this
284 property to customize your application layouts to support both layout directions.
289 \o Qt.LeftToRight - Text and graphics elements should be positioned
291 \o Qt.RightToLeft - Text and graphics elements should be positioned
296 \o \c application.inputPanel
298 This read-only property allows access to application's QInputPanel object
299 and all its properties and slots. See the QInputPanel documentation for
300 further details. Deprecated in favor of Qt.InputMethod
303 The following example uses the \c application object to indicate
304 whether the application is currently active:
306 \snippet doc/src/snippets/qml/application.qml document
308 \qmlproperty object Qt::inputMethod
311 The \c inputMethod object allows access to application's QInputMethod object
312 and all its properties and slots. See the QInputMethod documentation for
318 \qmlmethod object Qt::include(string url, jsobject callback)
320 Includes another JavaScript file. This method can only be used from within JavaScript files,
321 and not regular QML files.
323 This imports all functions from \a url into the current script's namespace.
325 Qt.include() returns an object that describes the status of the operation. The object has
326 a single property, \c {status}, that is set to one of the following values:
329 \header \o Symbol \o Value \o Description
330 \row \o result.OK \o 0 \o The include completed successfully.
331 \row \o result.LOADING \o 1 \o Data is being loaded from the network.
332 \row \o result.NETWORK_ERROR \o 2 \o A network error occurred while fetching the url.
333 \row \o result.EXCEPTION \o 3 \o A JavaScript exception occurred while executing the included code.
334 An additional \c exception property will be set in this case.
337 The \c status property will be updated as the operation progresses.
339 If provided, \a callback is invoked when the operation completes. The callback is passed
340 the same object as is returned from the Qt.include() call.
342 // Qt.include() is implemented in qv8include.cpp
345 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
346 : propertyCapture(0), rootContext(0), isDebugging(false),
347 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
348 cleanup(0), erroredBindings(0), inProgressCreations(0),
349 workerScriptEngine(0), activeVME(0),
350 networkAccessManager(0), networkAccessManagerFactory(0),
351 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
352 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
356 QQmlEnginePrivate::~QQmlEnginePrivate()
358 Q_ASSERT(inProgressCreations == 0);
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;
477 \brief The QQmlEngine class provides an environment for instantiating QML components.
480 Each QML component is instantiated in a QQmlContext.
481 QQmlContext's are essential for passing data to QML
482 components. In QML, contexts are arranged hierarchically and this
483 hierarchy is managed by the QQmlEngine.
485 Prior to creating any QML components, an application must have
486 created a QQmlEngine to gain access to a QML context. The
487 following example shows how to create a simple Text item.
491 QQmlComponent component(&engine);
492 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
493 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
495 //add item to view, etc
499 In this case, the Text item will be created in the engine's
500 \l {QQmlEngine::rootContext()}{root context}.
502 \sa QQmlComponent QQmlContext
506 Create a new QQmlEngine with the given \a parent.
508 QQmlEngine::QQmlEngine(QObject *parent)
509 : QJSEngine(*new QQmlEnginePrivate(this), parent)
516 Destroys the QQmlEngine.
518 Any QQmlContext's created on this engine will be
519 invalidated, but not destroyed (unless they are parented to the
522 QQmlEngine::~QQmlEngine()
525 if (d->isDebugging) {
526 QQmlEngineDebugService::instance()->remEngine(this);
529 // if we are the parent of any of the qobject module api instances,
530 // we need to remove them from our internal list, in order to prevent
531 // a segfault in engine private dtor.
532 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
533 QObject *currQObjectApi = 0;
534 QQmlMetaType::ModuleApiInstance *currInstance = 0;
535 foreach (const QQmlMetaType::ModuleApi &key, keys) {
536 currInstance = d->moduleApiInstances.value(key);
537 currQObjectApi = currInstance->qobjectApi;
538 if (this->children().contains(currQObjectApi)) {
539 delete currQObjectApi;
541 d->moduleApiInstances.remove(key);
545 // ensure we clean up QObjects with JS ownership
548 if (d->incubationController)
549 d->incubationController->d = 0;
552 /*! \fn void QQmlEngine::quit()
553 This signal is emitted when the QML loaded by the engine would like to quit.
556 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
557 This signal is emitted when \a warnings messages are generated by QML.
561 Clears the engine's internal component cache.
563 Normally the QQmlEngine caches components loaded from qml
564 files. This method clears this cache and forces the component to be
567 void QQmlEngine::clearComponentCache()
570 d->typeLoader.clearCache();
574 Returns the engine's root context.
576 The root context is automatically created by the QQmlEngine.
577 Data that should be available to all QML component instances
578 instantiated by the engine should be put in the root context.
580 Additional data that should only be available to a subset of
581 component instances should be added to sub-contexts parented to the
584 QQmlContext *QQmlEngine::rootContext() const
586 Q_D(const QQmlEngine);
587 return d->rootContext;
591 Sets the \a factory to use for creating QNetworkAccessManager(s).
593 QNetworkAccessManager is used for all network access by QML. By
594 implementing a factory it is possible to create custom
595 QNetworkAccessManager with specialized caching, proxy and cookie
598 The factory must be set before executing the engine.
600 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
603 QMutexLocker locker(&d->mutex);
604 d->networkAccessManagerFactory = factory;
608 Returns the current QQmlNetworkAccessManagerFactory.
610 \sa setNetworkAccessManagerFactory()
612 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
614 Q_D(const QQmlEngine);
615 return d->networkAccessManagerFactory;
618 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
621 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
623 void *args[] = { 0 };
624 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
628 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
630 QMutexLocker locker(&mutex);
631 QNetworkAccessManager *nam;
632 if (networkAccessManagerFactory) {
633 nam = networkAccessManagerFactory->create(parent);
635 nam = new QNetworkAccessManager(parent);
641 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
643 Q_Q(const QQmlEngine);
644 if (!networkAccessManager)
645 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
646 return networkAccessManager;
650 Returns a common QNetworkAccessManager which can be used by any QML
651 element instantiated by this engine.
653 If a QQmlNetworkAccessManagerFactory has been set and a
654 QNetworkAccessManager has not yet been created, the
655 QQmlNetworkAccessManagerFactory will be used to create the
656 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
657 will have no proxy or cache set.
659 \sa setNetworkAccessManagerFactory()
661 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
663 Q_D(const QQmlEngine);
664 return d->getNetworkAccessManager();
669 Sets the \a provider to use for images requested via the \e
670 image: url scheme, with host \a providerId. The QQmlEngine
671 takes ownership of \a provider.
673 Image providers enable support for pixmap and threaded image
674 requests. See the QQmlImageProvider documentation for details on
675 implementing and using image providers.
677 All required image providers should be added to the engine before any
678 QML sources files are loaded.
680 \sa removeImageProvider()
682 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProvider *provider)
685 QMutexLocker locker(&d->mutex);
686 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProvider>(provider));
690 Returns the QQmlImageProvider set for \a providerId.
692 Returns the provider if it was found; otherwise returns 0.
694 QQmlImageProvider *QQmlEngine::imageProvider(const QString &providerId) const
696 Q_D(const QQmlEngine);
697 QMutexLocker locker(&d->mutex);
698 return d->imageProviders.value(providerId).data();
702 Removes the QQmlImageProvider for \a providerId.
704 \sa addImageProvider()
706 void QQmlEngine::removeImageProvider(const QString &providerId)
709 QMutexLocker locker(&d->mutex);
710 d->imageProviders.take(providerId);
713 QQmlImageProvider::ImageType QQmlEnginePrivate::getImageProviderType(const QUrl &url)
715 QMutexLocker locker(&mutex);
716 QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
719 return provider->imageType();
720 return QQmlImageProvider::Invalid;
723 QQuickTextureFactory *QQmlEnginePrivate::getTextureFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
725 QMutexLocker locker(&mutex);
726 QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
729 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
730 return provider->requestTexture(imageId, size, req_size);
735 QImage QQmlEnginePrivate::getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
737 QMutexLocker locker(&mutex);
739 QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
742 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
743 image = provider->requestImage(imageId, size, req_size);
748 QPixmap QQmlEnginePrivate::getPixmapFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
750 QMutexLocker locker(&mutex);
752 QSharedPointer<QQmlImageProvider> provider = imageProviders.value(url.host());
755 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
756 pixmap = provider->requestPixmap(imageId, size, req_size);
762 Return the base URL for this engine. The base URL is only used to
763 resolve components when a relative URL is passed to the
764 QQmlComponent constructor.
766 If a base URL has not been explicitly set, this method returns the
767 application's current working directory.
771 QUrl QQmlEngine::baseUrl() const
773 Q_D(const QQmlEngine);
774 if (d->baseUrl.isEmpty()) {
775 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
782 Set the base URL for this engine to \a url.
786 void QQmlEngine::setBaseUrl(const QUrl &url)
793 Returns true if warning messages will be output to stderr in addition
794 to being emitted by the warnings() signal, otherwise false.
796 The default value is true.
798 bool QQmlEngine::outputWarningsToStandardError() const
800 Q_D(const QQmlEngine);
801 return d->outputWarningsToStdErr;
805 Set whether warning messages will be output to stderr to \a enabled.
807 If \a enabled is true, any warning messages generated by QML will be
808 output to stderr and emitted by the warnings() signal. If \a enabled
809 is false, on the warnings() signal will be emitted. This allows
810 applications to handle warning output themselves.
812 The default value is true.
814 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
817 d->outputWarningsToStdErr = enabled;
821 Attempt to free unused memory.
823 void QQmlEngine::collectGarbage()
829 Returns the QQmlContext for the \a object, or 0 if no
830 context has been set.
832 When the QQmlEngine instantiates a QObject, the context is
835 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
840 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
843 static_cast<QQmlData *>(priv->declarativeData);
847 else if (data->outerContext)
848 return data->outerContext->asQQmlContext();
854 Sets the QQmlContext for the \a object to \a context.
855 If the \a object already has a context, a warning is
856 output, but the context is not changed.
858 When the QQmlEngine instantiates a QObject, the context is
861 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
863 if (!object || !context)
866 QQmlData *data = QQmlData::get(object, true);
868 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
872 QQmlContextData *contextData = QQmlContextData::get(context);
873 contextData->addObject(object);
877 \enum QQmlEngine::ObjectOwnership
879 Ownership controls whether or not QML automatically destroys the
880 QObject when the object is garbage collected by the JavaScript
881 engine. The two ownership options are:
883 \value CppOwnership The object is owned by C++ code, and will
884 never be deleted by QML. The JavaScript destroy() method cannot be
885 used on objects with CppOwnership. This option is similar to
886 QScriptEngine::QtOwnership.
888 \value JavaScriptOwnership The object is owned by JavaScript.
889 When the object is returned to QML as the return value of a method
890 call or property access, QML will delete the object if there are no
891 remaining JavaScript references to it and it has no
892 QObject::parent(). This option is similar to
893 QScriptEngine::ScriptOwnership.
895 Generally an application doesn't need to set an object's ownership
896 explicitly. QML uses a heuristic to set the default object
897 ownership. By default, an object that is created by QML has
898 JavaScriptOwnership. The exception to this are the root objects
899 created by calling QQmlComponent::create() or
900 QQmlComponent::beginCreate() which have CppOwnership by
901 default. The ownership of these root-level objects is considered to
902 have been transferred to the C++ caller.
904 Objects not-created by QML have CppOwnership by default. The
905 exception to this is objects returned from a C++ method call. The
906 ownership of these objects is passed to JavaScript.
908 Calling setObjectOwnership() overrides the default ownership
909 heuristic used by QML.
913 Sets the \a ownership of \a object.
915 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
920 QQmlData *ddata = QQmlData::get(object, true);
924 ddata->indestructible = (ownership == CppOwnership)?true:false;
925 ddata->explicitIndestructibleSet = true;
929 Returns the ownership of \a object.
931 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
936 QQmlData *ddata = QQmlData::get(object, false);
940 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
943 bool QQmlEngine::event(QEvent *e)
946 if (e->type() == QEvent::User)
947 d->doDeleteInEngineThread();
949 return QJSEngine::event(e);
952 void QQmlEnginePrivate::doDeleteInEngineThread()
954 QFieldList<Deletable, &Deletable::next> list;
956 list.copyAndClear(toDeleteInEngineThread);
959 while (Deletable *d = list.takeFirst())
963 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
965 QQmlData *data = QQmlData::get(object);
967 if (data && data->deferredComponent) {
968 if (QQmlDebugService::isDebuggingEnabled()) {
969 QQmlProfilerService::startRange(QQmlProfilerService::Creating);
970 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
971 QString typeName = type ? type->qmlTypeName() : QString::fromUtf8(object->metaObject()->className());
972 QQmlProfilerService::rangeData(QQmlProfilerService::Creating, typeName);
973 if (data->outerContext)
974 QQmlProfilerService::rangeLocation(QQmlProfilerService::Creating, data->outerContext->url, data->lineNumber, data->columnNumber);
976 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
978 QQmlComponentPrivate::ConstructionState state;
979 QQmlComponentPrivate::beginDeferred(ep, object, &state);
981 data->deferredComponent->release();
982 data->deferredComponent = 0;
984 QQmlComponentPrivate::complete(ep, &state);
985 QQmlProfilerService::endRange(QQmlProfilerService::Creating);
989 QQmlContext *qmlContext(const QObject *obj)
991 return QQmlEngine::contextForObject(obj);
994 QQmlEngine *qmlEngine(const QObject *obj)
996 QQmlData *data = QQmlData::get(obj, false);
997 if (!data || !data->context)
999 return data->context->engine;
1002 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1004 QQmlData *data = QQmlData::get(object);
1006 return 0; // Attached properties are only on objects created by QML
1008 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1012 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1016 rv = pf(const_cast<QObject *>(object));
1019 data->attachedProperties()->insert(id, rv);
1024 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1025 const QMetaObject *attachedMetaObject, bool create)
1028 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1030 if (*idCache == -1 || !object)
1033 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1036 QQmlDebuggingEnabler::QQmlDebuggingEnabler()
1038 #ifndef QQML_NO_DEBUG_PROTOCOL
1039 if (!QQmlEnginePrivate::qml_debugging_enabled) {
1040 qWarning("Qml debugging is enabled. Only use this in a safe environment!");
1042 QQmlEnginePrivate::qml_debugging_enabled = true;
1047 class QQmlDataExtended {
1050 ~QQmlDataExtended();
1052 QHash<int, QObject *> attachedProperties;
1053 QQmlNotifier objectNameNotifier;
1056 QQmlDataExtended::QQmlDataExtended()
1060 QQmlDataExtended::~QQmlDataExtended()
1064 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1067 layout(endpoint->next);
1069 int index = endpoint->sourceSignal;
1070 index = qMin(index, 0xFFFF - 1);
1072 endpoint->next = notifies[index];
1073 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1074 endpoint->prev = ¬ifies[index];
1075 notifies[index] = endpoint;
1078 void QQmlData::NotifyList::layout()
1080 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1083 QQmlNotifierEndpoint **old = notifies;
1084 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1085 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1086 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1087 sizeof(QQmlNotifierEndpoint*);
1088 memset(notifies + notifiesSize, 0, memsetSize);
1090 if (notifies != old) {
1091 for (int ii = 0; ii < notifiesSize; ++ii)
1093 notifies[ii]->prev = ¬ifies[ii];
1096 notifiesSize = maximumTodoIndex + 1;
1101 maximumTodoIndex = 0;
1105 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1108 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1109 notifyList->connectionMask = 0;
1110 notifyList->maximumTodoIndex = 0;
1111 notifyList->notifiesSize = 0;
1112 notifyList->todo = 0;
1113 notifyList->notifies = 0;
1116 Q_ASSERT(!endpoint->isConnected());
1118 index = qMin(index, 0xFFFF - 1);
1119 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1121 if (index < notifyList->notifiesSize) {
1123 endpoint->next = notifyList->notifies[index];
1124 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1125 endpoint->prev = ¬ifyList->notifies[index];
1126 notifyList->notifies[index] = endpoint;
1129 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1131 endpoint->next = notifyList->todo;
1132 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1133 endpoint->prev = ¬ifyList->todo;
1134 notifyList->todo = endpoint;
1138 QQmlNotifier *QQmlData::objectNameNotifier() const
1140 if (!extendedData) extendedData = new QQmlDataExtended;
1141 return &extendedData->objectNameNotifier;
1144 QHash<int, QObject *> *QQmlData::attachedProperties() const
1146 if (!extendedData) extendedData = new QQmlDataExtended;
1147 return &extendedData->attachedProperties;
1150 void QQmlData::destroyed(QObject *object)
1152 if (deferredComponent)
1153 deferredComponent->release();
1155 if (nextContextObject)
1156 nextContextObject->prevContextObject = prevContextObject;
1157 if (prevContextObject)
1158 *prevContextObject = nextContextObject;
1160 QQmlAbstractBinding *binding = bindings;
1162 QQmlAbstractBinding *next = binding->m_nextBinding;
1163 binding->m_prevBinding = 0;
1164 binding->m_nextBinding = 0;
1173 propertyCache->release();
1175 if (ownContext && context)
1179 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1180 *guard = (QObject *)0;
1181 guard->objectDestroyed(object);
1185 while (notifyList->todo)
1186 notifyList->todo->disconnect();
1187 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1188 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1191 free(notifyList->notifies);
1196 delete extendedData;
1198 v8object.Clear(); // The WeakReference handler will clean the actual handle
1204 void QQmlData::parentChanged(QObject *object, QObject *parent)
1210 void QQmlData::objectNameChanged(QObject *)
1212 if (extendedData) objectNameNotifier()->notify();
1215 bool QQmlData::hasBindingBit(int bit) const
1217 if (bindingBitsSize > bit)
1218 return bindingBits[bit / 32] & (1 << (bit % 32));
1223 void QQmlData::clearBindingBit(int bit)
1225 if (bindingBitsSize > bit)
1226 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1229 void QQmlData::setBindingBit(QObject *obj, int bit)
1231 if (bindingBitsSize <= bit) {
1232 int props = obj->metaObject()->propertyCount();
1233 Q_ASSERT(bit < props);
1235 int arraySize = (props + 31) / 32;
1236 int oldArraySize = bindingBitsSize / 32;
1238 bindingBits = (quint32 *)realloc(bindingBits,
1239 arraySize * sizeof(quint32));
1241 memset(bindingBits + oldArraySize,
1243 sizeof(quint32) * (arraySize - oldArraySize));
1245 bindingBitsSize = arraySize * 32;
1248 bindingBits[bit / 32] |= (1 << (bit % 32));
1251 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
1253 if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
1254 if (url.authority().isEmpty())
1255 return QLatin1Char(':') + url.path();
1258 return url.toLocalFile();
1262 static QString toLocalFile(const QString &url)
1264 if (!url.startsWith(QLatin1String("file://"), Qt::CaseInsensitive))
1267 QString file = url.mid(7);
1269 //XXX TODO: handle windows hostnames: "//servername/path/to/file.txt"
1271 // magic for drives on windows
1272 if (file.length() > 2 && file.at(0) == QLatin1Char('/') && file.at(2) == QLatin1Char(':'))
1278 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QString& url)
1280 if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) {
1281 if (url.length() > 4)
1282 return QLatin1Char(':') + url.mid(4);
1286 return toLocalFile(url);
1289 void QQmlEnginePrivate::sendQuit()
1293 if (q->receivers(SIGNAL(quit())) == 0) {
1294 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1298 static void dumpwarning(const QQmlError &error)
1300 qWarning().nospace() << qPrintable(error.toString());
1303 static void dumpwarning(const QList<QQmlError> &errors)
1305 for (int ii = 0; ii < errors.count(); ++ii)
1306 dumpwarning(errors.at(ii));
1309 void QQmlEnginePrivate::warning(const QQmlError &error)
1312 q->warnings(QList<QQmlError>() << error);
1313 if (outputWarningsToStdErr)
1317 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1320 q->warnings(errors);
1321 if (outputWarningsToStdErr)
1322 dumpwarning(errors);
1325 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1328 QQmlEnginePrivate::get(engine)->warning(error);
1333 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1336 QQmlEnginePrivate::get(engine)->warning(error);
1341 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1344 engine->warning(error);
1349 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1352 engine->warning(error);
1358 This function should be called prior to evaluation of any js expression,
1359 so that scarce resources are not freed prematurely (eg, if there is a
1360 nested javascript expression).
1362 void QQmlEnginePrivate::referenceScarceResources()
1364 scarceResourcesRefCount += 1;
1368 This function should be called after evaluation of the js expression is
1369 complete, and so the scarce resources may be freed safely.
1371 void QQmlEnginePrivate::dereferenceScarceResources()
1373 Q_ASSERT(scarceResourcesRefCount > 0);
1374 scarceResourcesRefCount -= 1;
1376 // if the refcount is zero, then evaluation of the "top level"
1377 // expression must have completed. We can safely release the
1378 // scarce resources.
1379 if (scarceResourcesRefCount == 0) {
1380 // iterate through the list and release them all.
1381 // note that the actual SRD is owned by the JS engine,
1382 // so we cannot delete the SRD; but we can free the
1383 // memory used by the variant in the SRD.
1384 while (ScarceResourceData *sr = scarceResources.first()) {
1385 sr->data = QVariant();
1386 scarceResources.remove(sr);
1392 Adds \a path as a directory where the engine searches for
1393 installed modules in a URL-based directory structure.
1394 The \a path may be a local filesystem directory or a URL.
1396 The newly added \a path will be first in the importPathList().
1398 \sa setImportPathList(), {QML Modules}
1400 void QQmlEngine::addImportPath(const QString& path)
1403 d->importDatabase.addImportPath(path);
1407 Returns the list of directories where the engine searches for
1408 installed modules in a URL-based directory structure.
1410 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1411 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1412 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1413 provided by that module. A \c qmldir file is required for defining the
1414 type version mapping and possibly declarative extensions plugins.
1416 By default, the list contains the directory of the application executable,
1417 paths specified in the \c QML_IMPORT_PATH environment variable,
1418 and the builtin \c ImportsPath from QLibraryInfo.
1420 \sa addImportPath() setImportPathList()
1422 QStringList QQmlEngine::importPathList() const
1424 Q_D(const QQmlEngine);
1425 return d->importDatabase.importPathList();
1429 Sets \a paths as the list of directories where the engine searches for
1430 installed modules in a URL-based directory structure.
1432 By default, the list contains the directory of the application executable,
1433 paths specified in the \c QML_IMPORT_PATH environment variable,
1434 and the builtin \c ImportsPath from QLibraryInfo.
1436 \sa importPathList() addImportPath()
1438 void QQmlEngine::setImportPathList(const QStringList &paths)
1441 d->importDatabase.setImportPathList(paths);
1446 Adds \a path as a directory where the engine searches for
1447 native plugins for imported modules (referenced in the \c qmldir file).
1449 By default, the list contains only \c ., i.e. the engine searches
1450 in the directory of the \c qmldir file itself.
1452 The newly added \a path will be first in the pluginPathList().
1454 \sa setPluginPathList()
1456 void QQmlEngine::addPluginPath(const QString& path)
1459 d->importDatabase.addPluginPath(path);
1464 Returns the list of directories where the engine searches for
1465 native plugins for imported modules (referenced in the \c qmldir file).
1467 By default, the list contains only \c ., i.e. the engine searches
1468 in the directory of the \c qmldir file itself.
1470 \sa addPluginPath() setPluginPathList()
1472 QStringList QQmlEngine::pluginPathList() const
1474 Q_D(const QQmlEngine);
1475 return d->importDatabase.pluginPathList();
1479 Sets the list of directories where the engine searches for
1480 native plugins for imported modules (referenced in the \c qmldir file)
1483 By default, the list contains only \c ., i.e. the engine searches
1484 in the directory of the \c qmldir file itself.
1486 \sa pluginPathList() addPluginPath()
1488 void QQmlEngine::setPluginPathList(const QStringList &paths)
1491 d->importDatabase.setPluginPathList(paths);
1495 Imports the plugin named \a filePath with the \a uri provided.
1496 Returns true if the plugin was successfully imported; otherwise returns false.
1498 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1500 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1502 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1505 return d->importDatabase.importPlugin(filePath, uri, errors);
1509 Imports the plugin named \a filePath with the \a uri provided.
1510 Returns true if the plugin was successfully imported; otherwise returns false.
1512 On failure and if non-null, *\a errorString will be set to a message describing the failure.
1514 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1516 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1519 QList<QQmlError> errors;
1520 bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1521 if (!errors.isEmpty()) {
1523 for (int i = 0; i < errors.size(); ++i) {
1524 builtError = QString(QLatin1String("%1\n %2"))
1526 .arg(errors.at(i).toString());
1528 *errorString = builtError;
1534 \property QQmlEngine::offlineStoragePath
1535 \brief the directory for storing offline user data
1537 Returns the directory where SQL and other offline
1540 QQuickWebView and the SQL databases created with openDatabase()
1543 The default is QML/OfflineStorage in the platform-standard
1544 user application data directory.
1546 Note that the path may not currently exist on the filesystem, so
1547 callers wanting to \e create new files at this location should create
1548 it first - see QDir::mkpath().
1550 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1553 d->offlineStoragePath = dir;
1556 QString QQmlEngine::offlineStoragePath() const
1558 Q_D(const QQmlEngine);
1559 return d->offlineStoragePath;
1562 static void voidptr_destructor(void *v)
1564 void **ptr = (void **)v;
1568 static void *voidptr_constructor(const void *v)
1573 return new void*(*(void **)v);
1577 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1581 if (!mo->superClass()) {
1582 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1583 propertyCache.insert(mo, rv);
1586 QQmlPropertyCache *super = cache(mo->superClass());
1587 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1588 propertyCache.insert(mo, rv);
1593 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1596 QList<QQmlType *> types;
1598 int maxMinorVersion = 0;
1600 const QMetaObject *metaObject = type->metaObject();
1602 while (metaObject) {
1603 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1604 type->majorVersion(), minorVersion);
1606 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1612 metaObject = metaObject->superClass();
1615 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1617 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1621 QQmlPropertyCache *raw = cache(type->metaObject());
1623 bool hasCopied = false;
1625 for (int ii = 0; ii < types.count(); ++ii) {
1626 QQmlType *currentType = types.at(ii);
1630 int rev = currentType->metaObjectRevision();
1631 int moIndex = types.count() - 1 - ii;
1633 if (raw->allowedRevisionCache[moIndex] != rev) {
1638 raw->allowedRevisionCache[moIndex] = rev;
1642 // Test revision compatibility - the basic rule is:
1643 // * Anything that is excluded, cannot overload something that is not excluded *
1645 // Signals override:
1646 // * other signals and methods of the same name.
1647 // * properties named on<Signal Name>
1648 // * automatic <property name>Changed notify signals
1650 // Methods override:
1651 // * other methods of the same name
1653 // Properties override:
1654 // * other elements of the same name
1656 bool overloadError = false;
1657 QString overloadName;
1660 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1661 !overloadError && iter != raw->stringCache.end();
1664 QQmlPropertyData *d = *iter;
1665 if (raw->isAllowedInRevision(d))
1666 continue; // Not excluded - no problems
1668 // check that a regular "name" overload isn't happening
1669 QQmlPropertyData *current = d;
1670 while (!overloadError && current) {
1671 current = d->overrideData(current);
1672 if (current && raw->isAllowedInRevision(current))
1673 overloadError = true;
1678 if (overloadError) {
1679 if (hasCopied) raw->release();
1681 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."));
1685 if (!hasCopied) raw->addref();
1686 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1688 if (minorVersion != maxMinorVersion) {
1690 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1696 QQmlMetaType::ModuleApiInstance *
1697 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1699 Locker locker(this);
1701 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1703 a = new QQmlMetaType::ModuleApiInstance;
1704 a->scriptCallback = module.script;
1705 a->qobjectCallback = module.qobject;
1706 moduleApiInstances.insert(module, a);
1712 bool QQmlEnginePrivate::isQObject(int t)
1714 Locker locker(this);
1715 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1718 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1720 Locker locker(this);
1721 int t = v.userType();
1722 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1724 return *(QObject **)(v.constData());
1726 return QQmlMetaType::toQObject(v, ok);
1730 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1732 Locker locker(this);
1733 if (m_compositeTypes.contains(t))
1734 return QQmlMetaType::Object;
1735 else if (m_qmlLists.contains(t))
1736 return QQmlMetaType::List;
1738 return QQmlMetaType::typeCategory(t);
1741 bool QQmlEnginePrivate::isList(int t) const
1743 Locker locker(this);
1744 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1747 int QQmlEnginePrivate::listType(int t) const
1749 Locker locker(this);
1750 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1751 if (iter != m_qmlLists.end())
1754 return QQmlMetaType::listType(t);
1757 const QMetaObject *QQmlEnginePrivate::rawMetaObjectForType(int t) const
1759 Locker locker(this);
1760 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1761 if (iter != m_compositeTypes.end()) {
1762 return (*iter)->root;
1764 QQmlType *type = QQmlMetaType::qmlType(t);
1765 return type?type->baseMetaObject():0;
1769 const QMetaObject *QQmlEnginePrivate::metaObjectForType(int t) const
1771 Locker locker(this);
1772 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1773 if (iter != m_compositeTypes.end()) {
1774 return (*iter)->root;
1776 QQmlType *type = QQmlMetaType::qmlType(t);
1777 return type?type->metaObject():0;
1781 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1783 QByteArray name = data->root->className();
1785 QByteArray ptr = name + '*';
1786 QByteArray lst = "QQmlListProperty<" + name + '>';
1788 int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
1789 voidptr_constructor);
1790 int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
1791 voidptr_constructor);
1795 Locker locker(this);
1796 m_qmlLists.insert(lst_type, ptr_type);
1797 m_compositeTypes.insert(ptr_type, data);
1800 bool QQml_isFileCaseCorrect(const QString &fileName)
1802 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1803 QFileInfo info(fileName);
1804 const QString absolute = info.absoluteFilePath();
1806 #if defined(Q_OS_MAC)
1807 const QString canonical = info.canonicalFilePath();
1808 #elif defined(Q_OS_WIN)
1809 wchar_t buffer[1024];
1811 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1812 if (rv == 0 || rv >= 1024) return true;
1813 rv = ::GetLongPathName(buffer, buffer, 1024);
1814 if (rv == 0 || rv >= 1024) return true;
1816 const QString canonical = QString::fromWCharArray(buffer);
1819 const int absoluteLength = absolute.length();
1820 const int canonicalLength = canonical.length();
1822 const int length = qMin(absoluteLength, canonicalLength);
1823 for (int ii = 0; ii < length; ++ii) {
1824 const QChar &a = absolute.at(absoluteLength - 1 - ii);
1825 const QChar &c = canonical.at(canonicalLength - 1 - ii);
1827 if (a.toLower() != c.toLower())
1839 \fn QQmlEngine *qmlEngine(const QObject *object)
1842 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
1843 QQmlEngine::contextForObject(object)->engine(), but more efficient.
1847 \fn QQmlContext *qmlContext(const QObject *object)
1850 Returns the QQmlContext associated with \a object, if any. This is equivalent to
1851 QQmlEngine::contextForObject(object).