1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtQml module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qqmlengine_p.h"
43 #include "qqmlengine.h"
44 #include "qqmlcomponentattached_p.h"
46 #include "qqmlcontext_p.h"
47 #include "qqmlcompiler_p.h"
49 #include "qqmlcontext.h"
50 #include "qqmlexpression.h"
51 #include "qqmlcomponent.h"
52 #include "qqmlvme_p.h"
53 #include <private/qqmlenginedebugservice_p.h>
54 #include "qqmlstringconverters_p.h"
55 #include "qqmlxmlhttprequest_p.h"
56 #include "qqmlscriptstring.h"
57 #include "qqmlglobal_p.h"
58 #include "qquicklistmodel_p.h"
59 #include "qquickworkerscript_p.h"
60 #include "qqmlcomponent_p.h"
61 #include "qqmlnetworkaccessmanagerfactory.h"
62 #include "qqmldirparser_p.h"
63 #include "qqmlextensioninterface.h"
64 #include "qqmllist_p.h"
65 #include "qqmltypenamecache_p.h"
66 #include "qqmlnotifier_p.h"
67 #include <private/qqmlprofilerservice_p.h>
68 #include <private/qv8debugservice_p.h>
69 #include <private/qdebugmessageservice_p.h>
70 #include "qqmlincubator.h"
71 #include <private/qv8profilerservice_p.h>
72 #include <private/qqmlboundsignal_p.h>
74 #include <QtCore/qstandardpaths.h>
75 #include <QtCore/qsettings.h>
77 #include <QtCore/qmetaobject.h>
78 #include <QNetworkAccessManager>
80 #include <QtCore/qcoreapplication.h>
81 #include <QtCore/qdir.h>
82 #include <QtCore/qmutex.h>
83 #include <QtNetwork/qnetworkconfigmanager.h>
85 #include <private/qobject_p.h>
86 #include <private/qmetaobject_p.h>
88 #include <private/qqmllocale_p.h>
90 #ifdef Q_OS_WIN // for %APPDATA%
91 #include <qt_windows.h>
95 #define CSIDL_APPDATA 0x001a // <username>\Application Data
98 Q_DECLARE_METATYPE(QQmlProperty)
102 void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
104 QQmlEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
105 QQmlValueTypeFactory::registerBaseTypes(uri, versionMajor, versionMinor);
109 \qmlclass QtObject QObject
110 \ingroup qml-utility-elements
112 \brief The QtObject element is the most basic element in QML.
114 The QtObject element is a non-visual element which contains only the
117 It can be useful to create a QtObject if you need an extremely
118 lightweight element to enclose a set of custom properties:
120 \snippet doc/src/snippets/qml/qtobject.qml 0
122 It can also be useful for C++ integration, as it is just a plain
123 QObject. See the QObject documentation for further details.
126 \qmlproperty string QtObject::objectName
127 This property holds the QObject::objectName for this specific object instance.
129 This allows a C++ application to locate an item within a QML component
130 using the QObject::findChild() method. For example, the following C++
131 application locates the child \l Rectangle item and dynamically changes its
140 width: 200; height: 200
154 view.setSource(QUrl::fromLocalFile("MyRect.qml"));
157 QQuickItem *item = view.rootObject()->findChild<QQuickItem*>("myRect");
159 item->setProperty("color", QColor(Qt::yellow));
163 bool QQmlEnginePrivate::qml_debugging_enabled = false;
165 void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
167 qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
168 qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
169 qmlRegisterType<QQuickListElement>(uri, versionMajor, versionMinor,"ListElement");
170 qmlRegisterCustomType<QQuickListModel>(uri, versionMajor, versionMinor,"ListModel", new QQuickListModelParser);
171 qmlRegisterType<QQuickWorkerScript>(uri,versionMajor,versionMinor,"WorkerScript");
174 void QQmlEnginePrivate::defineModule()
176 registerBaseTypes("QtQuick", 2, 0);
177 qmlRegisterUncreatableType<QQmlLocale>("QtQuick",2,0,"Locale",QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
182 \class QQmlImageProviderBase
183 \brief The QQmlImageProviderBase class is used to register image providers in the QML engine.
186 Image providers must be registered with the QML engine. The only information the QML
187 engine knows about image providers is the type of image data they provide. To use an
188 image provider to acquire image data, you must cast the QQmlImageProviderBase pointer
189 to a QQuickImageProvider pointer.
191 \sa QQuickImageProvider, QQuickTextureFactory
195 \enum QQmlImageProviderBase::ImageType
197 Defines the type of image supported by this image provider.
199 \value Image The Image Provider provides QImage images.
200 The QQuickImageProvider::requestImage() method will be called for all image requests.
201 \value Pixmap The Image Provider provides QPixmap images.
202 The QQuickImageProvider::requestPixmap() method will be called for all image requests.
203 \value Texture The Image Provider provides QSGTextureProvider based images.
204 The QQuickImageProvider::requestTexture() method will be called for all image requests. \omitvalue
208 QQmlImageProviderBase::QQmlImageProviderBase()
213 QQmlImageProviderBase::~QQmlImageProviderBase()
219 \qmlclass Qt QQmlEnginePrivate
220 \ingroup qml-utility-elements
221 \brief The QML global Qt object provides useful enums and functions from Qt.
223 \keyword QmlGlobalQtObject
225 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
227 The \c Qt object is a global object with utility functions, properties and enums.
229 It is not instantiable; to use it, call the members of the global \c Qt object directly.
236 color: Qt.rgba(1, 0, 0, 1)
237 text: Qt.md5("hello, world")
244 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
245 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
249 The Qt object also contains helper functions for creating objects of specific
250 data types. This is primarily useful when setting the properties of an item
251 when the property has one of the following types:
254 \li \c color - use \l{Qt::rgba()}{Qt.rgba()}, \l{Qt::hsla()}{Qt.hsla()}, \l{Qt::darker()}{Qt.darker()}, \l{Qt::lighter()}{Qt.lighter()} or \l{Qt::tint()}{Qt.tint()}
255 \li \c rect - use \l{Qt::rect()}{Qt.rect()}
256 \li \c point - use \l{Qt::point()}{Qt.point()}
257 \li \c size - use \l{Qt::size()}{Qt.size()}
258 \li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
261 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
263 \section1 Date/Time Formatters
265 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
268 \li \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
269 \li \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
270 \li \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
273 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
276 \section1 Dynamic Object Creation
277 The following functions on the global object allow you to dynamically create QML
278 items from files or strings. See \l{Dynamic Object Management in QML} for an overview
282 \li \l{Qt::createComponent()}{object Qt.createComponent(url)}
283 \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
289 \qmlproperty object Qt::application
292 The \c application object provides access to global application state
293 properties shared by many QML components.
299 \li \c application.active
301 This read-only property indicates whether the application is the top-most and focused
302 application, and the user is able to interact with the application. The property
303 is false when the application is in the background, the device keylock or screen
304 saver is active, the screen backlight is turned off, or the global system dialog
305 is being displayed on top of the application. It can be used for stopping and
306 pausing animations, timers and active processing of data in order to save device
307 battery power and free device memory and processor load when the application is not
311 \li \c application.layoutDirection
313 This read-only property can be used to query the default layout direction of the
314 application. On system start-up, the default layout direction depends on the
315 application's language. The property has a value of \c Qt.RightToLeft in locales
316 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
317 where the reading direction flows from left to right. You can bind to this
318 property to customize your application layouts to support both layout directions.
323 \li Qt.LeftToRight - Text and graphics elements should be positioned
325 \li Qt.RightToLeft - Text and graphics elements should be positioned
329 The following example uses the \c application object to indicate
330 whether the application is currently active:
332 \snippet doc/src/snippets/qml/application.qml document
334 \qmlproperty object Qt::inputMethod
337 The \c inputMethod object allows access to application's QInputMethod object
338 and all its properties and slots. See the QInputMethod documentation for
344 \qmlmethod object Qt::include(string url, jsobject callback)
346 Includes another JavaScript file. This method can only be used from within JavaScript files,
347 and not regular QML files.
349 This imports all functions from \a url into the current script's namespace.
351 Qt.include() returns an object that describes the status of the operation. The object has
352 a single property, \c {status}, that is set to one of the following values:
355 \header \li Symbol \li Value \li Description
356 \row \li result.OK \li 0 \li The include completed successfully.
357 \row \li result.LOADING \li 1 \li Data is being loaded from the network.
358 \row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
359 \row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
360 An additional \c exception property will be set in this case.
363 The \c status property will be updated as the operation progresses.
365 If provided, \a callback is invoked when the operation completes. The callback is passed
366 the same object as is returned from the Qt.include() call.
368 // Qt.include() is implemented in qv8include.cpp
371 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
372 : propertyCapture(0), rootContext(0), isDebugging(false),
373 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
374 cleanup(0), erroredBindings(0), inProgressCreations(0),
375 workerScriptEngine(0), activeVME(0),
376 networkAccessManager(0), networkAccessManagerFactory(0),
377 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
378 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
382 QQmlEnginePrivate::~QQmlEnginePrivate()
384 if (inProgressCreations)
385 qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
388 QQmlCleanup *c = cleanup;
390 if (cleanup) cleanup->prev = &cleanup;
396 doDeleteInEngineThread();
398 if (incubationController) incubationController->d = 0;
399 incubationController = 0;
404 for(QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
406 for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
408 for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
410 for(QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
411 delete (*iter)->qobjectApi;
416 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
418 QObjectPrivate *p = QObjectPrivate::get(o);
419 if (p->declarativeData) {
420 QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
421 if (d->ownContext && d->context) {
422 d->context->destroy();
426 // Mark this object as in the process of deletion to
427 // prevent it resolving in bindings
428 QQmlData::markAsDeleted(o);
432 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
434 static_cast<QQmlData *>(d)->destroyed(o);
437 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
439 static_cast<QQmlData *>(d)->parentChanged(o, p);
442 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **a)
444 QQmlData *ddata = QQmlData::get(object, false);
445 if (!ddata) return; // Probably being deleted
447 QQmlNotifierEndpoint *ep = ddata->notify(index);
448 if (ep) QQmlNotifier::emitNotify(ep, a);
451 int QQmlData::receivers(QAbstractDeclarativeData *d, const QObject *, int index)
453 return static_cast<QQmlData *>(d)->endpointCount(index);
456 int QQmlData::endpointCount(int index)
459 QQmlNotifierEndpoint *ep = notify(index);
470 void QQmlData::markAsDeleted(QObject *o)
472 QQmlData::setQueuedForDeletion(o);
474 QObjectPrivate *p = QObjectPrivate::get(o);
475 for (QList<QObject *>::iterator it = p->children.begin(), end = p->children.end(); it != end; ++it) {
476 QQmlData::markAsDeleted(*it);
480 void QQmlData::setQueuedForDeletion(QObject *object)
483 if (QObjectPrivate *priv = QObjectPrivate::get(object)) {
484 if (!priv->wasDeleted && priv->declarativeData) {
485 QQmlData *ddata = QQmlData::get(object, false);
486 if (ddata->ownContext && ddata->context)
487 ddata->context->emitDestruction();
488 ddata->isQueuedForDeletion = true;
494 void QQmlEnginePrivate::init()
498 static bool firstTime = true;
500 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component");
506 qRegisterMetaType<QVariant>("QVariant");
507 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
508 qRegisterMetaType<QJSValue>("QJSValue");
509 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
510 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
511 qRegisterMetaType<QList<int> >("QList<int>");
512 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
514 v8engine()->setEngine(q);
516 rootContext = new QQmlContext(q,true);
518 if (QCoreApplication::instance()->thread() == q->thread() &&
519 QQmlEngineDebugService::isDebuggingEnabled()) {
521 QQmlEngineDebugService::instance()->addEngine(q);
522 QV8DebugService::initialize(v8engine());
523 QV8ProfilerService::initialize();
524 QQmlProfilerService::initialize();
525 QDebugMessageService::instance();
528 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
529 if (!dataLocation.isEmpty())
530 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator())
531 + QDir::separator() + QLatin1String("QML")
532 + QDir::separator() + QLatin1String("OfflineStorage");
535 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
538 if (!workerScriptEngine)
539 workerScriptEngine = new QQuickWorkerScriptEngine(q);
540 return workerScriptEngine;
547 \brief The QQmlEngine class provides an environment for instantiating QML components.
550 Each QML component is instantiated in a QQmlContext.
551 QQmlContext's are essential for passing data to QML
552 components. In QML, contexts are arranged hierarchically and this
553 hierarchy is managed by the QQmlEngine.
555 Prior to creating any QML components, an application must have
556 created a QQmlEngine to gain access to a QML context. The
557 following example shows how to create a simple Text item.
561 QQmlComponent component(&engine);
562 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
563 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
565 //add item to view, etc
569 In this case, the Text item will be created in the engine's
570 \l {QQmlEngine::rootContext()}{root context}.
572 Note that the QtQuick 1 version is called QDeclarativeEngine.
574 \sa QQmlComponent, QQmlContext
578 Create a new QQmlEngine with the given \a parent.
580 QQmlEngine::QQmlEngine(QObject *parent)
581 : QJSEngine(*new QQmlEnginePrivate(this), parent)
588 Destroys the QQmlEngine.
590 Any QQmlContext's created on this engine will be
591 invalidated, but not destroyed (unless they are parented to the
594 QQmlEngine::~QQmlEngine()
597 if (d->isDebugging) {
598 QQmlEngineDebugService::instance()->remEngine(this);
601 // Emit onDestruction signals for the root context before
602 // we destroy the contexts, engine, Module APIs etc. that
603 // may be required to handle the destruction signal.
604 QQmlContextData::get(rootContext())->emitDestruction();
606 // if we are the parent of any of the qobject module api instances,
607 // we need to remove them from our internal list, in order to prevent
608 // a segfault in engine private dtor.
609 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
610 QObject *currQObjectApi = 0;
611 QQmlMetaType::ModuleApiInstance *currInstance = 0;
612 foreach (const QQmlMetaType::ModuleApi &key, keys) {
613 currInstance = d->moduleApiInstances.value(key);
614 currQObjectApi = currInstance->qobjectApi;
615 if (this->children().contains(currQObjectApi)) {
616 delete currQObjectApi;
618 d->moduleApiInstances.remove(key);
622 if (d->incubationController)
623 d->incubationController->d = 0;
626 /*! \fn void QQmlEngine::quit()
627 This signal is emitted when the QML loaded by the engine would like to quit.
630 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
631 This signal is emitted when \a warnings messages are generated by QML.
635 Clears the engine's internal component cache.
637 This function causes the property metadata of all components previously
638 loaded by the engine to be destroyed. All previously loaded components and
639 the property bindings for all extant objects created from those components will
642 This function returns the engine to a state where it does not contain any loaded
643 component data. This may be useful in order to reload a smaller subset of the
644 previous component set, or to load a new version of a previously loaded component.
646 Once the component cache has been cleared, components must be loaded before
647 any new objects can be created.
649 void QQmlEngine::clearComponentCache()
652 d->typeLoader.clearCache();
656 Returns the engine's root context.
658 The root context is automatically created by the QQmlEngine.
659 Data that should be available to all QML component instances
660 instantiated by the engine should be put in the root context.
662 Additional data that should only be available to a subset of
663 component instances should be added to sub-contexts parented to the
666 QQmlContext *QQmlEngine::rootContext() const
668 Q_D(const QQmlEngine);
669 return d->rootContext;
673 Sets the \a factory to use for creating QNetworkAccessManager(s).
675 QNetworkAccessManager is used for all network access by QML. By
676 implementing a factory it is possible to create custom
677 QNetworkAccessManager with specialized caching, proxy and cookie
680 The factory must be set before executing the engine.
682 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
685 QMutexLocker locker(&d->mutex);
686 d->networkAccessManagerFactory = factory;
690 Returns the current QQmlNetworkAccessManagerFactory.
692 \sa setNetworkAccessManagerFactory()
694 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
696 Q_D(const QQmlEngine);
697 return d->networkAccessManagerFactory;
700 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
703 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
705 void *args[] = { 0 };
706 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
710 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
712 QMutexLocker locker(&mutex);
713 QNetworkAccessManager *nam;
714 if (networkAccessManagerFactory) {
715 nam = networkAccessManagerFactory->create(parent);
717 nam = new QNetworkAccessManager(parent);
723 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
725 Q_Q(const QQmlEngine);
726 if (!networkAccessManager)
727 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
728 return networkAccessManager;
732 Returns a common QNetworkAccessManager which can be used by any QML
733 element instantiated by this engine.
735 If a QQmlNetworkAccessManagerFactory has been set and a
736 QNetworkAccessManager has not yet been created, the
737 QQmlNetworkAccessManagerFactory will be used to create the
738 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
739 will have no proxy or cache set.
741 \sa setNetworkAccessManagerFactory()
743 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
745 Q_D(const QQmlEngine);
746 return d->getNetworkAccessManager();
751 Sets the \a provider to use for images requested via the \e
752 image: url scheme, with host \a providerId. The QQmlEngine
753 takes ownership of \a provider.
755 Image providers enable support for pixmap and threaded image
756 requests. See the QQuickImageProvider documentation for details on
757 implementing and using image providers.
759 All required image providers should be added to the engine before any
760 QML sources files are loaded.
762 \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
764 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
767 QMutexLocker locker(&d->mutex);
768 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
772 Returns the image provider set for \a providerId.
774 Returns the provider if it was found; otherwise returns 0.
776 \sa QQuickImageProvider
778 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
780 Q_D(const QQmlEngine);
781 QMutexLocker locker(&d->mutex);
782 return d->imageProviders.value(providerId).data();
786 Removes the image provider for \a providerId.
788 \sa addImageProvider(), QQuickImageProvider
790 void QQmlEngine::removeImageProvider(const QString &providerId)
793 QMutexLocker locker(&d->mutex);
794 d->imageProviders.take(providerId);
798 Return the base URL for this engine. The base URL is only used to
799 resolve components when a relative URL is passed to the
800 QQmlComponent constructor.
802 If a base URL has not been explicitly set, this method returns the
803 application's current working directory.
807 QUrl QQmlEngine::baseUrl() const
809 Q_D(const QQmlEngine);
810 if (d->baseUrl.isEmpty()) {
811 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
818 Set the base URL for this engine to \a url.
822 void QQmlEngine::setBaseUrl(const QUrl &url)
829 Returns true if warning messages will be output to stderr in addition
830 to being emitted by the warnings() signal, otherwise false.
832 The default value is true.
834 bool QQmlEngine::outputWarningsToStandardError() const
836 Q_D(const QQmlEngine);
837 return d->outputWarningsToStdErr;
841 Set whether warning messages will be output to stderr to \a enabled.
843 If \a enabled is true, any warning messages generated by QML will be
844 output to stderr and emitted by the warnings() signal. If \a enabled
845 is false, on the warnings() signal will be emitted. This allows
846 applications to handle warning output themselves.
848 The default value is true.
850 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
853 d->outputWarningsToStdErr = enabled;
857 Attempt to free unused memory.
859 void QQmlEngine::collectGarbage()
865 Returns the QQmlContext for the \a object, or 0 if no
866 context has been set.
868 When the QQmlEngine instantiates a QObject, the context is
871 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
876 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
879 static_cast<QQmlData *>(priv->declarativeData);
883 else if (data->outerContext)
884 return data->outerContext->asQQmlContext();
890 Sets the QQmlContext for the \a object to \a context.
891 If the \a object already has a context, a warning is
892 output, but the context is not changed.
894 When the QQmlEngine instantiates a QObject, the context is
897 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
899 if (!object || !context)
902 QQmlData *data = QQmlData::get(object, true);
904 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
908 QQmlContextData *contextData = QQmlContextData::get(context);
909 contextData->addObject(object);
913 \enum QQmlEngine::ObjectOwnership
915 Ownership controls whether or not QML automatically destroys the
916 QObject when the object is garbage collected by the JavaScript
917 engine. The two ownership options are:
919 \value CppOwnership The object is owned by C++ code, and will
920 never be deleted by QML. The JavaScript destroy() method cannot be
921 used on objects with CppOwnership. This option is similar to
922 QScriptEngine::QtOwnership.
924 \value JavaScriptOwnership The object is owned by JavaScript.
925 When the object is returned to QML as the return value of a method
926 call or property access, QML will track it, and delete the object
927 if there are no remaining JavaScript references to it and it has no
928 QObject::parent(). An object tracked by one QQmlEngine
929 will be deleted during that QQmlEngine's destructor, and thus
930 JavaScript references between objects with JavaScriptOwnership from
931 two different engines will not be valid after the deletion of one of
932 those engines. This option is similar to QScriptEngine::ScriptOwnership.
934 Generally an application doesn't need to set an object's ownership
935 explicitly. QML uses a heuristic to set the default object
936 ownership. By default, an object that is created by QML has
937 JavaScriptOwnership. The exception to this are the root objects
938 created by calling QQmlComponent::create() or
939 QQmlComponent::beginCreate() which have CppOwnership by
940 default. The ownership of these root-level objects is considered to
941 have been transferred to the C++ caller.
943 Objects not-created by QML have CppOwnership by default. The
944 exception to this is objects returned from a C++ method call. The
945 ownership of these objects is passed to JavaScript.
947 Calling setObjectOwnership() overrides the default ownership
948 heuristic used by QML.
952 Sets the \a ownership of \a object.
954 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
959 QQmlData *ddata = QQmlData::get(object, true);
963 ddata->indestructible = (ownership == CppOwnership)?true:false;
964 ddata->explicitIndestructibleSet = true;
968 Returns the ownership of \a object.
970 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
975 QQmlData *ddata = QQmlData::get(object, false);
979 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
982 bool QQmlEngine::event(QEvent *e)
985 if (e->type() == QEvent::User)
986 d->doDeleteInEngineThread();
988 return QJSEngine::event(e);
991 void QQmlEnginePrivate::doDeleteInEngineThread()
993 QFieldList<Deletable, &Deletable::next> list;
995 list.copyAndClear(toDeleteInEngineThread);
998 while (Deletable *d = list.takeFirst())
1002 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
1004 QQmlData *data = QQmlData::get(object);
1006 if (data && data->deferredComponent) {
1007 QQmlObjectCreatingProfiler prof;
1009 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
1010 prof.setTypeName(type ? type->qmlTypeName()
1011 : QString::fromUtf8(object->metaObject()->className()));
1012 if (data->outerContext)
1013 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
1015 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
1017 QQmlComponentPrivate::ConstructionState state;
1018 QQmlComponentPrivate::beginDeferred(ep, object, &state);
1020 data->deferredComponent->release();
1021 data->deferredComponent = 0;
1023 QQmlComponentPrivate::complete(ep, &state);
1027 QQmlContext *qmlContext(const QObject *obj)
1029 return QQmlEngine::contextForObject(obj);
1032 QQmlEngine *qmlEngine(const QObject *obj)
1034 QQmlData *data = QQmlData::get(obj, false);
1035 if (!data || !data->context)
1037 return data->context->engine;
1040 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1042 QQmlData *data = QQmlData::get(object);
1044 return 0; // Attached properties are only on objects created by QML
1046 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1050 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1054 rv = pf(const_cast<QObject *>(object));
1057 data->attachedProperties()->insert(id, rv);
1062 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1063 const QMetaObject *attachedMetaObject, bool create)
1066 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1068 if (*idCache == -1 || !object)
1071 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1074 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1076 #ifndef QQML_NO_DEBUG_PROTOCOL
1077 if (!QQmlEnginePrivate::qml_debugging_enabled
1079 qDebug("QML debugging is enabled. Only use this in a safe environment.");
1081 QQmlEnginePrivate::qml_debugging_enabled = true;
1086 class QQmlDataExtended {
1089 ~QQmlDataExtended();
1091 QHash<int, QObject *> attachedProperties;
1094 QQmlDataExtended::QQmlDataExtended()
1098 QQmlDataExtended::~QQmlDataExtended()
1102 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1105 layout(endpoint->next);
1107 int index = endpoint->sourceSignal;
1108 index = qMin(index, 0xFFFF - 1);
1110 endpoint->next = notifies[index];
1111 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1112 endpoint->prev = ¬ifies[index];
1113 notifies[index] = endpoint;
1116 void QQmlData::NotifyList::layout()
1118 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1121 QQmlNotifierEndpoint **old = notifies;
1122 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1123 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1124 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1125 sizeof(QQmlNotifierEndpoint*);
1126 memset(notifies + notifiesSize, 0, memsetSize);
1128 if (notifies != old) {
1129 for (int ii = 0; ii < notifiesSize; ++ii)
1131 notifies[ii]->prev = ¬ifies[ii];
1134 notifiesSize = maximumTodoIndex + 1;
1139 maximumTodoIndex = 0;
1143 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1146 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1147 notifyList->connectionMask = 0;
1148 notifyList->maximumTodoIndex = 0;
1149 notifyList->notifiesSize = 0;
1150 notifyList->todo = 0;
1151 notifyList->notifies = 0;
1154 Q_ASSERT(!endpoint->isConnected());
1156 index = qMin(index, 0xFFFF - 1);
1157 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1159 if (index < notifyList->notifiesSize) {
1161 endpoint->next = notifyList->notifies[index];
1162 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1163 endpoint->prev = ¬ifyList->notifies[index];
1164 notifyList->notifies[index] = endpoint;
1167 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1169 endpoint->next = notifyList->todo;
1170 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1171 endpoint->prev = ¬ifyList->todo;
1172 notifyList->todo = endpoint;
1176 bool QQml_isSignalConnected(QObject *obj, int signal_index, int index)
1178 QQmlData *data = QQmlData::get(obj);
1179 return QObjectPrivate::get(obj)->isSignalConnected(signal_index) || (data && data->signalHasEndpoint(index));
1183 index MUST be the index returned by QMetaMethod::index()
1184 This is different than the index returned by QObjectPrivate::signalIndex()
1186 bool QQmlData::signalHasEndpoint(int index)
1188 return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
1191 QHash<int, QObject *> *QQmlData::attachedProperties() const
1193 if (!extendedData) extendedData = new QQmlDataExtended;
1194 return &extendedData->attachedProperties;
1197 void QQmlData::destroyed(QObject *object)
1199 if (deferredComponent)
1200 deferredComponent->release();
1202 if (nextContextObject)
1203 nextContextObject->prevContextObject = prevContextObject;
1204 if (prevContextObject)
1205 *prevContextObject = nextContextObject;
1207 QQmlAbstractBinding *binding = bindings;
1209 QQmlAbstractBinding *next = binding->m_nextBinding;
1210 binding->m_prevBinding = 0;
1211 binding->m_nextBinding = 0;
1216 QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1217 while (signalHandler) {
1218 QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1219 signalHandler->m_prevSignal = 0;
1220 signalHandler->m_nextSignal = 0;
1221 delete signalHandler;
1222 signalHandler = next;
1229 propertyCache->release();
1231 if (ownContext && context)
1235 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1236 *guard = (QObject *)0;
1237 guard->objectDestroyed(object);
1241 while (notifyList->todo)
1242 notifyList->todo->disconnect();
1243 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1244 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1247 free(notifyList->notifies);
1253 delete extendedData;
1255 v8object.Clear(); // The WeakReference handler will clean the actual handle
1261 void QQmlData::parentChanged(QObject *object, QObject *parent)
1267 bool QQmlData::hasBindingBit(int bit) const
1269 if (bindingBitsSize > bit)
1270 return bindingBits[bit / 32] & (1 << (bit % 32));
1275 void QQmlData::clearBindingBit(int bit)
1277 if (bindingBitsSize > bit)
1278 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1281 void QQmlData::setBindingBit(QObject *obj, int bit)
1283 if (bindingBitsSize <= bit) {
1284 int props = obj->metaObject()->propertyCount();
1285 Q_ASSERT(bit < props);
1287 int arraySize = (props + 31) / 32;
1288 int oldArraySize = bindingBitsSize / 32;
1290 bindingBits = (quint32 *)realloc(bindingBits,
1291 arraySize * sizeof(quint32));
1293 memset(bindingBits + oldArraySize,
1295 sizeof(quint32) * (arraySize - oldArraySize));
1297 bindingBitsSize = arraySize * 32;
1300 bindingBits[bit / 32] |= (1 << (bit % 32));
1303 void QQmlEnginePrivate::sendQuit()
1307 if (q->receivers(SIGNAL(quit())) == 0) {
1308 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1312 static void dumpwarning(const QQmlError &error)
1314 qWarning().nospace() << qPrintable(error.toString());
1317 static void dumpwarning(const QList<QQmlError> &errors)
1319 for (int ii = 0; ii < errors.count(); ++ii)
1320 dumpwarning(errors.at(ii));
1323 void QQmlEnginePrivate::warning(const QQmlError &error)
1326 q->warnings(QList<QQmlError>() << error);
1327 if (outputWarningsToStdErr)
1331 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1334 q->warnings(errors);
1335 if (outputWarningsToStdErr)
1336 dumpwarning(errors);
1339 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1342 QQmlEnginePrivate::get(engine)->warning(error);
1347 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1350 QQmlEnginePrivate::get(engine)->warning(error);
1355 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1358 engine->warning(error);
1363 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1366 engine->warning(error);
1372 This function should be called prior to evaluation of any js expression,
1373 so that scarce resources are not freed prematurely (eg, if there is a
1374 nested javascript expression).
1376 void QQmlEnginePrivate::referenceScarceResources()
1378 scarceResourcesRefCount += 1;
1382 This function should be called after evaluation of the js expression is
1383 complete, and so the scarce resources may be freed safely.
1385 void QQmlEnginePrivate::dereferenceScarceResources()
1387 Q_ASSERT(scarceResourcesRefCount > 0);
1388 scarceResourcesRefCount -= 1;
1390 // if the refcount is zero, then evaluation of the "top level"
1391 // expression must have completed. We can safely release the
1392 // scarce resources.
1393 if (scarceResourcesRefCount == 0) {
1394 // iterate through the list and release them all.
1395 // note that the actual SRD is owned by the JS engine,
1396 // so we cannot delete the SRD; but we can free the
1397 // memory used by the variant in the SRD.
1398 while (ScarceResourceData *sr = scarceResources.first()) {
1399 sr->data = QVariant();
1400 scarceResources.remove(sr);
1406 Adds \a path as a directory where the engine searches for
1407 installed modules in a URL-based directory structure.
1408 The \a path may be a local filesystem directory or a URL.
1410 The newly added \a path will be first in the importPathList().
1412 \sa setImportPathList(), {QML Modules}
1414 void QQmlEngine::addImportPath(const QString& path)
1417 d->importDatabase.addImportPath(path);
1421 Returns the list of directories where the engine searches for
1422 installed modules in a URL-based directory structure.
1424 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1425 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1426 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1427 provided by that module. A \c qmldir file is required for defining the
1428 type version mapping and possibly QML extensions plugins.
1430 By default, the list contains the directory of the application executable,
1431 paths specified in the \c QML_IMPORT_PATH environment variable,
1432 and the builtin \c ImportsPath from QLibraryInfo.
1434 \sa addImportPath(), setImportPathList()
1436 QStringList QQmlEngine::importPathList() const
1438 Q_D(const QQmlEngine);
1439 return d->importDatabase.importPathList();
1443 Sets \a paths as the list of directories where the engine searches for
1444 installed modules in a URL-based directory structure.
1446 By default, the list contains the directory of the application executable,
1447 paths specified in the \c QML_IMPORT_PATH environment variable,
1448 and the builtin \c ImportsPath from QLibraryInfo.
1450 \sa importPathList(), addImportPath()
1452 void QQmlEngine::setImportPathList(const QStringList &paths)
1455 d->importDatabase.setImportPathList(paths);
1460 Adds \a path as a directory where the engine searches for
1461 native plugins for imported modules (referenced in the \c qmldir file).
1463 By default, the list contains only \c ., i.e. the engine searches
1464 in the directory of the \c qmldir file itself.
1466 The newly added \a path will be first in the pluginPathList().
1468 \sa setPluginPathList()
1470 void QQmlEngine::addPluginPath(const QString& path)
1473 d->importDatabase.addPluginPath(path);
1478 Returns the list of directories where the engine searches for
1479 native plugins for imported modules (referenced in the \c qmldir file).
1481 By default, the list contains only \c ., i.e. the engine searches
1482 in the directory of the \c qmldir file itself.
1484 \sa addPluginPath(), setPluginPathList()
1486 QStringList QQmlEngine::pluginPathList() const
1488 Q_D(const QQmlEngine);
1489 return d->importDatabase.pluginPathList();
1493 Sets the list of directories where the engine searches for
1494 native plugins for imported modules (referenced in the \c qmldir file)
1497 By default, the list contains only \c ., i.e. the engine searches
1498 in the directory of the \c qmldir file itself.
1500 \sa pluginPathList(), addPluginPath()
1502 void QQmlEngine::setPluginPathList(const QStringList &paths)
1505 d->importDatabase.setPluginPathList(paths);
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, the \a errors list will have any errors which occurred prepended to it.
1514 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1516 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1519 return d->importDatabase.importPlugin(filePath, uri, errors);
1523 Imports the plugin named \a filePath with the \a uri provided.
1524 Returns true if the plugin was successfully imported; otherwise returns false.
1526 On failure and if non-null, *\a errorString will be set to a message describing the failure.
1528 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1530 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1533 QList<QQmlError> errors;
1534 bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1535 if (!errors.isEmpty()) {
1537 for (int i = 0; i < errors.size(); ++i) {
1538 builtError = QString(QLatin1String("%1\n %2"))
1540 .arg(errors.at(i).toString());
1542 *errorString = builtError;
1548 \property QQmlEngine::offlineStoragePath
1549 \brief the directory for storing offline user data
1551 Returns the directory where SQL and other offline
1554 QQuickWebView and the SQL databases created with openDatabase()
1557 The default is QML/OfflineStorage in the platform-standard
1558 user application data directory.
1560 Note that the path may not currently exist on the filesystem, so
1561 callers wanting to \e create new files at this location should create
1562 it first - see QDir::mkpath().
1564 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1567 d->offlineStoragePath = dir;
1570 QString QQmlEngine::offlineStoragePath() const
1572 Q_D(const QQmlEngine);
1573 return d->offlineStoragePath;
1576 static void voidptr_destructor(void *v)
1578 void **ptr = (void **)v;
1582 static void *voidptr_constructor(const void *v)
1587 return new void*(*(void **)v);
1591 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1595 if (!mo->superClass()) {
1596 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1597 propertyCache.insert(mo, rv);
1600 QQmlPropertyCache *super = cache(mo->superClass());
1601 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1602 propertyCache.insert(mo, rv);
1607 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1610 QList<QQmlType *> types;
1612 int maxMinorVersion = 0;
1614 const QMetaObject *metaObject = type->metaObject();
1616 while (metaObject) {
1617 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1618 type->majorVersion(), minorVersion);
1620 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1626 metaObject = metaObject->superClass();
1629 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1631 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1635 QQmlPropertyCache *raw = cache(type->metaObject());
1637 bool hasCopied = false;
1639 for (int ii = 0; ii < types.count(); ++ii) {
1640 QQmlType *currentType = types.at(ii);
1644 int rev = currentType->metaObjectRevision();
1645 int moIndex = types.count() - 1 - ii;
1647 if (raw->allowedRevisionCache[moIndex] != rev) {
1652 raw->allowedRevisionCache[moIndex] = rev;
1656 // Test revision compatibility - the basic rule is:
1657 // * Anything that is excluded, cannot overload something that is not excluded *
1659 // Signals override:
1660 // * other signals and methods of the same name.
1661 // * properties named on<Signal Name>
1662 // * automatic <property name>Changed notify signals
1664 // Methods override:
1665 // * other methods of the same name
1667 // Properties override:
1668 // * other elements of the same name
1670 bool overloadError = false;
1671 QString overloadName;
1674 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1675 !overloadError && iter != raw->stringCache.end();
1678 QQmlPropertyData *d = *iter;
1679 if (raw->isAllowedInRevision(d))
1680 continue; // Not excluded - no problems
1682 // check that a regular "name" overload isn't happening
1683 QQmlPropertyData *current = d;
1684 while (!overloadError && current) {
1685 current = d->overrideData(current);
1686 if (current && raw->isAllowedInRevision(current))
1687 overloadError = true;
1692 if (overloadError) {
1693 if (hasCopied) raw->release();
1695 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."));
1699 if (!hasCopied) raw->addref();
1700 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1702 if (minorVersion != maxMinorVersion) {
1704 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1710 QQmlMetaType::ModuleApiInstance *
1711 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1713 Locker locker(this);
1715 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1717 a = new QQmlMetaType::ModuleApiInstance;
1718 a->scriptCallback = module.script;
1719 a->qobjectCallback = module.qobject;
1720 a->instanceMetaObject = module.instanceMetaObject;
1721 moduleApiInstances.insert(module, a);
1727 bool QQmlEnginePrivate::isQObject(int t)
1729 Locker locker(this);
1730 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1733 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1735 Locker locker(this);
1736 int t = v.userType();
1737 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1739 return *(QObject **)(v.constData());
1741 return QQmlMetaType::toQObject(v, ok);
1745 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1747 Locker locker(this);
1748 if (m_compositeTypes.contains(t))
1749 return QQmlMetaType::Object;
1750 else if (m_qmlLists.contains(t))
1751 return QQmlMetaType::List;
1753 return QQmlMetaType::typeCategory(t);
1756 bool QQmlEnginePrivate::isList(int t) const
1758 Locker locker(this);
1759 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1762 int QQmlEnginePrivate::listType(int t) const
1764 Locker locker(this);
1765 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1766 if (iter != m_qmlLists.end())
1769 return QQmlMetaType::listType(t);
1772 const QMetaObject *QQmlEnginePrivate::rawMetaObjectForType(int t) const
1774 Locker locker(this);
1775 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1776 if (iter != m_compositeTypes.end()) {
1777 return (*iter)->root;
1779 QQmlType *type = QQmlMetaType::qmlType(t);
1780 return type?type->baseMetaObject():0;
1784 const QMetaObject *QQmlEnginePrivate::metaObjectForType(int t) const
1786 Locker locker(this);
1787 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1788 if (iter != m_compositeTypes.end()) {
1789 return (*iter)->root;
1791 QQmlType *type = QQmlMetaType::qmlType(t);
1792 return type?type->metaObject():0;
1796 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1798 QByteArray name = data->root->className();
1800 QByteArray ptr = name + '*';
1801 QByteArray lst = "QQmlListProperty<" + name + '>';
1803 int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
1804 voidptr_constructor);
1805 int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
1806 voidptr_constructor);
1810 Locker locker(this);
1811 m_qmlLists.insert(lst_type, ptr_type);
1812 m_compositeTypes.insert(ptr_type, data);
1815 bool QQml_isFileCaseCorrect(const QString &fileName)
1817 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1818 QFileInfo info(fileName);
1819 const QString absolute = info.absoluteFilePath();
1821 #if defined(Q_OS_MAC)
1822 const QString canonical = info.canonicalFilePath();
1823 #elif defined(Q_OS_WIN)
1824 wchar_t buffer[1024];
1826 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1827 if (rv == 0 || rv >= 1024) return true;
1828 rv = ::GetLongPathName(buffer, buffer, 1024);
1829 if (rv == 0 || rv >= 1024) return true;
1831 const QString canonical = QString::fromWCharArray(buffer);
1834 const int absoluteLength = absolute.length();
1835 const int canonicalLength = canonical.length();
1837 const int length = qMin(absoluteLength, canonicalLength);
1838 for (int ii = 0; ii < length; ++ii) {
1839 const QChar &a = absolute.at(absoluteLength - 1 - ii);
1840 const QChar &c = canonical.at(canonicalLength - 1 - ii);
1842 if (a.toLower() != c.toLower())
1854 \fn QQmlEngine *qmlEngine(const QObject *object)
1857 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
1858 QQmlEngine::contextForObject(object)->engine(), but more efficient.
1862 \fn QQmlContext *qmlContext(const QObject *object)
1865 Returns the QQmlContext associated with \a object, if any. This is equivalent to
1866 QQmlEngine::contextForObject(object).