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>
73 #include <QtCore/qstandardpaths.h>
74 #include <QtCore/qsettings.h>
76 #include <QtCore/qmetaobject.h>
77 #include <QNetworkAccessManager>
79 #include <QMetaObject>
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>
87 #include <private/qqmllocale_p.h>
89 #ifdef Q_OS_WIN // for %APPDATA%
90 #include <qt_windows.h>
94 #define CSIDL_APPDATA 0x001a // <username>\Application Data
97 Q_DECLARE_METATYPE(QQmlProperty)
101 void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
103 QQmlEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
104 QQmlValueTypeFactory::registerBaseTypes(uri, versionMajor, versionMinor);
108 \qmlclass QtObject QObject
109 \ingroup qml-utility-elements
111 \brief The QtObject element is the most basic element in QML.
113 The QtObject element is a non-visual element which contains only the
116 It can be useful to create a QtObject if you need an extremely
117 lightweight element to enclose a set of custom properties:
119 \snippet doc/src/snippets/qml/qtobject.qml 0
121 It can also be useful for C++ integration, as it is just a plain
122 QObject. See the QObject documentation for further details.
125 \qmlproperty string QtObject::objectName
126 This property holds the QObject::objectName for this specific object instance.
128 This allows a C++ application to locate an item within a QML component
129 using the QObject::findChild() method. For example, the following C++
130 application locates the child \l Rectangle item and dynamically changes its
139 width: 200; height: 200
153 view.setSource(QUrl::fromLocalFile("MyRect.qml"));
156 QQuickItem *item = view.rootObject()->findChild<QQuickItem*>("myRect");
158 item->setProperty("color", QColor(Qt::yellow));
162 bool QQmlEnginePrivate::qml_debugging_enabled = false;
164 void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
166 qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
167 qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
168 qmlRegisterType<QQuickListElement>(uri, versionMajor, versionMinor,"ListElement");
169 qmlRegisterCustomType<QQuickListModel>(uri, versionMajor, versionMinor,"ListModel", new QQuickListModelParser);
170 qmlRegisterType<QQuickWorkerScript>(uri,versionMajor,versionMinor,"WorkerScript");
173 void QQmlEnginePrivate::defineModule()
175 registerBaseTypes("QtQuick", 2, 0);
176 qmlRegisterUncreatableType<QQmlLocale>("QtQuick",2,0,"Locale",QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
181 \class QQmlImageProviderBase
182 \brief The QQmlImageProviderBase class is used to register image providers in the QML engine.
185 Image providers must be registered with the QML engine. The only information the QML
186 engine knows about image providers is the type of image data they provide. To use an
187 image provider to acquire image data, you must cast the QQmlImageProviderBase pointer
188 to a QQuickImageProvider pointer.
190 \sa QQuickImageProvider, QQuickTextureFactory
194 \enum QQmlImageProviderBase::ImageType
196 Defines the type of image supported by this image provider.
198 \value Image The Image Provider provides QImage images.
199 The QQuickImageProvider::requestImage() method will be called for all image requests.
200 \value Pixmap The Image Provider provides QPixmap images.
201 The QQuickImageProvider::requestPixmap() method will be called for all image requests.
202 \value Texture The Image Provider provides QSGTextureProvider based images.
203 The QQuickImageProvider::requestTexture() method will be called for all image requests. \omitvalue
207 QQmlImageProviderBase::QQmlImageProviderBase()
212 QQmlImageProviderBase::~QQmlImageProviderBase()
218 \qmlclass Qt QQmlEnginePrivate
219 \ingroup qml-utility-elements
220 \brief The QML global Qt object provides useful enums and functions from Qt.
222 \keyword QmlGlobalQtObject
224 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
226 The \c Qt object is a global object with utility functions, properties and enums.
228 It is not instantiable; to use it, call the members of the global \c Qt object directly.
235 color: Qt.rgba(1, 0, 0, 1)
236 text: Qt.md5("hello, world")
243 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
244 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
248 The Qt object also contains helper functions for creating objects of specific
249 data types. This is primarily useful when setting the properties of an item
250 when the property has one of the following types:
253 \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()}
254 \li \c rect - use \l{Qt::rect()}{Qt.rect()}
255 \li \c point - use \l{Qt::point()}{Qt.point()}
256 \li \c size - use \l{Qt::size()}{Qt.size()}
257 \li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
260 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
262 \section1 Date/Time Formatters
264 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
267 \li \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
268 \li \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
269 \li \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
272 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
275 \section1 Dynamic Object Creation
276 The following functions on the global object allow you to dynamically create QML
277 items from files or strings. See \l{Dynamic Object Management in QML} for an overview
281 \li \l{Qt::createComponent()}{object Qt.createComponent(url)}
282 \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
288 \qmlproperty object Qt::application
291 The \c application object provides access to global application state
292 properties shared by many QML components.
298 \li \c application.active
300 This read-only property indicates whether the application is the top-most and focused
301 application, and the user is able to interact with the application. The property
302 is false when the application is in the background, the device keylock or screen
303 saver is active, the screen backlight is turned off, or the global system dialog
304 is being displayed on top of the application. It can be used for stopping and
305 pausing animations, timers and active processing of data in order to save device
306 battery power and free device memory and processor load when the application is not
310 \li \c application.layoutDirection
312 This read-only property can be used to query the default layout direction of the
313 application. On system start-up, the default layout direction depends on the
314 application's language. The property has a value of \c Qt.RightToLeft in locales
315 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
316 where the reading direction flows from left to right. You can bind to this
317 property to customize your application layouts to support both layout directions.
322 \li Qt.LeftToRight - Text and graphics elements should be positioned
324 \li Qt.RightToLeft - Text and graphics elements should be positioned
329 \li \c application.inputPanel
331 This read-only property allows access to application's QInputPanel object
332 and all its properties and slots. See the QInputPanel documentation for
333 further details. Deprecated in favor of Qt.InputMethod
336 The following example uses the \c application object to indicate
337 whether the application is currently active:
339 \snippet doc/src/snippets/qml/application.qml document
341 \qmlproperty object Qt::inputMethod
344 The \c inputMethod object allows access to application's QInputMethod object
345 and all its properties and slots. See the QInputMethod documentation for
351 \qmlmethod object Qt::include(string url, jsobject callback)
353 Includes another JavaScript file. This method can only be used from within JavaScript files,
354 and not regular QML files.
356 This imports all functions from \a url into the current script's namespace.
358 Qt.include() returns an object that describes the status of the operation. The object has
359 a single property, \c {status}, that is set to one of the following values:
362 \header \li Symbol \li Value \li Description
363 \row \li result.OK \li 0 \li The include completed successfully.
364 \row \li result.LOADING \li 1 \li Data is being loaded from the network.
365 \row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
366 \row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
367 An additional \c exception property will be set in this case.
370 The \c status property will be updated as the operation progresses.
372 If provided, \a callback is invoked when the operation completes. The callback is passed
373 the same object as is returned from the Qt.include() call.
375 // Qt.include() is implemented in qv8include.cpp
378 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
379 : propertyCapture(0), rootContext(0), isDebugging(false),
380 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
381 cleanup(0), erroredBindings(0), inProgressCreations(0),
382 workerScriptEngine(0), activeVME(0),
383 networkAccessManager(0), networkAccessManagerFactory(0),
384 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
385 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
389 QQmlEnginePrivate::~QQmlEnginePrivate()
391 if (inProgressCreations)
392 qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
395 QQmlCleanup *c = cleanup;
397 if (cleanup) cleanup->prev = &cleanup;
403 doDeleteInEngineThread();
405 if (incubationController) incubationController->d = 0;
406 incubationController = 0;
411 for(QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
413 for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
415 for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
417 for(QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
418 delete (*iter)->qobjectApi;
423 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
425 QObjectPrivate *p = QObjectPrivate::get(o);
426 if (p->declarativeData) {
427 QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
428 if (d->ownContext && d->context) {
429 d->context->destroy();
435 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
437 static_cast<QQmlData *>(d)->destroyed(o);
440 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
442 static_cast<QQmlData *>(d)->parentChanged(o, p);
445 void QQmlData::objectNameChanged(QAbstractDeclarativeData *d, QObject *o)
447 static_cast<QQmlData *>(d)->objectNameChanged(o);
450 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **)
452 QQmlData *ddata = QQmlData::get(object, false);
453 if (!ddata) return; // Probably being deleted
455 QQmlNotifierEndpoint *ep = ddata->notify(index);
456 if (ep) QQmlNotifier::emitNotify(ep);
459 void QQmlEnginePrivate::init()
463 static bool firstTime = true;
465 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component");
470 qRegisterMetaType<QVariant>("QVariant");
471 qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
472 qRegisterMetaType<QJSValue>("QJSValue");
473 qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
474 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
475 qRegisterMetaType<QList<int> >("QList<int>");
476 qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
480 v8engine()->setEngine(q);
482 rootContext = new QQmlContext(q,true);
484 if (QCoreApplication::instance()->thread() == q->thread() &&
485 QQmlEngineDebugService::isDebuggingEnabled()) {
487 QQmlEngineDebugService::instance()->addEngine(q);
488 QV8DebugService::initialize(v8engine());
489 QV8ProfilerService::initialize();
490 QQmlProfilerService::initialize();
491 QDebugMessageService::instance();
494 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
495 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator()) +
496 QDir::separator() + QLatin1String("QML") +
497 QDir::separator() + QLatin1String("OfflineStorage");
500 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
503 if (!workerScriptEngine)
504 workerScriptEngine = new QQuickWorkerScriptEngine(q);
505 return workerScriptEngine;
511 \brief The QQmlEngine class provides an environment for instantiating QML components.
514 Each QML component is instantiated in a QQmlContext.
515 QQmlContext's are essential for passing data to QML
516 components. In QML, contexts are arranged hierarchically and this
517 hierarchy is managed by the QQmlEngine.
519 Prior to creating any QML components, an application must have
520 created a QQmlEngine to gain access to a QML context. The
521 following example shows how to create a simple Text item.
525 QQmlComponent component(&engine);
526 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
527 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
529 //add item to view, etc
533 In this case, the Text item will be created in the engine's
534 \l {QQmlEngine::rootContext()}{root context}.
536 \sa QQmlComponent QQmlContext
540 Create a new QQmlEngine with the given \a parent.
542 QQmlEngine::QQmlEngine(QObject *parent)
543 : QJSEngine(*new QQmlEnginePrivate(this), parent)
550 Destroys the QQmlEngine.
552 Any QQmlContext's created on this engine will be
553 invalidated, but not destroyed (unless they are parented to the
556 QQmlEngine::~QQmlEngine()
559 if (d->isDebugging) {
560 QQmlEngineDebugService::instance()->remEngine(this);
563 // if we are the parent of any of the qobject module api instances,
564 // we need to remove them from our internal list, in order to prevent
565 // a segfault in engine private dtor.
566 QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
567 QObject *currQObjectApi = 0;
568 QQmlMetaType::ModuleApiInstance *currInstance = 0;
569 foreach (const QQmlMetaType::ModuleApi &key, keys) {
570 currInstance = d->moduleApiInstances.value(key);
571 currQObjectApi = currInstance->qobjectApi;
572 if (this->children().contains(currQObjectApi)) {
573 delete currQObjectApi;
575 d->moduleApiInstances.remove(key);
579 // ensure we clean up QObjects with JS ownership
582 if (d->incubationController)
583 d->incubationController->d = 0;
586 /*! \fn void QQmlEngine::quit()
587 This signal is emitted when the QML loaded by the engine would like to quit.
590 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
591 This signal is emitted when \a warnings messages are generated by QML.
595 Clears the engine's internal component cache.
597 Normally the QQmlEngine caches components loaded from qml
598 files. This method clears this cache and forces the component to be
601 void QQmlEngine::clearComponentCache()
604 d->typeLoader.clearCache();
608 Returns the engine's root context.
610 The root context is automatically created by the QQmlEngine.
611 Data that should be available to all QML component instances
612 instantiated by the engine should be put in the root context.
614 Additional data that should only be available to a subset of
615 component instances should be added to sub-contexts parented to the
618 QQmlContext *QQmlEngine::rootContext() const
620 Q_D(const QQmlEngine);
621 return d->rootContext;
625 Sets the \a factory to use for creating QNetworkAccessManager(s).
627 QNetworkAccessManager is used for all network access by QML. By
628 implementing a factory it is possible to create custom
629 QNetworkAccessManager with specialized caching, proxy and cookie
632 The factory must be set before executing the engine.
634 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
637 QMutexLocker locker(&d->mutex);
638 d->networkAccessManagerFactory = factory;
642 Returns the current QQmlNetworkAccessManagerFactory.
644 \sa setNetworkAccessManagerFactory()
646 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
648 Q_D(const QQmlEngine);
649 return d->networkAccessManagerFactory;
652 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
655 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
657 void *args[] = { 0 };
658 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
662 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
664 QMutexLocker locker(&mutex);
665 QNetworkAccessManager *nam;
666 if (networkAccessManagerFactory) {
667 nam = networkAccessManagerFactory->create(parent);
669 nam = new QNetworkAccessManager(parent);
675 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
677 Q_Q(const QQmlEngine);
678 if (!networkAccessManager)
679 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
680 return networkAccessManager;
684 Returns a common QNetworkAccessManager which can be used by any QML
685 element instantiated by this engine.
687 If a QQmlNetworkAccessManagerFactory has been set and a
688 QNetworkAccessManager has not yet been created, the
689 QQmlNetworkAccessManagerFactory will be used to create the
690 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
691 will have no proxy or cache set.
693 \sa setNetworkAccessManagerFactory()
695 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
697 Q_D(const QQmlEngine);
698 return d->getNetworkAccessManager();
703 Sets the \a provider to use for images requested via the \e
704 image: url scheme, with host \a providerId. The QQmlEngine
705 takes ownership of \a provider.
707 Image providers enable support for pixmap and threaded image
708 requests. See the QQuickImageProvider documentation for details on
709 implementing and using image providers.
711 All required image providers should be added to the engine before any
712 QML sources files are loaded.
714 \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
716 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
719 QMutexLocker locker(&d->mutex);
720 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
724 Returns the image provider set for \a providerId.
726 Returns the provider if it was found; otherwise returns 0.
728 \sa QQuickImageProvider
730 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
732 Q_D(const QQmlEngine);
733 QMutexLocker locker(&d->mutex);
734 return d->imageProviders.value(providerId).data();
738 Removes the image provider for \a providerId.
740 \sa addImageProvider(), QQuickImageProvider
742 void QQmlEngine::removeImageProvider(const QString &providerId)
745 QMutexLocker locker(&d->mutex);
746 d->imageProviders.take(providerId);
750 Return the base URL for this engine. The base URL is only used to
751 resolve components when a relative URL is passed to the
752 QQmlComponent constructor.
754 If a base URL has not been explicitly set, this method returns the
755 application's current working directory.
759 QUrl QQmlEngine::baseUrl() const
761 Q_D(const QQmlEngine);
762 if (d->baseUrl.isEmpty()) {
763 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
770 Set the base URL for this engine to \a url.
774 void QQmlEngine::setBaseUrl(const QUrl &url)
781 Returns true if warning messages will be output to stderr in addition
782 to being emitted by the warnings() signal, otherwise false.
784 The default value is true.
786 bool QQmlEngine::outputWarningsToStandardError() const
788 Q_D(const QQmlEngine);
789 return d->outputWarningsToStdErr;
793 Set whether warning messages will be output to stderr to \a enabled.
795 If \a enabled is true, any warning messages generated by QML will be
796 output to stderr and emitted by the warnings() signal. If \a enabled
797 is false, on the warnings() signal will be emitted. This allows
798 applications to handle warning output themselves.
800 The default value is true.
802 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
805 d->outputWarningsToStdErr = enabled;
809 Attempt to free unused memory.
811 void QQmlEngine::collectGarbage()
817 Returns the QQmlContext for the \a object, or 0 if no
818 context has been set.
820 When the QQmlEngine instantiates a QObject, the context is
823 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
828 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
831 static_cast<QQmlData *>(priv->declarativeData);
835 else if (data->outerContext)
836 return data->outerContext->asQQmlContext();
842 Sets the QQmlContext for the \a object to \a context.
843 If the \a object already has a context, a warning is
844 output, but the context is not changed.
846 When the QQmlEngine instantiates a QObject, the context is
849 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
851 if (!object || !context)
854 QQmlData *data = QQmlData::get(object, true);
856 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
860 QQmlContextData *contextData = QQmlContextData::get(context);
861 contextData->addObject(object);
865 \enum QQmlEngine::ObjectOwnership
867 Ownership controls whether or not QML automatically destroys the
868 QObject when the object is garbage collected by the JavaScript
869 engine. The two ownership options are:
871 \value CppOwnership The object is owned by C++ code, and will
872 never be deleted by QML. The JavaScript destroy() method cannot be
873 used on objects with CppOwnership. This option is similar to
874 QScriptEngine::QtOwnership.
876 \value JavaScriptOwnership The object is owned by JavaScript.
877 When the object is returned to QML as the return value of a method
878 call or property access, QML will delete the object if there are no
879 remaining JavaScript references to it and it has no
880 QObject::parent(). This option is similar to
881 QScriptEngine::ScriptOwnership.
883 Generally an application doesn't need to set an object's ownership
884 explicitly. QML uses a heuristic to set the default object
885 ownership. By default, an object that is created by QML has
886 JavaScriptOwnership. The exception to this are the root objects
887 created by calling QQmlComponent::create() or
888 QQmlComponent::beginCreate() which have CppOwnership by
889 default. The ownership of these root-level objects is considered to
890 have been transferred to the C++ caller.
892 Objects not-created by QML have CppOwnership by default. The
893 exception to this is objects returned from a C++ method call. The
894 ownership of these objects is passed to JavaScript.
896 Calling setObjectOwnership() overrides the default ownership
897 heuristic used by QML.
901 Sets the \a ownership of \a object.
903 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
908 QQmlData *ddata = QQmlData::get(object, true);
912 ddata->indestructible = (ownership == CppOwnership)?true:false;
913 ddata->explicitIndestructibleSet = true;
917 Returns the ownership of \a object.
919 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
924 QQmlData *ddata = QQmlData::get(object, false);
928 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
931 bool QQmlEngine::event(QEvent *e)
934 if (e->type() == QEvent::User)
935 d->doDeleteInEngineThread();
937 return QJSEngine::event(e);
940 void QQmlEnginePrivate::doDeleteInEngineThread()
942 QFieldList<Deletable, &Deletable::next> list;
944 list.copyAndClear(toDeleteInEngineThread);
947 while (Deletable *d = list.takeFirst())
951 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
953 QQmlData *data = QQmlData::get(object);
955 if (data && data->deferredComponent) {
956 QQmlObjectCreatingProfiler prof;
958 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
959 prof.setTypeName(type ? type->qmlTypeName()
960 : QString::fromUtf8(object->metaObject()->className()));
961 if (data->outerContext)
962 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
964 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
966 QQmlComponentPrivate::ConstructionState state;
967 QQmlComponentPrivate::beginDeferred(ep, object, &state);
969 data->deferredComponent->release();
970 data->deferredComponent = 0;
972 QQmlComponentPrivate::complete(ep, &state);
976 QQmlContext *qmlContext(const QObject *obj)
978 return QQmlEngine::contextForObject(obj);
981 QQmlEngine *qmlEngine(const QObject *obj)
983 QQmlData *data = QQmlData::get(obj, false);
984 if (!data || !data->context)
986 return data->context->engine;
989 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
991 QQmlData *data = QQmlData::get(object);
993 return 0; // Attached properties are only on objects created by QML
995 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
999 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1003 rv = pf(const_cast<QObject *>(object));
1006 data->attachedProperties()->insert(id, rv);
1011 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1012 const QMetaObject *attachedMetaObject, bool create)
1015 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1017 if (*idCache == -1 || !object)
1020 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1023 QQmlDebuggingEnabler::QQmlDebuggingEnabler()
1025 #ifndef QQML_NO_DEBUG_PROTOCOL
1026 if (!QQmlEnginePrivate::qml_debugging_enabled) {
1027 qDebug("QML debugging is enabled. Only use this in a safe environment.");
1029 QQmlEnginePrivate::qml_debugging_enabled = true;
1034 class QQmlDataExtended {
1037 ~QQmlDataExtended();
1039 QHash<int, QObject *> attachedProperties;
1040 QQmlNotifier objectNameNotifier;
1043 QQmlDataExtended::QQmlDataExtended()
1047 QQmlDataExtended::~QQmlDataExtended()
1051 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1054 layout(endpoint->next);
1056 int index = endpoint->sourceSignal;
1057 index = qMin(index, 0xFFFF - 1);
1059 endpoint->next = notifies[index];
1060 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1061 endpoint->prev = ¬ifies[index];
1062 notifies[index] = endpoint;
1065 void QQmlData::NotifyList::layout()
1067 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1070 QQmlNotifierEndpoint **old = notifies;
1071 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1072 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1073 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1074 sizeof(QQmlNotifierEndpoint*);
1075 memset(notifies + notifiesSize, 0, memsetSize);
1077 if (notifies != old) {
1078 for (int ii = 0; ii < notifiesSize; ++ii)
1080 notifies[ii]->prev = ¬ifies[ii];
1083 notifiesSize = maximumTodoIndex + 1;
1088 maximumTodoIndex = 0;
1092 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1095 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1096 notifyList->connectionMask = 0;
1097 notifyList->maximumTodoIndex = 0;
1098 notifyList->notifiesSize = 0;
1099 notifyList->todo = 0;
1100 notifyList->notifies = 0;
1103 Q_ASSERT(!endpoint->isConnected());
1105 index = qMin(index, 0xFFFF - 1);
1106 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1108 if (index < notifyList->notifiesSize) {
1110 endpoint->next = notifyList->notifies[index];
1111 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1112 endpoint->prev = ¬ifyList->notifies[index];
1113 notifyList->notifies[index] = endpoint;
1116 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1118 endpoint->next = notifyList->todo;
1119 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1120 endpoint->prev = ¬ifyList->todo;
1121 notifyList->todo = endpoint;
1125 QQmlNotifier *QQmlData::objectNameNotifier() const
1127 if (!extendedData) extendedData = new QQmlDataExtended;
1128 return &extendedData->objectNameNotifier;
1131 QHash<int, QObject *> *QQmlData::attachedProperties() const
1133 if (!extendedData) extendedData = new QQmlDataExtended;
1134 return &extendedData->attachedProperties;
1137 void QQmlData::destroyed(QObject *object)
1139 if (deferredComponent)
1140 deferredComponent->release();
1142 if (nextContextObject)
1143 nextContextObject->prevContextObject = prevContextObject;
1144 if (prevContextObject)
1145 *prevContextObject = nextContextObject;
1147 QQmlAbstractBinding *binding = bindings;
1149 QQmlAbstractBinding *next = binding->m_nextBinding;
1150 binding->m_prevBinding = 0;
1151 binding->m_nextBinding = 0;
1160 propertyCache->release();
1162 if (ownContext && context)
1166 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1167 *guard = (QObject *)0;
1168 guard->objectDestroyed(object);
1172 while (notifyList->todo)
1173 notifyList->todo->disconnect();
1174 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1175 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1178 free(notifyList->notifies);
1183 delete extendedData;
1185 v8object.Clear(); // The WeakReference handler will clean the actual handle
1191 void QQmlData::parentChanged(QObject *object, QObject *parent)
1197 void QQmlData::objectNameChanged(QObject *)
1199 if (extendedData) objectNameNotifier()->notify();
1202 bool QQmlData::hasBindingBit(int bit) const
1204 if (bindingBitsSize > bit)
1205 return bindingBits[bit / 32] & (1 << (bit % 32));
1210 void QQmlData::clearBindingBit(int bit)
1212 if (bindingBitsSize > bit)
1213 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1216 void QQmlData::setBindingBit(QObject *obj, int bit)
1218 if (bindingBitsSize <= bit) {
1219 int props = obj->metaObject()->propertyCount();
1220 Q_ASSERT(bit < props);
1222 int arraySize = (props + 31) / 32;
1223 int oldArraySize = bindingBitsSize / 32;
1225 bindingBits = (quint32 *)realloc(bindingBits,
1226 arraySize * sizeof(quint32));
1228 memset(bindingBits + oldArraySize,
1230 sizeof(quint32) * (arraySize - oldArraySize));
1232 bindingBitsSize = arraySize * 32;
1235 bindingBits[bit / 32] |= (1 << (bit % 32));
1238 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
1240 if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
1241 if (url.authority().isEmpty())
1242 return QLatin1Char(':') + url.path();
1245 return url.toLocalFile();
1249 static QString toLocalFile(const QString &url)
1251 if (!url.startsWith(QLatin1String("file://"), Qt::CaseInsensitive))
1254 QString file = url.mid(7);
1256 //XXX TODO: handle windows hostnames: "//servername/path/to/file.txt"
1258 // magic for drives on windows
1259 if (file.length() > 2 && file.at(0) == QLatin1Char('/') && file.at(2) == QLatin1Char(':'))
1265 QString QQmlEnginePrivate::urlToLocalFileOrQrc(const QString& url)
1267 if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) {
1268 if (url.length() > 4)
1269 return QLatin1Char(':') + url.mid(4);
1273 return toLocalFile(url);
1276 void QQmlEnginePrivate::sendQuit()
1280 if (q->receivers(SIGNAL(quit())) == 0) {
1281 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1285 static void dumpwarning(const QQmlError &error)
1287 qWarning().nospace() << qPrintable(error.toString());
1290 static void dumpwarning(const QList<QQmlError> &errors)
1292 for (int ii = 0; ii < errors.count(); ++ii)
1293 dumpwarning(errors.at(ii));
1296 void QQmlEnginePrivate::warning(const QQmlError &error)
1299 q->warnings(QList<QQmlError>() << error);
1300 if (outputWarningsToStdErr)
1304 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1307 q->warnings(errors);
1308 if (outputWarningsToStdErr)
1309 dumpwarning(errors);
1312 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1315 QQmlEnginePrivate::get(engine)->warning(error);
1320 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1323 QQmlEnginePrivate::get(engine)->warning(error);
1328 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1331 engine->warning(error);
1336 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1339 engine->warning(error);
1345 This function should be called prior to evaluation of any js expression,
1346 so that scarce resources are not freed prematurely (eg, if there is a
1347 nested javascript expression).
1349 void QQmlEnginePrivate::referenceScarceResources()
1351 scarceResourcesRefCount += 1;
1355 This function should be called after evaluation of the js expression is
1356 complete, and so the scarce resources may be freed safely.
1358 void QQmlEnginePrivate::dereferenceScarceResources()
1360 Q_ASSERT(scarceResourcesRefCount > 0);
1361 scarceResourcesRefCount -= 1;
1363 // if the refcount is zero, then evaluation of the "top level"
1364 // expression must have completed. We can safely release the
1365 // scarce resources.
1366 if (scarceResourcesRefCount == 0) {
1367 // iterate through the list and release them all.
1368 // note that the actual SRD is owned by the JS engine,
1369 // so we cannot delete the SRD; but we can free the
1370 // memory used by the variant in the SRD.
1371 while (ScarceResourceData *sr = scarceResources.first()) {
1372 sr->data = QVariant();
1373 scarceResources.remove(sr);
1379 Adds \a path as a directory where the engine searches for
1380 installed modules in a URL-based directory structure.
1381 The \a path may be a local filesystem directory or a URL.
1383 The newly added \a path will be first in the importPathList().
1385 \sa setImportPathList(), {QML Modules}
1387 void QQmlEngine::addImportPath(const QString& path)
1390 d->importDatabase.addImportPath(path);
1394 Returns the list of directories where the engine searches for
1395 installed modules in a URL-based directory structure.
1397 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1398 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1399 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1400 provided by that module. A \c qmldir file is required for defining the
1401 type version mapping and possibly QML extensions plugins.
1403 By default, the list contains the directory of the application executable,
1404 paths specified in the \c QML_IMPORT_PATH environment variable,
1405 and the builtin \c ImportsPath from QLibraryInfo.
1407 \sa addImportPath() setImportPathList()
1409 QStringList QQmlEngine::importPathList() const
1411 Q_D(const QQmlEngine);
1412 return d->importDatabase.importPathList();
1416 Sets \a paths as the list of directories where the engine searches for
1417 installed modules in a URL-based directory structure.
1419 By default, the list contains the directory of the application executable,
1420 paths specified in the \c QML_IMPORT_PATH environment variable,
1421 and the builtin \c ImportsPath from QLibraryInfo.
1423 \sa importPathList() addImportPath()
1425 void QQmlEngine::setImportPathList(const QStringList &paths)
1428 d->importDatabase.setImportPathList(paths);
1433 Adds \a path as a directory where the engine searches for
1434 native plugins for imported modules (referenced in the \c qmldir file).
1436 By default, the list contains only \c ., i.e. the engine searches
1437 in the directory of the \c qmldir file itself.
1439 The newly added \a path will be first in the pluginPathList().
1441 \sa setPluginPathList()
1443 void QQmlEngine::addPluginPath(const QString& path)
1446 d->importDatabase.addPluginPath(path);
1451 Returns the list of directories where the engine searches for
1452 native plugins for imported modules (referenced in the \c qmldir file).
1454 By default, the list contains only \c ., i.e. the engine searches
1455 in the directory of the \c qmldir file itself.
1457 \sa addPluginPath() setPluginPathList()
1459 QStringList QQmlEngine::pluginPathList() const
1461 Q_D(const QQmlEngine);
1462 return d->importDatabase.pluginPathList();
1466 Sets the list of directories where the engine searches for
1467 native plugins for imported modules (referenced in the \c qmldir file)
1470 By default, the list contains only \c ., i.e. the engine searches
1471 in the directory of the \c qmldir file itself.
1473 \sa pluginPathList() addPluginPath()
1475 void QQmlEngine::setPluginPathList(const QStringList &paths)
1478 d->importDatabase.setPluginPathList(paths);
1482 Imports the plugin named \a filePath with the \a uri provided.
1483 Returns true if the plugin was successfully imported; otherwise returns false.
1485 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1487 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1489 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1492 return d->importDatabase.importPlugin(filePath, uri, errors);
1496 Imports the plugin named \a filePath with the \a uri provided.
1497 Returns true if the plugin was successfully imported; otherwise returns false.
1499 On failure and if non-null, *\a errorString will be set to a message describing the failure.
1501 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1503 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1506 QList<QQmlError> errors;
1507 bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1508 if (!errors.isEmpty()) {
1510 for (int i = 0; i < errors.size(); ++i) {
1511 builtError = QString(QLatin1String("%1\n %2"))
1513 .arg(errors.at(i).toString());
1515 *errorString = builtError;
1521 \property QQmlEngine::offlineStoragePath
1522 \brief the directory for storing offline user data
1524 Returns the directory where SQL and other offline
1527 QQuickWebView and the SQL databases created with openDatabase()
1530 The default is QML/OfflineStorage in the platform-standard
1531 user application data directory.
1533 Note that the path may not currently exist on the filesystem, so
1534 callers wanting to \e create new files at this location should create
1535 it first - see QDir::mkpath().
1537 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1540 d->offlineStoragePath = dir;
1543 QString QQmlEngine::offlineStoragePath() const
1545 Q_D(const QQmlEngine);
1546 return d->offlineStoragePath;
1549 static void voidptr_destructor(void *v)
1551 void **ptr = (void **)v;
1555 static void *voidptr_constructor(const void *v)
1560 return new void*(*(void **)v);
1564 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1568 if (!mo->superClass()) {
1569 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1570 propertyCache.insert(mo, rv);
1573 QQmlPropertyCache *super = cache(mo->superClass());
1574 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1575 propertyCache.insert(mo, rv);
1580 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1583 QList<QQmlType *> types;
1585 int maxMinorVersion = 0;
1587 const QMetaObject *metaObject = type->metaObject();
1589 while (metaObject) {
1590 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1591 type->majorVersion(), minorVersion);
1593 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1599 metaObject = metaObject->superClass();
1602 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1604 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1608 QQmlPropertyCache *raw = cache(type->metaObject());
1610 bool hasCopied = false;
1612 for (int ii = 0; ii < types.count(); ++ii) {
1613 QQmlType *currentType = types.at(ii);
1617 int rev = currentType->metaObjectRevision();
1618 int moIndex = types.count() - 1 - ii;
1620 if (raw->allowedRevisionCache[moIndex] != rev) {
1625 raw->allowedRevisionCache[moIndex] = rev;
1629 // Test revision compatibility - the basic rule is:
1630 // * Anything that is excluded, cannot overload something that is not excluded *
1632 // Signals override:
1633 // * other signals and methods of the same name.
1634 // * properties named on<Signal Name>
1635 // * automatic <property name>Changed notify signals
1637 // Methods override:
1638 // * other methods of the same name
1640 // Properties override:
1641 // * other elements of the same name
1643 bool overloadError = false;
1644 QString overloadName;
1647 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1648 !overloadError && iter != raw->stringCache.end();
1651 QQmlPropertyData *d = *iter;
1652 if (raw->isAllowedInRevision(d))
1653 continue; // Not excluded - no problems
1655 // check that a regular "name" overload isn't happening
1656 QQmlPropertyData *current = d;
1657 while (!overloadError && current) {
1658 current = d->overrideData(current);
1659 if (current && raw->isAllowedInRevision(current))
1660 overloadError = true;
1665 if (overloadError) {
1666 if (hasCopied) raw->release();
1668 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."));
1672 if (!hasCopied) raw->addref();
1673 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1675 if (minorVersion != maxMinorVersion) {
1677 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1683 QQmlMetaType::ModuleApiInstance *
1684 QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
1686 Locker locker(this);
1688 QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1690 a = new QQmlMetaType::ModuleApiInstance;
1691 a->scriptCallback = module.script;
1692 a->qobjectCallback = module.qobject;
1693 moduleApiInstances.insert(module, a);
1699 bool QQmlEnginePrivate::isQObject(int t)
1701 Locker locker(this);
1702 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1705 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1707 Locker locker(this);
1708 int t = v.userType();
1709 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1711 return *(QObject **)(v.constData());
1713 return QQmlMetaType::toQObject(v, ok);
1717 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1719 Locker locker(this);
1720 if (m_compositeTypes.contains(t))
1721 return QQmlMetaType::Object;
1722 else if (m_qmlLists.contains(t))
1723 return QQmlMetaType::List;
1725 return QQmlMetaType::typeCategory(t);
1728 bool QQmlEnginePrivate::isList(int t) const
1730 Locker locker(this);
1731 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1734 int QQmlEnginePrivate::listType(int t) const
1736 Locker locker(this);
1737 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1738 if (iter != m_qmlLists.end())
1741 return QQmlMetaType::listType(t);
1744 const QMetaObject *QQmlEnginePrivate::rawMetaObjectForType(int t) const
1746 Locker locker(this);
1747 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1748 if (iter != m_compositeTypes.end()) {
1749 return (*iter)->root;
1751 QQmlType *type = QQmlMetaType::qmlType(t);
1752 return type?type->baseMetaObject():0;
1756 const QMetaObject *QQmlEnginePrivate::metaObjectForType(int t) const
1758 Locker locker(this);
1759 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1760 if (iter != m_compositeTypes.end()) {
1761 return (*iter)->root;
1763 QQmlType *type = QQmlMetaType::qmlType(t);
1764 return type?type->metaObject():0;
1768 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
1770 QByteArray name = data->root->className();
1772 QByteArray ptr = name + '*';
1773 QByteArray lst = "QQmlListProperty<" + name + '>';
1775 int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
1776 voidptr_constructor);
1777 int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
1778 voidptr_constructor);
1782 Locker locker(this);
1783 m_qmlLists.insert(lst_type, ptr_type);
1784 m_compositeTypes.insert(ptr_type, data);
1787 bool QQml_isFileCaseCorrect(const QString &fileName)
1789 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1790 QFileInfo info(fileName);
1791 const QString absolute = info.absoluteFilePath();
1793 #if defined(Q_OS_MAC)
1794 const QString canonical = info.canonicalFilePath();
1795 #elif defined(Q_OS_WIN)
1796 wchar_t buffer[1024];
1798 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1799 if (rv == 0 || rv >= 1024) return true;
1800 rv = ::GetLongPathName(buffer, buffer, 1024);
1801 if (rv == 0 || rv >= 1024) return true;
1803 const QString canonical = QString::fromWCharArray(buffer);
1806 const int absoluteLength = absolute.length();
1807 const int canonicalLength = canonical.length();
1809 const int length = qMin(absoluteLength, canonicalLength);
1810 for (int ii = 0; ii < length; ++ii) {
1811 const QChar &a = absolute.at(absoluteLength - 1 - ii);
1812 const QChar &c = canonical.at(canonicalLength - 1 - ii);
1814 if (a.toLower() != c.toLower())
1826 \fn QQmlEngine *qmlEngine(const QObject *object)
1829 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
1830 QQmlEngine::contextForObject(object)->engine(), but more efficient.
1834 \fn QQmlContext *qmlContext(const QObject *object)
1837 Returns the QQmlContext associated with \a object, if any. This is equivalent to
1838 QQmlEngine::contextForObject(object).