1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtQml module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
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 <QtCore/qthread.h>
84 #include <private/qthread_p.h>
85 #include <QtNetwork/qnetworkconfigmanager.h>
87 #include <private/qobject_p.h>
88 #include <private/qmetaobject_p.h>
90 #include <private/qqmllocale_p.h>
92 #include "qqmlbind_p.h"
93 #include "qqmlconnections_p.h"
94 #include "qqmltimer_p.h"
96 #ifdef Q_OS_WIN // for %APPDATA%
97 #include <qt_windows.h>
101 #define CSIDL_APPDATA 0x001a // <username>\Application Data
104 Q_DECLARE_METATYPE(QQmlProperty)
108 void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
110 QQmlEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
111 QQmlEnginePrivate::registerQtQuick2Types(uri, versionMajor, versionMinor);
112 QQmlValueTypeFactory::registerValueTypes(uri, versionMajor, versionMinor);
117 \instantiates QObject
118 \inqmlmodule QtQuick 2
119 \ingroup qml-utility-elements
120 \brief A basic QML type
122 The QtObject type is a non-visual element which contains only the
125 It can be useful to create a QtObject if you need an extremely
126 lightweight type to enclose a set of custom properties:
128 \snippet qml/qtobject.qml 0
130 It can also be useful for C++ integration, as it is just a plain
131 QObject. See the QObject documentation for further details.
134 \qmlproperty string QtObject::objectName
135 This property holds the QObject::objectName for this specific object instance.
137 This allows a C++ application to locate an item within a QML component
138 using the QObject::findChild() method. For example, the following C++
139 application locates the child \l Rectangle item and dynamically changes its
148 width: 200; height: 200
162 view.setSource(QUrl::fromLocalFile("MyRect.qml"));
165 QQuickItem *item = view.rootObject()->findChild<QQuickItem*>("myRect");
167 item->setProperty("color", QColor(Qt::yellow));
171 bool QQmlEnginePrivate::qml_debugging_enabled = false;
172 bool QQmlEnginePrivate::s_designerMode = false;
174 // these types are part of the QML language
175 void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
177 qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
178 qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
179 qmlRegisterType<QQmlBind>(uri, versionMajor, versionMinor,"Binding");
180 qmlRegisterType<QQmlConnections>(uri, versionMajor, versionMinor,"Connections");
181 qmlRegisterType<QQmlTimer>(uri, versionMajor, versionMinor,"Timer");
182 qmlRegisterCustomType<QQmlConnections>(uri, versionMajor, versionMinor,"Connections", new QQmlConnectionsParser);
186 // These QtQuick types' implementation resides in the QtQml module
187 void QQmlEnginePrivate::registerQtQuick2Types(const char *uri, int versionMajor, int versionMinor)
189 qmlRegisterType<QQuickListElement>(uri, versionMajor, versionMinor, "ListElement");
190 qmlRegisterCustomType<QQuickListModel>(uri, versionMajor, versionMinor, "ListModel", new QQuickListModelParser);
191 qmlRegisterType<QQuickWorkerScript>(uri, versionMajor, versionMinor, "WorkerScript");
194 void QQmlEnginePrivate::defineQtQuick2Module()
196 // register the base types into the QtQuick namespace
197 registerBaseTypes("QtQuick",2,0);
199 // register the QtQuick2 types which are implemented in the QtQml module.
200 registerQtQuick2Types("QtQuick",2,0);
201 qmlRegisterUncreatableType<QQmlLocale>("QtQuick", 2, 0, "Locale", QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
204 bool QQmlEnginePrivate::designerMode()
206 return s_designerMode;
209 void QQmlEnginePrivate::activateDesignerMode()
211 s_designerMode = true;
216 \class QQmlImageProviderBase
217 \brief The QQmlImageProviderBase class is used to register image providers in the QML engine.
221 Image providers must be registered with the QML engine. The only information the QML
222 engine knows about image providers is the type of image data they provide. To use an
223 image provider to acquire image data, you must cast the QQmlImageProviderBase pointer
224 to a QQuickImageProvider pointer.
226 \sa QQuickImageProvider, QQuickTextureFactory
230 \enum QQmlImageProviderBase::ImageType
232 Defines the type of image supported by this image provider.
234 \value Image The Image Provider provides QImage images.
235 The QQuickImageProvider::requestImage() method will be called for all image requests.
236 \value Pixmap The Image Provider provides QPixmap images.
237 The QQuickImageProvider::requestPixmap() method will be called for all image requests.
238 \value Texture The Image Provider provides QSGTextureProvider based images.
239 The QQuickImageProvider::requestTexture() method will be called for all image requests.
244 \enum QQmlImageProviderBase::Flag
246 Defines specific requirements or features of this image provider.
248 \value ForceAsynchronousImageLoading Ensures that image requests to the provider are
249 run in a separate thread, which allows the provider to spend as much time as needed
250 on producing the image without blocking the main thread.
254 QQmlImageProviderBase::QQmlImageProviderBase()
259 QQmlImageProviderBase::~QQmlImageProviderBase()
266 \instantiates QQmlEnginePrivate
267 \ingroup qml-utility-elements
268 \brief The QML global Qt object provides useful enums and functions from Qt.
270 \keyword QmlGlobalQtObject
272 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
274 The \c Qt object is a global object with utility functions, properties and enums.
276 It is not instantiable; to use it, call the members of the global \c Qt object directly.
283 color: Qt.rgba(1, 0, 0, 1)
284 text: Qt.md5("hello, world")
291 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
292 the \l Qt::LeftButton and \l Qt::RightButton enumeration values as \c Qt.LeftButton and \c Qt.RightButton.
297 The Qt object also contains helper functions for creating objects of specific
298 data types. This is primarily useful when setting the properties of an item
299 when the property has one of the following types:
301 \li \c rect - use \l{Qt::rect()}{Qt.rect()}
302 \li \c point - use \l{Qt::point()}{Qt.point()}
303 \li \c size - use \l{Qt::size()}{Qt.size()}
306 If the QtQuick module has been imported, the following helper functions for
307 creating objects of specific data types are also available for clients to use:
309 \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()}
310 \li \c font - use \l{Qt::font()}{Qt.font()}
311 \li \c vector2d - use \l{Qt::vector2d()}{Qt.vector2d()}
312 \li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
313 \li \c vector4d - use \l{Qt::vector4d()}{Qt.vector4d()}
314 \li \c quaternion - use \l{Qt::quaternion()}{Qt.quaternion()}
315 \li \c matrix4x4 - use \l{Qt::matrix4x4()}{Qt.matrix4x4()}
318 There are also string based constructors for these types. See \l{qtqml-typesystem-basictypes.html}{QML Basic Types} for more information.
320 \section1 Date/Time Formatters
322 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
325 \li \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
326 \li \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
327 \li \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
330 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
333 \section1 Dynamic Object Creation
334 The following functions on the global object allow you to dynamically create QML
335 items from files or strings. See \l{Dynamic QML Object Creation from JavaScript} for an overview
339 \li \l{Qt::createComponent()}{object Qt.createComponent(url)}
340 \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
344 \section1 Other Functions
346 The following functions are also on the Qt object.
349 \li \l{Qt::quit()}{Qt.quit()}
350 \li \l{Qt::md5()}{Qt.md5(string)}
351 \li \l{Qt::btoa()}{string Qt.btoa(string)}
352 \li \l{Qt::atob()}{string Qt.atob(string)}
353 \li \l{Qt::binding()}{object Qt.binding(function)}
354 \li \l{Qt::locale()}{object Qt.locale()}
355 \li \l{Qt::resolvedUrl()}{string Qt.resolvedUrl(string)}
356 \li \l{Qt::openUrlExternally()}{Qt.openUrlExternally(string)}
357 \li \l{Qt::fontFamilies()}{list<string> Qt.fontFamilies()}
362 \qmlproperty object Qt::application
365 The \c application object provides access to global application state
366 properties shared by many QML components.
372 \li \c application.active
374 This read-only property indicates whether the application is the top-most and focused
375 application, and the user is able to interact with the application. The property
376 is false when the application is in the background, the device keylock or screen
377 saver is active, the screen backlight is turned off, or the global system dialog
378 is being displayed on top of the application. It can be used for stopping and
379 pausing animations, timers and active processing of data in order to save device
380 battery power and free device memory and processor load when the application is not
384 \li \c application.layoutDirection
386 This read-only property can be used to query the default layout direction of the
387 application. On system start-up, the default layout direction depends on the
388 application's language. The property has a value of \c Qt.RightToLeft in locales
389 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
390 where the reading direction flows from left to right. You can bind to this
391 property to customize your application layouts to support both layout directions.
396 \li Qt.LeftToRight - Text and graphics elements should be positioned
398 \li Qt.RightToLeft - Text and graphics elements should be positioned
404 The following example uses the \c application object to indicate
405 whether the application is currently active:
407 \snippet qml/application.qml document
411 \qmlproperty object Qt::inputMethod
414 The \c inputMethod object allows access to application's QInputMethod object
415 and all its properties and slots. See the QInputMethod documentation for
421 \qmlmethod object Qt::include(string url, jsobject callback)
423 Includes another JavaScript file. This method can only be used from within JavaScript files,
424 and not regular QML files.
426 This imports all functions from \a url into the current script's namespace.
428 Qt.include() returns an object that describes the status of the operation. The object has
429 a single property, \c {status}, that is set to one of the following values:
432 \header \li Symbol \li Value \li Description
433 \row \li result.OK \li 0 \li The include completed successfully.
434 \row \li result.LOADING \li 1 \li Data is being loaded from the network.
435 \row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
436 \row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
437 An additional \c exception property will be set in this case.
440 The \c status property will be updated as the operation progresses.
442 If provided, \a callback is invoked when the operation completes. The callback is passed
443 the same object as is returned from the Qt.include() call.
445 // Qt.include() is implemented in qv8include.cpp
448 QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
449 : propertyCapture(0), rootContext(0), isDebugging(false),
450 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
451 cleanup(0), erroredBindings(0), inProgressCreations(0),
452 workerScriptEngine(0), activeVME(0),
453 networkAccessManager(0), networkAccessManagerFactory(0),
454 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
455 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
459 QQmlEnginePrivate::~QQmlEnginePrivate()
461 if (inProgressCreations)
462 qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
465 QQmlCleanup *c = cleanup;
467 if (cleanup) cleanup->prev = &cleanup;
473 doDeleteInEngineThread();
475 if (incubationController) incubationController->d = 0;
476 incubationController = 0;
481 for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
483 for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
485 for (QHash<int, QQmlCompiledData *>::Iterator iter = m_compositeTypes.begin(); iter != m_compositeTypes.end(); ++iter)
486 iter.value()->isRegisteredWithEngine = false;
489 void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
491 QObjectPrivate *p = QObjectPrivate::get(o);
492 if (p->declarativeData) {
493 QQmlData *d = static_cast<QQmlData*>(p->declarativeData);
494 if (d->ownContext && d->context) {
495 d->context->destroy();
499 // Mark this object as in the process of deletion to
500 // prevent it resolving in bindings
501 QQmlData::markAsDeleted(o);
503 // Disconnect the notifiers now - during object destruction this would be too late, since
504 // the disconnect call wouldn't be able to call disconnectNotify(), as it isn't possible to
505 // get the metaobject anymore.
506 d->disconnectNotifiers();
510 void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
512 static_cast<QQmlData *>(d)->destroyed(o);
515 void QQmlData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
517 static_cast<QQmlData *>(d)->parentChanged(o, p);
520 class QQmlThreadNotifierProxyObject : public QObject
523 QPointer<QObject> target;
525 virtual int qt_metacall(QMetaObject::Call, int methodIndex, void **a) {
529 QMetaMethod method = target->metaObject()->method(methodIndex);
530 Q_ASSERT(method.methodType() == QMetaMethod::Signal);
531 int signalIndex = QMetaObjectPrivate::signalIndex(method);
532 QQmlData *ddata = QQmlData::get(target, false);
533 QQmlNotifierEndpoint *ep = ddata->notify(signalIndex);
534 if (ep) QQmlNotifier::emitNotify(ep, a);
542 void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **a)
544 QQmlData *ddata = QQmlData::get(object, false);
545 if (!ddata) return; // Probably being deleted
547 // In general, QML only supports QObject's that live on the same thread as the QQmlEngine
548 // that they're exposed to. However, to make writing "worker objects" that calculate data
549 // in a separate thread easier, QML allows a QObject that lives in the same thread as the
550 // QQmlEngine to emit signals from a different thread. These signals are then automatically
551 // marshalled back onto the QObject's thread and handled by QML from there. This is tested
552 // by the qqmlecmascript::threadSignal() autotest.
553 if (ddata->notifyList &&
554 QThread::currentThreadId() != QObjectPrivate::get(object)->threadData->threadId) {
556 if (!QObjectPrivate::get(object)->threadData->thread)
559 QMetaMethod m = QMetaObjectPrivate::signal(object->metaObject(), index);
560 QList<QByteArray> parameterTypes = m.parameterTypes();
562 int *types = (int *)malloc((parameterTypes.count() + 1) * sizeof(int));
563 void **args = (void **) malloc((parameterTypes.count() + 1) *sizeof(void *));
565 types[0] = 0; // return type
566 args[0] = 0; // return value
568 for (int ii = 0; ii < parameterTypes.count(); ++ii) {
569 const QByteArray &typeName = parameterTypes.at(ii);
570 if (typeName.endsWith('*'))
571 types[ii + 1] = QMetaType::VoidStar;
573 types[ii + 1] = QMetaType::type(typeName);
575 if (!types[ii + 1]) {
576 qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
577 "(Make sure '%s' is registered using qRegisterMetaType().)",
578 typeName.constData(), typeName.constData());
584 args[ii + 1] = QMetaType::create(types[ii + 1], a[ii + 1]);
587 QMetaCallEvent *ev = new QMetaCallEvent(m.methodIndex(), 0, 0, object, index,
588 parameterTypes.count() + 1, types, args);
590 QQmlThreadNotifierProxyObject *mpo = new QQmlThreadNotifierProxyObject;
591 mpo->target = object;
592 mpo->moveToThread(QObjectPrivate::get(object)->threadData->thread);
593 QCoreApplication::postEvent(mpo, ev);
596 QQmlNotifierEndpoint *ep = ddata->notify(index);
597 if (ep) QQmlNotifier::emitNotify(ep, a);
601 int QQmlData::receivers(QAbstractDeclarativeData *d, const QObject *, int index)
603 return static_cast<QQmlData *>(d)->endpointCount(index);
606 bool QQmlData::isSignalConnected(QAbstractDeclarativeData *d, const QObject *, int index)
608 return static_cast<QQmlData *>(d)->signalHasEndpoint(index);
611 int QQmlData::endpointCount(int index)
614 QQmlNotifierEndpoint *ep = notify(index);
625 void QQmlData::markAsDeleted(QObject *o)
627 QQmlData::setQueuedForDeletion(o);
629 QObjectPrivate *p = QObjectPrivate::get(o);
630 for (QList<QObject *>::iterator it = p->children.begin(), end = p->children.end(); it != end; ++it) {
631 QQmlData::markAsDeleted(*it);
635 void QQmlData::setQueuedForDeletion(QObject *object)
638 if (QObjectPrivate *priv = QObjectPrivate::get(object)) {
639 if (!priv->wasDeleted && priv->declarativeData) {
640 QQmlData *ddata = QQmlData::get(object, false);
641 if (ddata->ownContext && ddata->context)
642 ddata->context->emitDestruction();
643 ddata->isQueuedForDeletion = true;
649 void QQmlData::flushPendingBindingImpl(int coreIndex)
651 clearPendingBindingBit(coreIndex);
654 QQmlAbstractBinding *b = bindings;
655 while (b && *b->m_mePtr && b->propertyIndex() != coreIndex)
656 b = b->nextBinding();
660 b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor |
661 QQmlPropertyPrivate::DontRemoveBinding);
665 void QQmlEnginePrivate::init()
669 static bool firstTime = true;
671 qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component"); // required for the Compiler.
672 registerBaseTypes("QtQml", 2, 0); // import which provides language building blocks.
678 qRegisterMetaType<QVariant>();
679 qRegisterMetaType<QQmlScriptString>();
680 qRegisterMetaType<QJSValue>();
681 qRegisterMetaType<QQmlComponent::Status>();
682 qRegisterMetaType<QList<QObject*> >();
683 qRegisterMetaType<QList<int> >();
684 qRegisterMetaType<QQmlV8Handle>();
686 v8engine()->setEngine(q);
688 rootContext = new QQmlContext(q,true);
690 if (QCoreApplication::instance()->thread() == q->thread() &&
691 QQmlEngineDebugService::isDebuggingEnabled()) {
693 QQmlEngineDebugService::instance()->addEngine(q);
694 QV8DebugService::initialize(v8engine());
695 QV8ProfilerService::initialize();
696 QQmlProfilerService::initialize();
697 QDebugMessageService::instance();
700 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
701 if (!dataLocation.isEmpty())
702 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator())
703 + QDir::separator() + QLatin1String("QML")
704 + QDir::separator() + QLatin1String("OfflineStorage");
707 QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
710 if (!workerScriptEngine)
711 workerScriptEngine = new QQuickWorkerScriptEngine(q);
712 return workerScriptEngine;
719 \brief The QQmlEngine class provides an environment for instantiating QML components.
722 Each QML component is instantiated in a QQmlContext.
723 QQmlContext's are essential for passing data to QML
724 components. In QML, contexts are arranged hierarchically and this
725 hierarchy is managed by the QQmlEngine.
727 Prior to creating any QML components, an application must have
728 created a QQmlEngine to gain access to a QML context. The
729 following example shows how to create a simple Text item.
733 QQmlComponent component(&engine);
734 component.setData("import QtQuick 2.0\nText { text: \"Hello world!\" }", QUrl());
735 QQuickItem *item = qobject_cast<QQuickItem *>(component.create());
737 //add item to view, etc
741 In this case, the Text item will be created in the engine's
742 \l {QQmlEngine::rootContext()}{root context}.
744 Note that the QtQuick 1 version is called QDeclarativeEngine.
746 \sa QQmlComponent, QQmlContext
750 Create a new QQmlEngine with the given \a parent.
752 QQmlEngine::QQmlEngine(QObject *parent)
753 : QJSEngine(*new QQmlEnginePrivate(this), parent)
760 Destroys the QQmlEngine.
762 Any QQmlContext's created on this engine will be
763 invalidated, but not destroyed (unless they are parented to the
766 QQmlEngine::~QQmlEngine()
769 if (d->isDebugging) {
770 QQmlEngineDebugService::instance()->remEngine(this);
773 // Emit onDestruction signals for the root context before
774 // we destroy the contexts, engine, Singleton Types etc. that
775 // may be required to handle the destruction signal.
776 QQmlContextData::get(rootContext())->emitDestruction();
778 // clean up all singleton type instances which we own.
779 // we do this here and not in the private dtor since otherwise a crash can
780 // occur (if we are the QObject parent of the QObject singleton instance)
781 // XXX TODO: performance -- store list of singleton types separately?
782 QList<QQmlType*> singletonTypes = QQmlMetaType::qmlSingletonTypes();
783 foreach (QQmlType *currType, singletonTypes)
784 currType->singletonInstanceInfo()->destroy(this);
786 if (d->incubationController)
787 d->incubationController->d = 0;
790 /*! \fn void QQmlEngine::quit()
791 This signal is emitted when the QML loaded by the engine would like to quit.
794 /*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
795 This signal is emitted when \a warnings messages are generated by QML.
799 Clears the engine's internal component cache.
801 This function causes the property metadata of all components previously
802 loaded by the engine to be destroyed. All previously loaded components and
803 the property bindings for all extant objects created from those components will
806 This function returns the engine to a state where it does not contain any loaded
807 component data. This may be useful in order to reload a smaller subset of the
808 previous component set, or to load a new version of a previously loaded component.
810 Once the component cache has been cleared, components must be loaded before
811 any new objects can be created.
813 \sa trimComponentCache()
815 void QQmlEngine::clearComponentCache()
818 d->typeLoader.clearCache();
822 Trims the engine's internal component cache.
824 This function causes the property metadata of any loaded components which are
825 not currently in use to be destroyed.
827 A component is considered to be in use if there are any extant instances of
828 the component itself, any instances of other components that use the component,
829 or any objects instantiated by any of those components.
831 \sa clearComponentCache()
833 void QQmlEngine::trimComponentCache()
836 d->typeLoader.trimCache();
840 Returns the engine's root context.
842 The root context is automatically created by the QQmlEngine.
843 Data that should be available to all QML component instances
844 instantiated by the engine should be put in the root context.
846 Additional data that should only be available to a subset of
847 component instances should be added to sub-contexts parented to the
850 QQmlContext *QQmlEngine::rootContext() const
852 Q_D(const QQmlEngine);
853 return d->rootContext;
857 Sets the \a factory to use for creating QNetworkAccessManager(s).
859 QNetworkAccessManager is used for all network access by QML. By
860 implementing a factory it is possible to create custom
861 QNetworkAccessManager with specialized caching, proxy and cookie
864 The factory must be set before executing the engine.
866 void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
869 QMutexLocker locker(&d->mutex);
870 d->networkAccessManagerFactory = factory;
874 Returns the current QQmlNetworkAccessManagerFactory.
876 \sa setNetworkAccessManagerFactory()
878 QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
880 Q_D(const QQmlEngine);
881 return d->networkAccessManagerFactory;
884 void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
887 activeVME->finalizeCallbacks.append(qMakePair(QQmlGuard<QObject>(obj), index));
889 void *args[] = { 0 };
890 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
894 QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
896 QMutexLocker locker(&mutex);
897 QNetworkAccessManager *nam;
898 if (networkAccessManagerFactory) {
899 nam = networkAccessManagerFactory->create(parent);
901 nam = new QNetworkAccessManager(parent);
907 QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
909 Q_Q(const QQmlEngine);
910 if (!networkAccessManager)
911 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
912 return networkAccessManager;
916 Returns a common QNetworkAccessManager which can be used by any QML
917 type instantiated by this engine.
919 If a QQmlNetworkAccessManagerFactory has been set and a
920 QNetworkAccessManager has not yet been created, the
921 QQmlNetworkAccessManagerFactory will be used to create the
922 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
923 will have no proxy or cache set.
925 \sa setNetworkAccessManagerFactory()
927 QNetworkAccessManager *QQmlEngine::networkAccessManager() const
929 Q_D(const QQmlEngine);
930 return d->getNetworkAccessManager();
935 Sets the \a provider to use for images requested via the \e
936 image: url scheme, with host \a providerId. The QQmlEngine
937 takes ownership of \a provider.
939 Image providers enable support for pixmap and threaded image
940 requests. See the QQuickImageProvider documentation for details on
941 implementing and using image providers.
943 All required image providers should be added to the engine before any
944 QML sources files are loaded.
946 \sa removeImageProvider(), QQuickImageProvider, QQmlImageProviderBase
948 void QQmlEngine::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
951 QMutexLocker locker(&d->mutex);
952 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QQmlImageProviderBase>(provider));
956 Returns the image provider set for \a providerId.
958 Returns the provider if it was found; otherwise returns 0.
960 \sa QQuickImageProvider
962 QQmlImageProviderBase *QQmlEngine::imageProvider(const QString &providerId) const
964 Q_D(const QQmlEngine);
965 QMutexLocker locker(&d->mutex);
966 return d->imageProviders.value(providerId).data();
970 Removes the image provider for \a providerId.
972 \sa addImageProvider(), QQuickImageProvider
974 void QQmlEngine::removeImageProvider(const QString &providerId)
977 QMutexLocker locker(&d->mutex);
978 d->imageProviders.take(providerId);
982 Return the base URL for this engine. The base URL is only used to
983 resolve components when a relative URL is passed to the
984 QQmlComponent constructor.
986 If a base URL has not been explicitly set, this method returns the
987 application's current working directory.
991 QUrl QQmlEngine::baseUrl() const
993 Q_D(const QQmlEngine);
994 if (d->baseUrl.isEmpty()) {
995 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
1002 Set the base URL for this engine to \a url.
1006 void QQmlEngine::setBaseUrl(const QUrl &url)
1013 Returns true if warning messages will be output to stderr in addition
1014 to being emitted by the warnings() signal, otherwise false.
1016 The default value is true.
1018 bool QQmlEngine::outputWarningsToStandardError() const
1020 Q_D(const QQmlEngine);
1021 return d->outputWarningsToStdErr;
1025 Set whether warning messages will be output to stderr to \a enabled.
1027 If \a enabled is true, any warning messages generated by QML will be
1028 output to stderr and emitted by the warnings() signal. If \a enabled
1029 is false, on the warnings() signal will be emitted. This allows
1030 applications to handle warning output themselves.
1032 The default value is true.
1034 void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
1037 d->outputWarningsToStdErr = enabled;
1041 Returns the QQmlContext for the \a object, or 0 if no
1042 context has been set.
1044 When the QQmlEngine instantiates a QObject, the context is
1047 QQmlContext *QQmlEngine::contextForObject(const QObject *object)
1052 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
1055 static_cast<QQmlData *>(priv->declarativeData);
1059 else if (data->outerContext)
1060 return data->outerContext->asQQmlContext();
1066 Sets the QQmlContext for the \a object to \a context.
1067 If the \a object already has a context, a warning is
1068 output, but the context is not changed.
1070 When the QQmlEngine instantiates a QObject, the context is
1073 void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
1075 if (!object || !context)
1078 QQmlData *data = QQmlData::get(object, true);
1079 if (data->context) {
1080 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
1084 QQmlContextData *contextData = QQmlContextData::get(context);
1085 contextData->addObject(object);
1089 \enum QQmlEngine::ObjectOwnership
1091 Ownership controls whether or not QML automatically destroys the
1092 QObject when the object is garbage collected by the JavaScript
1093 engine. The two ownership options are:
1095 \value CppOwnership The object is owned by C++ code, and will
1096 never be deleted by QML. The JavaScript destroy() method cannot be
1097 used on objects with CppOwnership. This option is similar to
1098 QScriptEngine::QtOwnership.
1100 \value JavaScriptOwnership The object is owned by JavaScript.
1101 When the object is returned to QML as the return value of a method
1102 call or property access, QML will track it, and delete the object
1103 if there are no remaining JavaScript references to it and it has no
1104 QObject::parent(). An object tracked by one QQmlEngine
1105 will be deleted during that QQmlEngine's destructor, and thus
1106 JavaScript references between objects with JavaScriptOwnership from
1107 two different engines will not be valid after the deletion of one of
1108 those engines. This option is similar to QScriptEngine::ScriptOwnership.
1110 Generally an application doesn't need to set an object's ownership
1111 explicitly. QML uses a heuristic to set the default object
1112 ownership. By default, an object that is created by QML has
1113 JavaScriptOwnership. The exception to this are the root objects
1114 created by calling QQmlComponent::create() or
1115 QQmlComponent::beginCreate() which have CppOwnership by
1116 default. The ownership of these root-level objects is considered to
1117 have been transferred to the C++ caller.
1119 Objects not-created by QML have CppOwnership by default. The
1120 exception to this is objects returned from C++ method calls; in these cases,
1121 the ownership of the returned objects will be set to JavaScriptOwnerShip.
1122 Note this applies only to explicit invocations of Q_INVOKABLE methods or slots,
1123 and not to property getter invocations.
1125 Calling setObjectOwnership() overrides the default ownership
1126 heuristic used by QML.
1130 Sets the \a ownership of \a object.
1132 void QQmlEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
1137 QQmlData *ddata = QQmlData::get(object, true);
1141 ddata->indestructible = (ownership == CppOwnership)?true:false;
1142 ddata->explicitIndestructibleSet = true;
1146 Returns the ownership of \a object.
1148 QQmlEngine::ObjectOwnership QQmlEngine::objectOwnership(QObject *object)
1151 return CppOwnership;
1153 QQmlData *ddata = QQmlData::get(object, false);
1155 return CppOwnership;
1157 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
1160 bool QQmlEngine::event(QEvent *e)
1163 if (e->type() == QEvent::User)
1164 d->doDeleteInEngineThread();
1166 return QJSEngine::event(e);
1169 void QQmlEnginePrivate::doDeleteInEngineThread()
1171 QFieldList<Deletable, &Deletable::next> list;
1173 list.copyAndClear(toDeleteInEngineThread);
1176 while (Deletable *d = list.takeFirst())
1180 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
1182 QQmlData *data = QQmlData::get(object);
1184 if (data && data->compiledData && data->deferredIdx) {
1185 QQmlObjectCreatingProfiler prof;
1187 QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
1188 prof.setTypeName(type ? type->qmlTypeName()
1189 : QString::fromUtf8(object->metaObject()->className()));
1190 if (data->outerContext)
1191 prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
1193 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
1195 QQmlComponentPrivate::ConstructionState state;
1196 QQmlComponentPrivate::beginDeferred(ep, object, &state);
1198 // Release the reference for the deferral action (we still have one from construction)
1199 data->compiledData->release();
1200 data->compiledData = 0;
1202 QQmlComponentPrivate::complete(ep, &state);
1206 QQmlContext *qmlContext(const QObject *obj)
1208 return QQmlEngine::contextForObject(obj);
1211 QQmlEngine *qmlEngine(const QObject *obj)
1213 QQmlData *data = QQmlData::get(obj, false);
1214 if (!data || !data->context)
1216 return data->context->engine;
1219 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1221 QQmlData *data = QQmlData::get(object);
1223 return 0; // Attached properties are only on objects created by QML
1225 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1229 QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(id);
1233 rv = pf(const_cast<QObject *>(object));
1236 data->attachedProperties()->insert(id, rv);
1241 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1242 const QMetaObject *attachedMetaObject, bool create)
1245 *idCache = QQmlMetaType::attachedPropertiesFuncId(attachedMetaObject);
1247 if (*idCache == -1 || !object)
1250 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1253 QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
1255 #ifndef QQML_NO_DEBUG_PROTOCOL
1256 if (!QQmlEnginePrivate::qml_debugging_enabled
1258 qDebug("QML debugging is enabled. Only use this in a safe environment.");
1260 QQmlEnginePrivate::qml_debugging_enabled = true;
1265 class QQmlDataExtended {
1268 ~QQmlDataExtended();
1270 QHash<int, QObject *> attachedProperties;
1273 QQmlDataExtended::QQmlDataExtended()
1277 QQmlDataExtended::~QQmlDataExtended()
1281 void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1284 layout(endpoint->next);
1286 int index = endpoint->sourceSignal;
1287 index = qMin(index, 0xFFFF - 1);
1289 endpoint->next = notifies[index];
1290 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1291 endpoint->prev = ¬ifies[index];
1292 notifies[index] = endpoint;
1295 void QQmlData::NotifyList::layout()
1297 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1300 QQmlNotifierEndpoint **old = notifies;
1301 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1302 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1303 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1304 sizeof(QQmlNotifierEndpoint*);
1305 memset(notifies + notifiesSize, 0, memsetSize);
1307 if (notifies != old) {
1308 for (int ii = 0; ii < notifiesSize; ++ii)
1310 notifies[ii]->prev = ¬ifies[ii];
1313 notifiesSize = maximumTodoIndex + 1;
1318 maximumTodoIndex = 0;
1322 void QQmlData::addNotify(int index, QQmlNotifierEndpoint *endpoint)
1325 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1326 notifyList->connectionMask = 0;
1327 notifyList->maximumTodoIndex = 0;
1328 notifyList->notifiesSize = 0;
1329 notifyList->todo = 0;
1330 notifyList->notifies = 0;
1333 Q_ASSERT(!endpoint->isConnected());
1335 index = qMin(index, 0xFFFF - 1);
1336 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1338 if (index < notifyList->notifiesSize) {
1340 endpoint->next = notifyList->notifies[index];
1341 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1342 endpoint->prev = ¬ifyList->notifies[index];
1343 notifyList->notifies[index] = endpoint;
1346 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1348 endpoint->next = notifyList->todo;
1349 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1350 endpoint->prev = ¬ifyList->todo;
1351 notifyList->todo = endpoint;
1356 index MUST in the range returned by QObjectPrivate::signalIndex()
1357 This is different than the index returned by QMetaMethod::methodIndex()
1359 bool QQmlData::signalHasEndpoint(int index)
1361 return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
1364 void QQmlData::disconnectNotifiers()
1367 while (notifyList->todo)
1368 notifyList->todo->disconnect();
1369 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1370 while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
1373 free(notifyList->notifies);
1379 QHash<int, QObject *> *QQmlData::attachedProperties() const
1381 if (!extendedData) extendedData = new QQmlDataExtended;
1382 return &extendedData->attachedProperties;
1385 void QQmlData::destroyed(QObject *object)
1387 if (nextContextObject)
1388 nextContextObject->prevContextObject = prevContextObject;
1389 if (prevContextObject)
1390 *prevContextObject = nextContextObject;
1392 QQmlAbstractBinding *binding = bindings;
1394 QQmlAbstractBinding *next = binding->nextBinding();
1395 binding->setAddedToObject(false);
1396 binding->setNextBinding(0);
1402 compiledData->release();
1406 QQmlAbstractBoundSignal *signalHandler = signalHandlers;
1407 while (signalHandler) {
1408 if (signalHandler->isEvaluating()) {
1409 // The object is being deleted during signal handler evaluation.
1410 // This will cause a crash due to invalid memory access when the
1411 // evaluation has completed.
1412 // Abort with a friendly message instead.
1413 QString locationString;
1414 QQmlBoundSignalExpression *expr = signalHandler->expression();
1416 QString fileName = expr->sourceFile();
1417 if (fileName.isEmpty())
1418 fileName = QStringLiteral("<Unknown File>");
1419 locationString.append(fileName);
1420 locationString.append(QString::fromLatin1(":%0: ").arg(expr->lineNumber()));
1421 QString source = expr->expression();
1422 if (source.size() > 100) {
1423 source.truncate(96);
1424 source.append(QStringLiteral(" ..."));
1426 locationString.append(source);
1428 locationString = QStringLiteral("<Unknown Location>");
1430 qFatal("Object %p destroyed while one of its QML signal handlers is in progress.\n"
1431 "Most likely the object was deleted synchronously (use QObject::deleteLater() "
1432 "instead), or the application is running a nested event loop.\n"
1433 "This behavior is NOT supported!\n"
1434 "%s", object, qPrintable(locationString));
1437 QQmlAbstractBoundSignal *next = signalHandler->m_nextSignal;
1438 signalHandler->m_prevSignal = 0;
1439 signalHandler->m_nextSignal = 0;
1440 delete signalHandler;
1441 signalHandler = next;
1448 propertyCache->release();
1450 if (ownContext && context)
1454 QQmlGuard<QObject> *guard = static_cast<QQmlGuard<QObject> *>(guards);
1455 *guard = (QObject *)0;
1456 guard->objectDestroyed(object);
1459 disconnectNotifiers();
1462 delete extendedData;
1464 // Dispose the handle.
1465 // We don't simply clear it (and wait for next gc cycle to dispose
1466 // via the weak qobject reference callback) as this affects the
1467 // outcomes of v8's gc statistical analysis heuristics, which can
1468 // cause unnecessary growth of the old pointer space js heap area.
1469 qPersistentDispose(v8object);
1475 DEFINE_BOOL_CONFIG_OPTION(parentTest, QML_PARENT_TEST);
1477 void QQmlData::parentChanged(QObject *object, QObject *parent)
1480 if (parentFrozen && !QObjectPrivate::get(object)->wasDeleted) {
1484 { QDebug dbg(&on); dbg << object; on = on.left(on.length() - 1); }
1485 { QDebug dbg(&pn); dbg << parent; pn = pn.left(pn.length() - 1); }
1487 qFatal("Object %s has had its parent frozen by QML and cannot be changed.\n"
1488 "User code is attempting to change it to %s.\n"
1489 "This behavior is NOT supported!", qPrintable(on), qPrintable(pn));
1494 static void QQmlData_setBit(QQmlData *data, QObject *obj, int bit)
1496 if (data->bindingBitsSize <= bit) {
1497 int props = QQmlMetaObject(obj).propertyCount();
1498 Q_ASSERT(bit < 2 * props);
1500 int arraySize = (2 * props + 31) / 32;
1501 int oldArraySize = data->bindingBitsSize / 32;
1503 data->bindingBits = (quint32 *)realloc(data->bindingBits,
1504 arraySize * sizeof(quint32));
1506 memset(data->bindingBits + oldArraySize,
1508 sizeof(quint32) * (arraySize - oldArraySize));
1510 data->bindingBitsSize = arraySize * 32;
1513 data->bindingBits[bit / 32] |= (1 << (bit % 32));
1516 static void QQmlData_clearBit(QQmlData *data, int bit)
1518 if (data->bindingBitsSize > bit)
1519 data->bindingBits[bit / 32] &= ~(1 << (bit % 32));
1522 void QQmlData::clearBindingBit(int coreIndex)
1524 QQmlData_clearBit(this, coreIndex * 2);
1527 void QQmlData::setBindingBit(QObject *obj, int coreIndex)
1529 QQmlData_setBit(this, obj, coreIndex * 2);
1532 void QQmlData::clearPendingBindingBit(int coreIndex)
1534 QQmlData_clearBit(this, coreIndex * 2 + 1);
1537 void QQmlData::setPendingBindingBit(QObject *obj, int coreIndex)
1539 QQmlData_setBit(this, obj, coreIndex * 2 + 1);
1542 void QQmlEnginePrivate::sendQuit()
1546 if (q->receivers(SIGNAL(quit())) == 0) {
1547 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1551 static void dumpwarning(const QQmlError &error)
1553 QMessageLogger(error.url().toString().toLatin1().constData(),
1554 error.line(), 0).warning().nospace()
1555 << qPrintable(error.toString());
1558 static void dumpwarning(const QList<QQmlError> &errors)
1560 for (int ii = 0; ii < errors.count(); ++ii)
1561 dumpwarning(errors.at(ii));
1564 void QQmlEnginePrivate::warning(const QQmlError &error)
1567 q->warnings(QList<QQmlError>() << error);
1568 if (outputWarningsToStdErr)
1572 void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1575 q->warnings(errors);
1576 if (outputWarningsToStdErr)
1577 dumpwarning(errors);
1580 void QQmlEnginePrivate::warning(QQmlDelayedError *error)
1583 warning(error->error(q));
1586 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QQmlError &error)
1589 QQmlEnginePrivate::get(engine)->warning(error);
1594 void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1597 QQmlEnginePrivate::get(engine)->warning(error);
1602 void QQmlEnginePrivate::warning(QQmlEngine *engine, QQmlDelayedError *error)
1605 QQmlEnginePrivate::get(engine)->warning(error);
1607 dumpwarning(error->error(0));
1610 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QQmlError &error)
1613 engine->warning(error);
1618 void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError> &error)
1621 engine->warning(error);
1627 This function should be called prior to evaluation of any js expression,
1628 so that scarce resources are not freed prematurely (eg, if there is a
1629 nested javascript expression).
1631 void QQmlEnginePrivate::referenceScarceResources()
1633 scarceResourcesRefCount += 1;
1637 This function should be called after evaluation of the js expression is
1638 complete, and so the scarce resources may be freed safely.
1640 void QQmlEnginePrivate::dereferenceScarceResources()
1642 Q_ASSERT(scarceResourcesRefCount > 0);
1643 scarceResourcesRefCount -= 1;
1645 // if the refcount is zero, then evaluation of the "top level"
1646 // expression must have completed. We can safely release the
1647 // scarce resources.
1648 if (scarceResourcesRefCount == 0) {
1649 // iterate through the list and release them all.
1650 // note that the actual SRD is owned by the JS engine,
1651 // so we cannot delete the SRD; but we can free the
1652 // memory used by the variant in the SRD.
1653 while (ScarceResourceData *sr = scarceResources.first()) {
1654 sr->data = QVariant();
1655 scarceResources.remove(sr);
1661 Adds \a path as a directory where the engine searches for
1662 installed modules in a URL-based directory structure.
1664 The \a path may be a local filesystem directory, a
1665 \l {The Qt Resource System}{Qt Resource} path (\c {:/imports}), a
1666 \l {The Qt Resource System}{Qt Resource} url (\c {qrc:/imports}) or a URL.
1668 The \a path will be converted into canonical form before it
1669 is added to the import path list.
1671 The newly added \a path will be first in the importPathList().
1673 \sa setImportPathList(), {QML Modules}
1675 void QQmlEngine::addImportPath(const QString& path)
1678 d->importDatabase.addImportPath(path);
1682 Returns the list of directories where the engine searches for
1683 installed modules in a URL-based directory structure.
1685 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1686 imports \c com.mycompany.Feature will cause the QQmlEngine to look
1687 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1688 provided by that module. A \c qmldir file is required for defining the
1689 type version mapping and possibly QML extensions plugins.
1691 By default, the list contains the directory of the application executable,
1692 paths specified in the \c QML2_IMPORT_PATH environment variable,
1693 and the builtin \c Qml2ImportsPath from QLibraryInfo.
1695 \sa addImportPath(), setImportPathList()
1697 QStringList QQmlEngine::importPathList() const
1699 Q_D(const QQmlEngine);
1700 return d->importDatabase.importPathList();
1704 Sets \a paths as the list of directories where the engine searches for
1705 installed modules in a URL-based directory structure.
1707 By default, the list contains the directory of the application executable,
1708 paths specified in the \c QML2_IMPORT_PATH environment variable,
1709 and the builtin \c Qml2ImportsPath from QLibraryInfo.
1711 \sa importPathList(), addImportPath()
1713 void QQmlEngine::setImportPathList(const QStringList &paths)
1716 d->importDatabase.setImportPathList(paths);
1721 Adds \a path as a directory where the engine searches for
1722 native plugins for imported modules (referenced in the \c qmldir file).
1724 By default, the list contains only \c ., i.e. the engine searches
1725 in the directory of the \c qmldir file itself.
1727 The newly added \a path will be first in the pluginPathList().
1729 \sa setPluginPathList()
1731 void QQmlEngine::addPluginPath(const QString& path)
1734 d->importDatabase.addPluginPath(path);
1739 Returns the list of directories where the engine searches for
1740 native plugins for imported modules (referenced in the \c qmldir file).
1742 By default, the list contains only \c ., i.e. the engine searches
1743 in the directory of the \c qmldir file itself.
1745 \sa addPluginPath(), setPluginPathList()
1747 QStringList QQmlEngine::pluginPathList() const
1749 Q_D(const QQmlEngine);
1750 return d->importDatabase.pluginPathList();
1754 Sets the list of directories where the engine searches for
1755 native plugins for imported modules (referenced in the \c qmldir file)
1758 By default, the list contains only \c ., i.e. the engine searches
1759 in the directory of the \c qmldir file itself.
1761 \sa pluginPathList(), addPluginPath()
1763 void QQmlEngine::setPluginPathList(const QStringList &paths)
1766 d->importDatabase.setPluginPathList(paths);
1770 Imports the plugin named \a filePath with the \a uri provided.
1771 Returns true if the plugin was successfully imported; otherwise returns false.
1773 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1775 The plugin has to be a Qt plugin which implements the QQmlExtensionPlugin interface.
1777 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1780 return d->importDatabase.importPlugin(filePath, uri, QString(), errors);
1784 \property QQmlEngine::offlineStoragePath
1785 \brief the directory for storing offline user data
1787 Returns the directory where SQL and other offline
1790 QQuickWebView and the SQL databases created with openDatabase()
1793 The default is QML/OfflineStorage in the platform-standard
1794 user application data directory.
1796 Note that the path may not currently exist on the filesystem, so
1797 callers wanting to \e create new files at this location should create
1798 it first - see QDir::mkpath().
1800 void QQmlEngine::setOfflineStoragePath(const QString& dir)
1803 d->offlineStoragePath = dir;
1806 QString QQmlEngine::offlineStoragePath() const
1808 Q_D(const QQmlEngine);
1809 return d->offlineStoragePath;
1812 QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
1816 if (!mo->superClass()) {
1817 QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
1818 propertyCache.insert(mo, rv);
1821 QQmlPropertyCache *super = cache(mo->superClass());
1822 QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
1823 propertyCache.insert(mo, rv);
1828 QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
1831 QList<QQmlType *> types;
1833 int maxMinorVersion = 0;
1835 const QMetaObject *metaObject = type->metaObject();
1837 while (metaObject) {
1838 QQmlType *t = QQmlMetaType::qmlType(metaObject, type->module(),
1839 type->majorVersion(), minorVersion);
1841 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1847 metaObject = metaObject->superClass();
1850 if (QQmlPropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1852 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1856 QQmlPropertyCache *raw = cache(type->metaObject());
1858 bool hasCopied = false;
1860 for (int ii = 0; ii < types.count(); ++ii) {
1861 QQmlType *currentType = types.at(ii);
1865 int rev = currentType->metaObjectRevision();
1866 int moIndex = types.count() - 1 - ii;
1868 if (raw->allowedRevisionCache[moIndex] != rev) {
1873 raw->allowedRevisionCache[moIndex] = rev;
1877 // Test revision compatibility - the basic rule is:
1878 // * Anything that is excluded, cannot overload something that is not excluded *
1880 // Signals override:
1881 // * other signals and methods of the same name.
1882 // * properties named on<Signal Name>
1883 // * automatic <property name>Changed notify signals
1885 // Methods override:
1886 // * other methods of the same name
1888 // Properties override:
1889 // * other elements of the same name
1891 bool overloadError = false;
1892 QString overloadName;
1895 for (QQmlPropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1896 !overloadError && iter != raw->stringCache.end();
1899 QQmlPropertyData *d = *iter;
1900 if (raw->isAllowedInRevision(d))
1901 continue; // Not excluded - no problems
1903 // check that a regular "name" overload isn't happening
1904 QQmlPropertyData *current = d;
1905 while (!overloadError && current) {
1906 current = d->overrideData(current);
1907 if (current && raw->isAllowedInRevision(current))
1908 overloadError = true;
1913 if (overloadError) {
1914 if (hasCopied) raw->release();
1916 error.setDescription(QLatin1String("Type ") + type->qmlTypeName() + QLatin1Char(' ') + QString::number(type->majorVersion()) + QLatin1Char('.') + QString::number(minorVersion) + QLatin1String(" contains an illegal property \"") + overloadName + QLatin1String("\". This is an error in the type's implementation."));
1920 if (!hasCopied) raw->addref();
1921 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1923 if (minorVersion != maxMinorVersion) {
1925 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1931 bool QQmlEnginePrivate::isQObject(int t)
1933 Locker locker(this);
1934 return m_compositeTypes.contains(t) || QQmlMetaType::isQObject(t);
1937 QObject *QQmlEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1939 Locker locker(this);
1940 int t = v.userType();
1941 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1943 return *(QObject **)(v.constData());
1945 return QQmlMetaType::toQObject(v, ok);
1949 QQmlMetaType::TypeCategory QQmlEnginePrivate::typeCategory(int t) const
1951 Locker locker(this);
1952 if (m_compositeTypes.contains(t))
1953 return QQmlMetaType::Object;
1954 else if (m_qmlLists.contains(t))
1955 return QQmlMetaType::List;
1957 return QQmlMetaType::typeCategory(t);
1960 bool QQmlEnginePrivate::isList(int t) const
1962 Locker locker(this);
1963 return m_qmlLists.contains(t) || QQmlMetaType::isList(t);
1966 int QQmlEnginePrivate::listType(int t) const
1968 Locker locker(this);
1969 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1970 if (iter != m_qmlLists.end())
1973 return QQmlMetaType::listType(t);
1976 QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
1978 Locker locker(this);
1979 QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1980 if (iter != m_compositeTypes.end()) {
1981 return QQmlMetaObject((*iter)->rootPropertyCache);
1983 QQmlType *type = QQmlMetaType::qmlType(t);
1984 return QQmlMetaObject(type?type->baseMetaObject():0);
1988 QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
1990 Locker locker(this);
1991 QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.find(t);
1992 if (iter != m_compositeTypes.end()) {
1993 return QQmlMetaObject((*iter)->rootPropertyCache);
1995 QQmlType *type = QQmlMetaType::qmlType(t);
1996 return QQmlMetaObject(type?type->metaObject():0);
2000 QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
2002 Locker locker(this);
2003 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
2004 if (iter != m_compositeTypes.end()) {
2005 return (*iter)->rootPropertyCache;
2007 QQmlType *type = QQmlMetaType::qmlType(t);
2009 return type?cache(type->metaObject()):0;
2013 QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t)
2015 Locker locker(this);
2016 QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
2017 if (iter != m_compositeTypes.end()) {
2018 return (*iter)->rootPropertyCache;
2020 QQmlType *type = QQmlMetaType::qmlType(t);
2022 return type?cache(type->baseMetaObject()):0;
2026 void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
2028 QByteArray name = data->rootPropertyCache->className();
2030 QByteArray ptr = name + '*';
2031 QByteArray lst = "QQmlListProperty<" + name + '>';
2033 int ptr_type = QMetaType::registerNormalizedType(ptr,
2034 QtMetaTypePrivate::QMetaTypeFunctionHelper<QObject*>::Delete,
2035 QtMetaTypePrivate::QMetaTypeFunctionHelper<QObject*>::Create,
2036 QtMetaTypePrivate::QMetaTypeFunctionHelper<QObject*>::Destruct,
2037 QtMetaTypePrivate::QMetaTypeFunctionHelper<QObject*>::Construct,
2039 static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QObject*>::Flags),
2041 int lst_type = QMetaType::registerNormalizedType(lst,
2042 QtMetaTypePrivate::QMetaTypeFunctionHelper<QQmlListProperty<QObject> >::Delete,
2043 QtMetaTypePrivate::QMetaTypeFunctionHelper<QQmlListProperty<QObject> >::Create,
2044 QtMetaTypePrivate::QMetaTypeFunctionHelper<QQmlListProperty<QObject> >::Destruct,
2045 QtMetaTypePrivate::QMetaTypeFunctionHelper<QQmlListProperty<QObject> >::Construct,
2046 sizeof(QQmlListProperty<QObject>),
2047 static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<QObject> >::Flags),
2048 static_cast<QMetaObject*>(0));
2050 data->metaTypeId = ptr_type;
2051 data->listMetaTypeId = lst_type;
2052 data->isRegisteredWithEngine = true;
2054 Locker locker(this);
2055 m_qmlLists.insert(lst_type, ptr_type);
2056 // The QQmlCompiledData is not referenced here, but it is removed from this
2057 // hash in the QQmlCompiledData destructor
2058 m_compositeTypes.insert(ptr_type, data);
2061 void QQmlEnginePrivate::unregisterCompositeType(QQmlCompiledData *data)
2063 int ptr_type = data->metaTypeId;
2064 int lst_type = data->listMetaTypeId;
2066 Locker locker(this);
2067 m_qmlLists.remove(lst_type);
2068 m_compositeTypes.remove(ptr_type);
2071 bool QQmlEnginePrivate::isTypeLoaded(const QUrl &url) const
2073 return typeLoader.isTypeLoaded(url);
2076 bool QQmlEnginePrivate::isScriptLoaded(const QUrl &url) const
2078 return typeLoader.isScriptLoaded(url);
2081 bool QQml_isFileCaseCorrect(const QString &fileName, int lengthIn /* = -1 */)
2083 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
2084 QFileInfo info(fileName);
2085 const QString absolute = info.absoluteFilePath();
2087 #if defined(Q_OS_MAC) || defined(Q_OS_WINCE)
2088 const QString canonical = info.canonicalFilePath();
2089 #elif defined(Q_OS_WIN)
2090 wchar_t buffer[1024];
2092 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
2093 if (rv == 0 || rv >= 1024) return true;
2094 rv = ::GetLongPathName(buffer, buffer, 1024);
2095 if (rv == 0 || rv >= 1024) return true;
2097 const QString canonical = QString::fromWCharArray(buffer);
2100 const int absoluteLength = absolute.length();
2101 const int canonicalLength = canonical.length();
2103 int length = qMin(absoluteLength, canonicalLength);
2104 if (lengthIn >= 0) {
2105 length = qMin(lengthIn, length);
2107 // No length given: Limit to file name. Do not trigger
2108 // on drive letters or folder names.
2109 int lastSlash = absolute.lastIndexOf(QLatin1Char('/'));
2111 lastSlash = absolute.lastIndexOf(QLatin1Char('\\'));
2112 if (lastSlash >= 0) {
2113 const int fileNameLength = absoluteLength - 1 - lastSlash;
2114 length = qMin(length, fileNameLength);
2118 for (int ii = 0; ii < length; ++ii) {
2119 const QChar &a = absolute.at(absoluteLength - 1 - ii);
2120 const QChar &c = canonical.at(canonicalLength - 1 - ii);
2122 if (a.toLower() != c.toLower())
2135 \fn QQmlEngine *qmlEngine(const QObject *object)
2138 Returns the QQmlEngine associated with \a object, if any. This is equivalent to
2139 QQmlEngine::contextForObject(object)->engine(), but more efficient.
2143 \fn QQmlContext *qmlContext(const QObject *object)
2146 Returns the QQmlContext associated with \a object, if any. This is equivalent to
2147 QQmlEngine::contextForObject(object).