1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qdeclarativeengine_p.h"
43 #include "qdeclarativeengine.h"
44 #include "qdeclarativecomponentattached_p.h"
46 #include "qdeclarativecontext_p.h"
47 #include "qdeclarativecompiler_p.h"
48 #include "qdeclarative.h"
49 #include "qdeclarativecontext.h"
50 #include "qdeclarativeexpression.h"
51 #include "qdeclarativecomponent.h"
52 #include "qdeclarativebinding_p_p.h"
53 #include "qdeclarativevme_p.h"
54 #include <private/qdeclarativeenginedebugservice_p.h>
55 #include "qdeclarativestringconverters_p.h"
56 #include "qdeclarativexmlhttprequest_p.h"
57 #include "qdeclarativesqldatabase_p.h"
58 #include "qdeclarativescriptstring.h"
59 #include "qdeclarativeglobal_p.h"
60 #include "qdeclarativelistmodel_p.h"
61 #include "qdeclarativeworkerscript_p.h"
62 #include "qdeclarativecomponent_p.h"
63 #include "qdeclarativenetworkaccessmanagerfactory.h"
64 #include "qdeclarativeimageprovider.h"
65 #include "qdeclarativedirparser_p.h"
66 #include "qdeclarativeextensioninterface.h"
67 #include "qdeclarativelist_p.h"
68 #include "qdeclarativetypenamecache_p.h"
69 #include "qdeclarativenotifier_p.h"
70 #include <private/qdeclarativedebugtrace_p.h>
71 #include <private/qdeclarativeapplication_p.h>
72 #include <private/qv8debugservice_p.h>
73 #include <private/qdebugmessageservice_p.h>
74 #include "qdeclarativeincubator.h"
75 #include <private/qv8profilerservice_p.h>
77 #include <QtCore/qstandardpaths.h>
78 #include <QtCore/qsettings.h>
80 #include <QtCore/qmetaobject.h>
81 #include <QNetworkAccessManager>
83 #include <QMetaObject>
84 #include <QtCore/qcoreapplication.h>
85 #include <QtCore/qdir.h>
86 #include <QtCore/qmutex.h>
87 #include <QtNetwork/qnetworkconfigmanager.h>
89 #include <private/qobject_p.h>
91 #include <private/qdeclarativelocale_p.h>
93 #ifdef Q_OS_WIN // for %APPDATA%
94 #include <qt_windows.h>
98 #define CSIDL_APPDATA 0x001a // <username>\Application Data
101 Q_DECLARE_METATYPE(QDeclarativeProperty)
105 void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
107 QDeclarativeEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
108 QDeclarativeValueTypeFactory::registerBaseTypes(uri, versionMajor, versionMinor);
112 \qmlclass QtObject QObject
113 \ingroup qml-utility-elements
115 \brief The QtObject element is the most basic element in QML.
117 The QtObject element is a non-visual element which contains only the
120 It can be useful to create a QtObject if you need an extremely
121 lightweight element to enclose a set of custom properties:
123 \snippet doc/src/snippets/declarative/qtobject.qml 0
125 It can also be useful for C++ integration, as it is just a plain
126 QObject. See the QObject documentation for further details.
129 \qmlproperty string QtObject::objectName
130 This property holds the QObject::objectName for this specific object instance.
132 This allows a C++ application to locate an item within a QML component
133 using the QObject::findChild() method. For example, the following C++
134 application locates the child \l Rectangle item and dynamically changes its
143 width: 200; height: 200
156 QDeclarativeView view;
157 view.setSource(QUrl::fromLocalFile("MyRect.qml"));
160 QDeclarativeItem *item = view.rootObject()->findChild<QDeclarativeItem*>("myRect");
162 item->setProperty("color", QColor(Qt::yellow));
166 bool QDeclarativeEnginePrivate::qml_debugging_enabled = false;
168 void QDeclarativeEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
170 qmlRegisterType<QDeclarativeComponent>(uri,versionMajor,versionMinor,"Component");
171 qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
172 qmlRegisterType<QDeclarativeListElement>(uri, versionMajor, versionMinor,"ListElement");
173 qmlRegisterCustomType<QDeclarativeListModel>(uri, versionMajor, versionMinor,"ListModel", new QDeclarativeListModelParser);
174 qmlRegisterType<QDeclarativeWorkerScript>(uri,versionMajor,versionMinor,"WorkerScript");
177 void QDeclarativeEnginePrivate::defineModule()
179 registerBaseTypes("QtQuick", 2, 0);
180 qmlRegisterType<QDeclarativeBinding>();
181 qmlRegisterUncreatableType<QDeclarativeApplication>("QtQuick",2,0,"Application", QDeclarativeApplication::tr("Application is an abstract class"));
182 qmlRegisterUncreatableType<QDeclarativeLocale>("QtQuick",2,0,"Locale",QDeclarativeEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
186 \qmlclass Qt QDeclarativeEnginePrivate
187 \ingroup qml-utility-elements
188 \brief The QML global Qt object provides useful enums and functions from Qt.
190 \keyword QmlGlobalQtObject
192 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
194 The \c Qt object is a global object with utility functions, properties and enums.
196 It is not instantiable; to use it, call the members of the global \c Qt object directly.
203 color: Qt.rgba(1, 0, 0, 1)
204 text: Qt.md5("hello, world")
211 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
212 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
216 The Qt object also contains helper functions for creating objects of specific
217 data types. This is primarily useful when setting the properties of an item
218 when the property has one of the following types:
221 \o \c color - use \l{Qt::rgba()}{Qt.rgba()}, \l{Qt::hsla()}{Qt.hsla()}, \l{Qt::darker()}{Qt.darker()}, \l{Qt::lighter()}{Qt.lighter()} or \l{Qt::tint()}{Qt.tint()}
222 \o \c rect - use \l{Qt::rect()}{Qt.rect()}
223 \o \c point - use \l{Qt::point()}{Qt.point()}
224 \o \c size - use \l{Qt::size()}{Qt.size()}
225 \o \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
228 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
230 \section1 Date/Time Formatters
232 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
235 \o \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
236 \o \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
237 \o \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
240 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
243 \section1 Dynamic Object Creation
244 The following functions on the global object allow you to dynamically create QML
245 items from files or strings. See \l{Dynamic Object Management in QML} for an overview
249 \o \l{Qt::createComponent()}{object Qt.createComponent(url)}
250 \o \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
256 \qmlproperty object Qt::application
259 The \c application object provides access to global application state
260 properties shared by many QML components.
266 \o \c application.active
268 This read-only property indicates whether the application is the top-most and focused
269 application, and the user is able to interact with the application. The property
270 is false when the application is in the background, the device keylock or screen
271 saver is active, the screen backlight is turned off, or the global system dialog
272 is being displayed on top of the application. It can be used for stopping and
273 pausing animations, timers and active processing of data in order to save device
274 battery power and free device memory and processor load when the application is not
278 \o \c application.layoutDirection
280 This read-only property can be used to query the default layout direction of the
281 application. On system start-up, the default layout direction depends on the
282 application's language. The property has a value of \c Qt.RightToLeft in locales
283 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
284 where the reading direction flows from left to right. You can bind to this
285 property to customize your application layouts to support both layout directions.
290 \o Qt.LeftToRight - Text and graphics elements should be positioned
292 \o Qt.RightToLeft - Text and graphics elements should be positioned
297 \o \c application.inputPanel
299 This read-only property allows access to application's QInputPanel object
300 and all its properties and slots. See the QInputPanel documentation for
304 The following example uses the \c application object to indicate
305 whether the application is currently active:
307 \snippet doc/src/snippets/declarative/application.qml document
313 \qmlmethod object Qt::include(string url, jsobject callback)
315 Includes another JavaScript file. This method can only be used from within JavaScript files,
316 and not regular QML files.
318 This imports all functions from \a url into the current script's namespace.
320 Qt.include() returns an object that describes the status of the operation. The object has
321 a single property, \c {status}, that is set to one of the following values:
324 \header \o Symbol \o Value \o Description
325 \row \o result.OK \o 0 \o The include completed successfully.
326 \row \o result.LOADING \o 1 \o Data is being loaded from the network.
327 \row \o result.NETWORK_ERROR \o 2 \o A network error occurred while fetching the url.
328 \row \o result.EXCEPTION \o 3 \o A JavaScript exception occurred while executing the included code.
329 An additional \c exception property will be set in this case.
332 The \c status property will be updated as the operation progresses.
334 If provided, \a callback is invoked when the operation completes. The callback is passed
335 the same object as is returned from the Qt.include() call.
337 // Qt.include() is implemented in qv8include.cpp
340 QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e)
341 : propertyCapture(0), rootContext(0), isDebugging(false),
342 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
343 cleanup(0), erroredBindings(0), inProgressCreations(0),
344 workerScriptEngine(0), activeVME(0),
345 networkAccessManager(0), networkAccessManagerFactory(0),
346 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
347 incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
351 QDeclarativeEnginePrivate::~QDeclarativeEnginePrivate()
353 Q_ASSERT(inProgressCreations == 0);
356 QDeclarativeCleanup *c = cleanup;
358 if (cleanup) cleanup->prev = &cleanup;
364 doDeleteInEngineThread();
366 if (incubationController) incubationController->d = 0;
367 incubationController = 0;
372 for(QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
374 for(QHash<const QMetaObject *, QDeclarativePropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
376 for(QHash<QPair<QDeclarativeType *, int>, QDeclarativePropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
378 for(QHash<QDeclarativeMetaType::ModuleApi, QDeclarativeMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
379 delete (*iter)->qobjectApi;
384 void QDeclarativePrivate::qdeclarativeelement_destructor(QObject *o)
386 QObjectPrivate *p = QObjectPrivate::get(o);
387 if (p->declarativeData) {
388 QDeclarativeData *d = static_cast<QDeclarativeData*>(p->declarativeData);
389 if (d->ownContext && d->context) {
390 d->context->destroy();
396 void QDeclarativeData::destroyed(QAbstractDeclarativeData *d, QObject *o)
398 static_cast<QDeclarativeData *>(d)->destroyed(o);
401 void QDeclarativeData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
403 static_cast<QDeclarativeData *>(d)->parentChanged(o, p);
406 void QDeclarativeData::objectNameChanged(QAbstractDeclarativeData *d, QObject *o)
408 static_cast<QDeclarativeData *>(d)->objectNameChanged(o);
411 void QDeclarativeData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **)
413 QDeclarativeData *ddata = QDeclarativeData::get(object, false);
414 if (!ddata) return; // Probably being deleted
416 QDeclarativeNotifierEndpoint *ep = ddata->notify(index);
417 if (ep) QDeclarativeNotifier::emitNotify(ep);
420 void QDeclarativeEnginePrivate::init()
422 Q_Q(QDeclarativeEngine);
424 static bool firstTime = true;
426 // This is a nasty hack as QNetworkAccessManager will issue a
427 // BlockingQueuedConnection to the main thread if it is initialized for the
428 // first time on a non-main thread. This can cause a lockup if the main thread
429 // is blocking on the thread that initialize the network access manager.
430 QNetworkConfigurationManager man;
432 qmlRegisterType<QDeclarativeComponent>("QML", 1, 0, "Component");
437 qRegisterMetaType<QVariant>("QVariant");
438 qRegisterMetaType<QDeclarativeScriptString>("QDeclarativeScriptString");
439 qRegisterMetaType<QJSValue>("QJSValue");
440 qRegisterMetaType<QDeclarativeComponent::Status>("QDeclarativeComponent::Status");
441 qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
442 qRegisterMetaType<QList<int> >("QList<int>");
443 qRegisterMetaType<QDeclarativeV8Handle>("QDeclarativeV8Handle");
445 QDeclarativeData::init();
447 v8engine()->setEngine(q);
449 rootContext = new QDeclarativeContext(q,true);
451 if (QCoreApplication::instance()->thread() == q->thread() &&
452 QDeclarativeEngineDebugService::isDebuggingEnabled()) {
454 QDeclarativeEngineDebugService::instance()->addEngine(q);
455 QV8DebugService::initialize(v8engine());
456 QV8ProfilerService::initialize();
457 QDeclarativeDebugTrace::initialize();
458 QDebugMessageService::instance();
461 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
462 offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator()) +
463 QDir::separator() + QLatin1String("QML") +
464 QDir::separator() + QLatin1String("OfflineStorage");
467 QDeclarativeWorkerScriptEngine *QDeclarativeEnginePrivate::getWorkerScriptEngine()
469 Q_Q(QDeclarativeEngine);
470 if (!workerScriptEngine)
471 workerScriptEngine = new QDeclarativeWorkerScriptEngine(q);
472 return workerScriptEngine;
476 \class QDeclarativeEngine
478 \brief The QDeclarativeEngine class provides an environment for instantiating QML components.
481 Each QML component is instantiated in a QDeclarativeContext.
482 QDeclarativeContext's are essential for passing data to QML
483 components. In QML, contexts are arranged hierarchically and this
484 hierarchy is managed by the QDeclarativeEngine.
486 Prior to creating any QML components, an application must have
487 created a QDeclarativeEngine to gain access to a QML context. The
488 following example shows how to create a simple Text item.
491 QDeclarativeEngine engine;
492 QDeclarativeComponent component(&engine);
493 component.setData("import QtQuick 1.0\nText { text: \"Hello world!\" }", QUrl());
494 QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(component.create());
496 //add item to view, etc
500 In this case, the Text item will be created in the engine's
501 \l {QDeclarativeEngine::rootContext()}{root context}.
503 \sa QDeclarativeComponent QDeclarativeContext
507 Create a new QDeclarativeEngine with the given \a parent.
509 QDeclarativeEngine::QDeclarativeEngine(QObject *parent)
510 : QJSEngine(*new QDeclarativeEnginePrivate(this), parent)
512 Q_D(QDeclarativeEngine);
517 Destroys the QDeclarativeEngine.
519 Any QDeclarativeContext's created on this engine will be
520 invalidated, but not destroyed (unless they are parented to the
521 QDeclarativeEngine object).
523 QDeclarativeEngine::~QDeclarativeEngine()
525 Q_D(QDeclarativeEngine);
526 if (d->isDebugging) {
527 QDeclarativeEngineDebugService::instance()->remEngine(this);
530 // if we are the parent of any of the qobject module api instances,
531 // we need to remove them from our internal list, in order to prevent
532 // a segfault in engine private dtor.
533 QList<QDeclarativeMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
534 QObject *currQObjectApi = 0;
535 QDeclarativeMetaType::ModuleApiInstance *currInstance = 0;
536 foreach (const QDeclarativeMetaType::ModuleApi &key, keys) {
537 currInstance = d->moduleApiInstances.value(key);
538 currQObjectApi = currInstance->qobjectApi;
539 if (this->children().contains(currQObjectApi)) {
540 delete currQObjectApi;
542 d->moduleApiInstances.remove(key);
546 // ensure we clean up QObjects with JS ownership
549 if (d->incubationController)
550 d->incubationController->d = 0;
553 /*! \fn void QDeclarativeEngine::quit()
554 This signal is emitted when the QML loaded by the engine would like to quit.
557 /*! \fn void QDeclarativeEngine::warnings(const QList<QDeclarativeError> &warnings)
558 This signal is emitted when \a warnings messages are generated by QML.
562 Clears the engine's internal component cache.
564 Normally the QDeclarativeEngine caches components loaded from qml
565 files. This method clears this cache and forces the component to be
568 void QDeclarativeEngine::clearComponentCache()
570 Q_D(QDeclarativeEngine);
571 d->typeLoader.clearCache();
575 Returns the engine's root context.
577 The root context is automatically created by the QDeclarativeEngine.
578 Data that should be available to all QML component instances
579 instantiated by the engine should be put in the root context.
581 Additional data that should only be available to a subset of
582 component instances should be added to sub-contexts parented to the
585 QDeclarativeContext *QDeclarativeEngine::rootContext() const
587 Q_D(const QDeclarativeEngine);
588 return d->rootContext;
592 Sets the \a factory to use for creating QNetworkAccessManager(s).
594 QNetworkAccessManager is used for all network access by QML. By
595 implementing a factory it is possible to create custom
596 QNetworkAccessManager with specialized caching, proxy and cookie
599 The factory must be set before executing the engine.
601 void QDeclarativeEngine::setNetworkAccessManagerFactory(QDeclarativeNetworkAccessManagerFactory *factory)
603 Q_D(QDeclarativeEngine);
604 QMutexLocker locker(&d->mutex);
605 d->networkAccessManagerFactory = factory;
609 Returns the current QDeclarativeNetworkAccessManagerFactory.
611 \sa setNetworkAccessManagerFactory()
613 QDeclarativeNetworkAccessManagerFactory *QDeclarativeEngine::networkAccessManagerFactory() const
615 Q_D(const QDeclarativeEngine);
616 return d->networkAccessManagerFactory;
619 void QDeclarativeEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
622 activeVME->finalizeCallbacks.append(qMakePair(QDeclarativeGuard<QObject>(obj), index));
624 void *args[] = { 0 };
625 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
629 QNetworkAccessManager *QDeclarativeEnginePrivate::createNetworkAccessManager(QObject *parent) const
631 QMutexLocker locker(&mutex);
632 QNetworkAccessManager *nam;
633 if (networkAccessManagerFactory) {
634 nam = networkAccessManagerFactory->create(parent);
636 nam = new QNetworkAccessManager(parent);
642 QNetworkAccessManager *QDeclarativeEnginePrivate::getNetworkAccessManager() const
644 Q_Q(const QDeclarativeEngine);
645 if (!networkAccessManager)
646 networkAccessManager = createNetworkAccessManager(const_cast<QDeclarativeEngine*>(q));
647 return networkAccessManager;
651 Returns a common QNetworkAccessManager which can be used by any QML
652 element instantiated by this engine.
654 If a QDeclarativeNetworkAccessManagerFactory has been set and a
655 QNetworkAccessManager has not yet been created, the
656 QDeclarativeNetworkAccessManagerFactory will be used to create the
657 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
658 will have no proxy or cache set.
660 \sa setNetworkAccessManagerFactory()
662 QNetworkAccessManager *QDeclarativeEngine::networkAccessManager() const
664 Q_D(const QDeclarativeEngine);
665 return d->getNetworkAccessManager();
670 Sets the \a provider to use for images requested via the \e
671 image: url scheme, with host \a providerId. The QDeclarativeEngine
672 takes ownership of \a provider.
674 Image providers enable support for pixmap and threaded image
675 requests. See the QDeclarativeImageProvider documentation for details on
676 implementing and using image providers.
678 All required image providers should be added to the engine before any
679 QML sources files are loaded.
681 \sa removeImageProvider()
683 void QDeclarativeEngine::addImageProvider(const QString &providerId, QDeclarativeImageProvider *provider)
685 Q_D(QDeclarativeEngine);
686 QMutexLocker locker(&d->mutex);
687 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QDeclarativeImageProvider>(provider));
691 Returns the QDeclarativeImageProvider set for \a providerId.
693 Returns the provider if it was found; otherwise returns 0.
695 QDeclarativeImageProvider *QDeclarativeEngine::imageProvider(const QString &providerId) const
697 Q_D(const QDeclarativeEngine);
698 QMutexLocker locker(&d->mutex);
699 return d->imageProviders.value(providerId).data();
703 Removes the QDeclarativeImageProvider for \a providerId.
705 \sa addImageProvider()
707 void QDeclarativeEngine::removeImageProvider(const QString &providerId)
709 Q_D(QDeclarativeEngine);
710 QMutexLocker locker(&d->mutex);
711 d->imageProviders.take(providerId);
714 QDeclarativeImageProvider::ImageType QDeclarativeEnginePrivate::getImageProviderType(const QUrl &url)
716 QMutexLocker locker(&mutex);
717 QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
720 return provider->imageType();
721 return QDeclarativeImageProvider::Invalid;
724 QDeclarativeTextureFactory *QDeclarativeEnginePrivate::getTextureFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
726 QMutexLocker locker(&mutex);
727 QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
730 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
731 return provider->requestTexture(imageId, size, req_size);
736 QImage QDeclarativeEnginePrivate::getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
738 QMutexLocker locker(&mutex);
740 QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
743 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
744 image = provider->requestImage(imageId, size, req_size);
749 QPixmap QDeclarativeEnginePrivate::getPixmapFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
751 QMutexLocker locker(&mutex);
753 QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
756 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
757 pixmap = provider->requestPixmap(imageId, size, req_size);
763 Return the base URL for this engine. The base URL is only used to
764 resolve components when a relative URL is passed to the
765 QDeclarativeComponent constructor.
767 If a base URL has not been explicitly set, this method returns the
768 application's current working directory.
772 QUrl QDeclarativeEngine::baseUrl() const
774 Q_D(const QDeclarativeEngine);
775 if (d->baseUrl.isEmpty()) {
776 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
783 Set the base URL for this engine to \a url.
787 void QDeclarativeEngine::setBaseUrl(const QUrl &url)
789 Q_D(QDeclarativeEngine);
794 Returns true if warning messages will be output to stderr in addition
795 to being emitted by the warnings() signal, otherwise false.
797 The default value is true.
799 bool QDeclarativeEngine::outputWarningsToStandardError() const
801 Q_D(const QDeclarativeEngine);
802 return d->outputWarningsToStdErr;
806 Set whether warning messages will be output to stderr to \a enabled.
808 If \a enabled is true, any warning messages generated by QML will be
809 output to stderr and emitted by the warnings() signal. If \a enabled
810 is false, on the warnings() signal will be emitted. This allows
811 applications to handle warning output themselves.
813 The default value is true.
815 void QDeclarativeEngine::setOutputWarningsToStandardError(bool enabled)
817 Q_D(QDeclarativeEngine);
818 d->outputWarningsToStdErr = enabled;
822 Attempt to free unused memory.
824 void QDeclarativeEngine::collectGarbage()
830 Returns the QDeclarativeContext for the \a object, or 0 if no
831 context has been set.
833 When the QDeclarativeEngine instantiates a QObject, the context is
836 QDeclarativeContext *QDeclarativeEngine::contextForObject(const QObject *object)
841 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
843 QDeclarativeData *data =
844 static_cast<QDeclarativeData *>(priv->declarativeData);
848 else if (data->outerContext)
849 return data->outerContext->asQDeclarativeContext();
855 Sets the QDeclarativeContext for the \a object to \a context.
856 If the \a object already has a context, a warning is
857 output, but the context is not changed.
859 When the QDeclarativeEngine instantiates a QObject, the context is
862 void QDeclarativeEngine::setContextForObject(QObject *object, QDeclarativeContext *context)
864 if (!object || !context)
867 QDeclarativeData *data = QDeclarativeData::get(object, true);
869 qWarning("QDeclarativeEngine::setContextForObject(): Object already has a QDeclarativeContext");
873 QDeclarativeContextData *contextData = QDeclarativeContextData::get(context);
874 contextData->addObject(object);
878 \enum QDeclarativeEngine::ObjectOwnership
880 Ownership controls whether or not QML automatically destroys the
881 QObject when the object is garbage collected by the JavaScript
882 engine. The two ownership options are:
884 \value CppOwnership The object is owned by C++ code, and will
885 never be deleted by QML. The JavaScript destroy() method cannot be
886 used on objects with CppOwnership. This option is similar to
887 QScriptEngine::QtOwnership.
889 \value JavaScriptOwnership The object is owned by JavaScript.
890 When the object is returned to QML as the return value of a method
891 call or property access, QML will delete the object if there are no
892 remaining JavaScript references to it and it has no
893 QObject::parent(). This option is similar to
894 QScriptEngine::ScriptOwnership.
896 Generally an application doesn't need to set an object's ownership
897 explicitly. QML uses a heuristic to set the default object
898 ownership. By default, an object that is created by QML has
899 JavaScriptOwnership. The exception to this are the root objects
900 created by calling QDeclarativeCompnent::create() or
901 QDeclarativeComponent::beginCreate() which have CppOwnership by
902 default. The ownership of these root-level objects is considered to
903 have been transferred to the C++ caller.
905 Objects not-created by QML have CppOwnership by default. The
906 exception to this is objects returned from a C++ method call. The
907 ownership of these objects is passed to JavaScript.
909 Calling setObjectOwnership() overrides the default ownership
910 heuristic used by QML.
914 Sets the \a ownership of \a object.
916 void QDeclarativeEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
921 QDeclarativeData *ddata = QDeclarativeData::get(object, true);
925 ddata->indestructible = (ownership == CppOwnership)?true:false;
926 ddata->explicitIndestructibleSet = true;
930 Returns the ownership of \a object.
932 QDeclarativeEngine::ObjectOwnership QDeclarativeEngine::objectOwnership(QObject *object)
937 QDeclarativeData *ddata = QDeclarativeData::get(object, false);
941 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
944 bool QDeclarativeEngine::event(QEvent *e)
946 Q_D(QDeclarativeEngine);
947 if (e->type() == QEvent::User)
948 d->doDeleteInEngineThread();
950 return QJSEngine::event(e);
953 void QDeclarativeEnginePrivate::doDeleteInEngineThread()
955 QFieldList<Deletable, &Deletable::next> list;
957 list.copyAndClear(toDeleteInEngineThread);
960 while (Deletable *d = list.takeFirst())
964 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
966 QDeclarativeData *data = QDeclarativeData::get(object);
968 if (data && data->deferredComponent) {
969 if (QDeclarativeDebugService::isDebuggingEnabled()) {
970 QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Creating);
971 QDeclarativeType *type = QDeclarativeMetaType::qmlType(object->metaObject());
972 QString typeName = type ? type->qmlTypeName() : QString::fromUtf8(object->metaObject()->className());
973 QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Creating, typeName);
974 if (data->outerContext)
975 QDeclarativeDebugTrace::rangeLocation(QDeclarativeDebugTrace::Creating, data->outerContext->url, data->lineNumber, data->columnNumber);
977 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(data->context->engine);
979 QDeclarativeComponentPrivate::ConstructionState state;
980 QDeclarativeComponentPrivate::beginDeferred(ep, object, &state);
982 data->deferredComponent->release();
983 data->deferredComponent = 0;
985 QDeclarativeComponentPrivate::complete(ep, &state);
986 QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Creating);
990 QDeclarativeContext *qmlContext(const QObject *obj)
992 return QDeclarativeEngine::contextForObject(obj);
995 QDeclarativeEngine *qmlEngine(const QObject *obj)
997 QDeclarativeData *data = QDeclarativeData::get(obj, false);
998 if (!data || !data->context)
1000 return data->context->engine;
1003 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
1005 QDeclarativeData *data = QDeclarativeData::get(object);
1007 return 0; // Attached properties are only on objects created by QML
1009 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1013 QDeclarativeAttachedPropertiesFunc pf = QDeclarativeMetaType::attachedPropertiesFuncById(id);
1017 rv = pf(const_cast<QObject *>(object));
1020 data->attachedProperties()->insert(id, rv);
1025 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1026 const QMetaObject *attachedMetaObject, bool create)
1029 *idCache = QDeclarativeMetaType::attachedPropertiesFuncId(attachedMetaObject);
1031 if (*idCache == -1 || !object)
1034 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1037 QDeclarativeDebuggingEnabler::QDeclarativeDebuggingEnabler()
1039 #ifndef QDECLARATIVE_NO_DEBUG_PROTOCOL
1040 if (!QDeclarativeEnginePrivate::qml_debugging_enabled) {
1041 qWarning("Qml debugging is enabled. Only use this in a safe environment!");
1043 QDeclarativeEnginePrivate::qml_debugging_enabled = true;
1048 class QDeclarativeDataExtended {
1050 QDeclarativeDataExtended();
1051 ~QDeclarativeDataExtended();
1053 QHash<int, QObject *> attachedProperties;
1054 QDeclarativeNotifier objectNameNotifier;
1057 QDeclarativeDataExtended::QDeclarativeDataExtended()
1061 QDeclarativeDataExtended::~QDeclarativeDataExtended()
1065 void QDeclarativeData::NotifyList::layout(QDeclarativeNotifierEndpoint *endpoint)
1068 layout(endpoint->next);
1070 int index = endpoint->sourceSignal;
1071 index = qMin(index, 0xFFFF - 1);
1073 endpoint->next = notifies[index];
1074 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1075 endpoint->prev = ¬ifies[index];
1076 notifies[index] = endpoint;
1079 void QDeclarativeData::NotifyList::layout()
1081 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1084 QDeclarativeNotifierEndpoint **old = notifies;
1085 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QDeclarativeNotifierEndpoint*);
1086 notifies = (QDeclarativeNotifierEndpoint**)realloc(notifies, reallocSize);
1087 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1088 sizeof(QDeclarativeNotifierEndpoint*);
1089 memset(notifies + notifiesSize, 0, memsetSize);
1091 if (notifies != old) {
1092 for (int ii = 0; ii < notifiesSize; ++ii)
1094 notifies[ii]->prev = ¬ifies[ii];
1097 notifiesSize = maximumTodoIndex + 1;
1102 maximumTodoIndex = 0;
1106 void QDeclarativeData::addNotify(int index, QDeclarativeNotifierEndpoint *endpoint)
1109 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1110 notifyList->connectionMask = 0;
1111 notifyList->maximumTodoIndex = 0;
1112 notifyList->notifiesSize = 0;
1113 notifyList->todo = 0;
1114 notifyList->notifies = 0;
1117 Q_ASSERT(!endpoint->isConnected());
1119 index = qMin(index, 0xFFFF - 1);
1120 notifyList->connectionMask |= (1ULL << quint64(index % 64));
1122 if (index < notifyList->notifiesSize) {
1124 endpoint->next = notifyList->notifies[index];
1125 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1126 endpoint->prev = ¬ifyList->notifies[index];
1127 notifyList->notifies[index] = endpoint;
1130 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1132 endpoint->next = notifyList->todo;
1133 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1134 endpoint->prev = ¬ifyList->todo;
1135 notifyList->todo = endpoint;
1139 QDeclarativeNotifier *QDeclarativeData::objectNameNotifier() const
1141 if (!extendedData) extendedData = new QDeclarativeDataExtended;
1142 return &extendedData->objectNameNotifier;
1145 QHash<int, QObject *> *QDeclarativeData::attachedProperties() const
1147 if (!extendedData) extendedData = new QDeclarativeDataExtended;
1148 return &extendedData->attachedProperties;
1151 void QDeclarativeData::destroyed(QObject *object)
1153 if (deferredComponent)
1154 deferredComponent->release();
1156 if (nextContextObject)
1157 nextContextObject->prevContextObject = prevContextObject;
1158 if (prevContextObject)
1159 *prevContextObject = nextContextObject;
1161 QDeclarativeAbstractBinding *binding = bindings;
1163 QDeclarativeAbstractBinding *next = binding->m_nextBinding;
1164 binding->m_prevBinding = 0;
1165 binding->m_nextBinding = 0;
1174 propertyCache->release();
1176 if (ownContext && context)
1180 QDeclarativeGuard<QObject> *guard = static_cast<QDeclarativeGuard<QObject> *>(guards);
1181 *guard = (QObject *)0;
1182 guard->objectDestroyed(object);
1186 while (notifyList->todo)
1187 notifyList->todo->disconnect();
1188 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1189 while (QDeclarativeNotifierEndpoint *ep = notifyList->notifies[ii])
1192 free(notifyList->notifies);
1197 delete extendedData;
1199 v8object.Clear(); // The WeakReference handler will clean the actual handle
1205 void QDeclarativeData::parentChanged(QObject *object, QObject *parent)
1211 void QDeclarativeData::objectNameChanged(QObject *)
1213 if (extendedData) objectNameNotifier()->notify();
1216 bool QDeclarativeData::hasBindingBit(int bit) const
1218 if (bindingBitsSize > bit)
1219 return bindingBits[bit / 32] & (1 << (bit % 32));
1224 void QDeclarativeData::clearBindingBit(int bit)
1226 if (bindingBitsSize > bit)
1227 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1230 void QDeclarativeData::setBindingBit(QObject *obj, int bit)
1232 if (bindingBitsSize <= bit) {
1233 int props = obj->metaObject()->propertyCount();
1234 Q_ASSERT(bit < props);
1236 int arraySize = (props + 31) / 32;
1237 int oldArraySize = bindingBitsSize / 32;
1239 bindingBits = (quint32 *)realloc(bindingBits,
1240 arraySize * sizeof(quint32));
1242 memset(bindingBits + oldArraySize,
1244 sizeof(quint32) * (arraySize - oldArraySize));
1246 bindingBitsSize = arraySize * 32;
1249 bindingBits[bit / 32] |= (1 << (bit % 32));
1252 QString QDeclarativeEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
1254 if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
1255 if (url.authority().isEmpty())
1256 return QLatin1Char(':') + url.path();
1259 return url.toLocalFile();
1263 static QString toLocalFile(const QString &url)
1265 if (!url.startsWith(QLatin1String("file://"), Qt::CaseInsensitive))
1268 QString file = url.mid(7);
1270 //XXX TODO: handle windows hostnames: "//servername/path/to/file.txt"
1272 // magic for drives on windows
1273 if (file.length() > 2 && file.at(0) == QLatin1Char('/') && file.at(2) == QLatin1Char(':'))
1279 QString QDeclarativeEnginePrivate::urlToLocalFileOrQrc(const QString& url)
1281 if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) {
1282 if (url.length() > 4)
1283 return QLatin1Char(':') + url.mid(4);
1287 return toLocalFile(url);
1290 void QDeclarativeEnginePrivate::sendQuit()
1292 Q_Q(QDeclarativeEngine);
1294 if (q->receivers(SIGNAL(quit())) == 0) {
1295 qWarning("Signal QDeclarativeEngine::quit() emitted, but no receivers connected to handle it.");
1299 static void dumpwarning(const QDeclarativeError &error)
1301 qWarning().nospace() << qPrintable(error.toString());
1304 static void dumpwarning(const QList<QDeclarativeError> &errors)
1306 for (int ii = 0; ii < errors.count(); ++ii)
1307 dumpwarning(errors.at(ii));
1310 void QDeclarativeEnginePrivate::warning(const QDeclarativeError &error)
1312 Q_Q(QDeclarativeEngine);
1313 q->warnings(QList<QDeclarativeError>() << error);
1314 if (outputWarningsToStdErr)
1318 void QDeclarativeEnginePrivate::warning(const QList<QDeclarativeError> &errors)
1320 Q_Q(QDeclarativeEngine);
1321 q->warnings(errors);
1322 if (outputWarningsToStdErr)
1323 dumpwarning(errors);
1326 void QDeclarativeEnginePrivate::warning(QDeclarativeEngine *engine, const QDeclarativeError &error)
1329 QDeclarativeEnginePrivate::get(engine)->warning(error);
1334 void QDeclarativeEnginePrivate::warning(QDeclarativeEngine *engine, const QList<QDeclarativeError> &error)
1337 QDeclarativeEnginePrivate::get(engine)->warning(error);
1342 void QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate *engine, const QDeclarativeError &error)
1345 engine->warning(error);
1350 void QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate *engine, const QList<QDeclarativeError> &error)
1353 engine->warning(error);
1359 This function should be called prior to evaluation of any js expression,
1360 so that scarce resources are not freed prematurely (eg, if there is a
1361 nested javascript expression).
1363 void QDeclarativeEnginePrivate::referenceScarceResources()
1365 scarceResourcesRefCount += 1;
1369 This function should be called after evaluation of the js expression is
1370 complete, and so the scarce resources may be freed safely.
1372 void QDeclarativeEnginePrivate::dereferenceScarceResources()
1374 Q_ASSERT(scarceResourcesRefCount > 0);
1375 scarceResourcesRefCount -= 1;
1377 // if the refcount is zero, then evaluation of the "top level"
1378 // expression must have completed. We can safely release the
1379 // scarce resources.
1380 if (scarceResourcesRefCount == 0) {
1381 // iterate through the list and release them all.
1382 // note that the actual SRD is owned by the JS engine,
1383 // so we cannot delete the SRD; but we can free the
1384 // memory used by the variant in the SRD.
1385 while (ScarceResourceData *sr = scarceResources.first()) {
1386 sr->data = QVariant();
1387 scarceResources.remove(sr);
1393 Adds \a path as a directory where the engine searches for
1394 installed modules in a URL-based directory structure.
1395 The \a path may be a local filesystem directory or a URL.
1397 The newly added \a path will be first in the importPathList().
1399 \sa setImportPathList(), {QML Modules}
1401 void QDeclarativeEngine::addImportPath(const QString& path)
1403 Q_D(QDeclarativeEngine);
1404 d->importDatabase.addImportPath(path);
1408 Returns the list of directories where the engine searches for
1409 installed modules in a URL-based directory structure.
1411 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1412 imports \c com.mycompany.Feature will cause the QDeclarativeEngine to look
1413 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1414 provided by that module. A \c qmldir file is required for defining the
1415 type version mapping and possibly declarative extensions plugins.
1417 By default, the list contains the directory of the application executable,
1418 paths specified in the \c QML_IMPORT_PATH environment variable,
1419 and the builtin \c ImportsPath from QLibraryInfo.
1421 \sa addImportPath() setImportPathList()
1423 QStringList QDeclarativeEngine::importPathList() const
1425 Q_D(const QDeclarativeEngine);
1426 return d->importDatabase.importPathList();
1430 Sets \a paths as the list of directories where the engine searches for
1431 installed modules in a URL-based directory structure.
1433 By default, the list contains the directory of the application executable,
1434 paths specified in the \c QML_IMPORT_PATH environment variable,
1435 and the builtin \c ImportsPath from QLibraryInfo.
1437 \sa importPathList() addImportPath()
1439 void QDeclarativeEngine::setImportPathList(const QStringList &paths)
1441 Q_D(QDeclarativeEngine);
1442 d->importDatabase.setImportPathList(paths);
1447 Adds \a path as a directory where the engine searches for
1448 native plugins for imported modules (referenced in the \c qmldir file).
1450 By default, the list contains only \c ., i.e. the engine searches
1451 in the directory of the \c qmldir file itself.
1453 The newly added \a path will be first in the pluginPathList().
1455 \sa setPluginPathList()
1457 void QDeclarativeEngine::addPluginPath(const QString& path)
1459 Q_D(QDeclarativeEngine);
1460 d->importDatabase.addPluginPath(path);
1465 Returns the list of directories where the engine searches for
1466 native plugins for imported modules (referenced in the \c qmldir file).
1468 By default, the list contains only \c ., i.e. the engine searches
1469 in the directory of the \c qmldir file itself.
1471 \sa addPluginPath() setPluginPathList()
1473 QStringList QDeclarativeEngine::pluginPathList() const
1475 Q_D(const QDeclarativeEngine);
1476 return d->importDatabase.pluginPathList();
1480 Sets the list of directories where the engine searches for
1481 native plugins for imported modules (referenced in the \c qmldir file)
1484 By default, the list contains only \c ., i.e. the engine searches
1485 in the directory of the \c qmldir file itself.
1487 \sa pluginPathList() addPluginPath()
1489 void QDeclarativeEngine::setPluginPathList(const QStringList &paths)
1491 Q_D(QDeclarativeEngine);
1492 d->importDatabase.setPluginPathList(paths);
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, the \a errors list will have any errors which occurred prepended to it.
1501 The plugin has to be a Qt plugin which implements the QDeclarativeExtensionPlugin interface.
1503 bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &uri, QList<QDeclarativeError> *errors)
1505 Q_D(QDeclarativeEngine);
1506 return d->importDatabase.importPlugin(filePath, uri, errors);
1510 Imports the plugin named \a filePath with the \a uri provided.
1511 Returns true if the plugin was successfully imported; otherwise returns false.
1513 On failure and if non-null, *\a errorString will be set to a message describing the failure.
1515 The plugin has to be a Qt plugin which implements the QDeclarativeExtensionPlugin interface.
1517 bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1519 Q_D(QDeclarativeEngine);
1520 QList<QDeclarativeError> errors;
1521 bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1522 if (!errors.isEmpty()) {
1524 for (int i = 0; i < errors.size(); ++i) {
1525 builtError = QString(QLatin1String("%1\n %2"))
1527 .arg(errors.at(i).toString());
1529 *errorString = builtError;
1535 \property QDeclarativeEngine::offlineStoragePath
1536 \brief the directory for storing offline user data
1538 Returns the directory where SQL and other offline
1541 QDeclarativeWebView and the SQL databases created with openDatabase()
1544 The default is QML/OfflineStorage in the platform-standard
1545 user application data directory.
1547 Note that the path may not currently exist on the filesystem, so
1548 callers wanting to \e create new files at this location should create
1549 it first - see QDir::mkpath().
1551 void QDeclarativeEngine::setOfflineStoragePath(const QString& dir)
1553 Q_D(QDeclarativeEngine);
1554 d->offlineStoragePath = dir;
1557 QString QDeclarativeEngine::offlineStoragePath() const
1559 Q_D(const QDeclarativeEngine);
1560 return d->offlineStoragePath;
1563 static void voidptr_destructor(void *v)
1565 void **ptr = (void **)v;
1569 static void *voidptr_constructor(const void *v)
1574 return new void*(*(void **)v);
1578 QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(const QMetaObject *mo)
1580 Q_Q(QDeclarativeEngine);
1582 if (!mo->superClass()) {
1583 QDeclarativePropertyCache *rv = new QDeclarativePropertyCache(q, mo);
1584 propertyCache.insert(mo, rv);
1587 QDeclarativePropertyCache *super = cache(mo->superClass());
1588 QDeclarativePropertyCache *rv = super->copyAndAppend(q, mo);
1589 propertyCache.insert(mo, rv);
1594 QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(QDeclarativeType *type, int minorVersion,
1595 QDeclarativeError &error)
1597 QList<QDeclarativeType *> types;
1599 int maxMinorVersion = 0;
1601 const QMetaObject *metaObject = type->metaObject();
1603 while (metaObject) {
1604 QDeclarativeType *t = QDeclarativeMetaType::qmlType(metaObject, type->module(),
1605 type->majorVersion(), minorVersion);
1607 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1613 metaObject = metaObject->superClass();
1616 if (QDeclarativePropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1618 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1622 QDeclarativePropertyCache *raw = cache(type->metaObject());
1624 bool hasCopied = false;
1626 for (int ii = 0; ii < types.count(); ++ii) {
1627 QDeclarativeType *currentType = types.at(ii);
1631 int rev = currentType->metaObjectRevision();
1632 int moIndex = types.count() - 1 - ii;
1634 if (raw->allowedRevisionCache[moIndex] != rev) {
1639 raw->allowedRevisionCache[moIndex] = rev;
1643 // Test revision compatibility - the basic rule is:
1644 // * Anything that is excluded, cannot overload something that is not excluded *
1646 // Signals override:
1647 // * other signals and methods of the same name.
1648 // * properties named on<Signal Name>
1649 // * automatic <property name>Changed notify signals
1651 // Methods override:
1652 // * other methods of the same name
1654 // Properties override:
1655 // * other elements of the same name
1657 bool overloadError = false;
1658 QString overloadName;
1661 for (QDeclarativePropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1662 !overloadError && iter != raw->stringCache.end();
1665 QDeclarativePropertyData *d = *iter;
1666 if (raw->isAllowedInRevision(d))
1667 continue; // Not excluded - no problems
1669 // check that a regular "name" overload isn't happening
1670 QDeclarativePropertyData *current = d;
1671 while (!overloadError && current) {
1672 current = d->overrideData(current);
1673 if (current && raw->isAllowedInRevision(current))
1674 overloadError = true;
1679 if (overloadError) {
1680 if (hasCopied) raw->release();
1682 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."));
1686 if (!hasCopied) raw->addref();
1687 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1689 if (minorVersion != maxMinorVersion) {
1691 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1697 QDeclarativeMetaType::ModuleApiInstance *
1698 QDeclarativeEnginePrivate::moduleApiInstance(const QDeclarativeMetaType::ModuleApi &module)
1700 Locker locker(this);
1702 QDeclarativeMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1704 a = new QDeclarativeMetaType::ModuleApiInstance;
1705 a->scriptCallback = module.script;
1706 a->qobjectCallback = module.qobject;
1707 moduleApiInstances.insert(module, a);
1713 bool QDeclarativeEnginePrivate::isQObject(int t)
1715 Locker locker(this);
1716 return m_compositeTypes.contains(t) || QDeclarativeMetaType::isQObject(t);
1719 QObject *QDeclarativeEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1721 Locker locker(this);
1722 int t = v.userType();
1723 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1725 return *(QObject **)(v.constData());
1727 return QDeclarativeMetaType::toQObject(v, ok);
1731 QDeclarativeMetaType::TypeCategory QDeclarativeEnginePrivate::typeCategory(int t) const
1733 Locker locker(this);
1734 if (m_compositeTypes.contains(t))
1735 return QDeclarativeMetaType::Object;
1736 else if (m_qmlLists.contains(t))
1737 return QDeclarativeMetaType::List;
1739 return QDeclarativeMetaType::typeCategory(t);
1742 bool QDeclarativeEnginePrivate::isList(int t) const
1744 Locker locker(this);
1745 return m_qmlLists.contains(t) || QDeclarativeMetaType::isList(t);
1748 int QDeclarativeEnginePrivate::listType(int t) const
1750 Locker locker(this);
1751 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1752 if (iter != m_qmlLists.end())
1755 return QDeclarativeMetaType::listType(t);
1758 const QMetaObject *QDeclarativeEnginePrivate::rawMetaObjectForType(int t) const
1760 Locker locker(this);
1761 QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1762 if (iter != m_compositeTypes.end()) {
1763 return (*iter)->root;
1765 QDeclarativeType *type = QDeclarativeMetaType::qmlType(t);
1766 return type?type->baseMetaObject():0;
1770 const QMetaObject *QDeclarativeEnginePrivate::metaObjectForType(int t) const
1772 Locker locker(this);
1773 QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1774 if (iter != m_compositeTypes.end()) {
1775 return (*iter)->root;
1777 QDeclarativeType *type = QDeclarativeMetaType::qmlType(t);
1778 return type?type->metaObject():0;
1782 void QDeclarativeEnginePrivate::registerCompositeType(QDeclarativeCompiledData *data)
1784 QByteArray name = data->root->className();
1786 QByteArray ptr = name + '*';
1787 QByteArray lst = "QDeclarativeListProperty<" + name + '>';
1789 int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
1790 voidptr_constructor);
1791 int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
1792 voidptr_constructor);
1796 Locker locker(this);
1797 m_qmlLists.insert(lst_type, ptr_type);
1798 m_compositeTypes.insert(ptr_type, data);
1801 bool QDeclarative_isFileCaseCorrect(const QString &fileName)
1803 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
1804 QFileInfo info(fileName);
1805 const QString absolute = info.absoluteFilePath();
1807 #if defined(Q_OS_MAC)
1808 const QString canonical = info.canonicalFilePath();
1809 #elif defined(Q_OS_WIN)
1810 wchar_t buffer[1024];
1812 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1813 if (rv == 0 || rv >= 1024) return true;
1814 rv = ::GetLongPathName(buffer, buffer, 1024);
1815 if (rv == 0 || rv >= 1024) return true;
1817 const QString canonical = QString::fromWCharArray(buffer);
1820 const int absoluteLength = absolute.length();
1821 const int canonicalLength = canonical.length();
1823 const int length = qMin(absoluteLength, canonicalLength);
1824 for (int ii = 0; ii < length; ++ii) {
1825 const QChar &a = absolute.at(absoluteLength - 1 - ii);
1826 const QChar &c = canonical.at(canonicalLength - 1 - ii);
1828 if (a.toLower() != c.toLower())
1840 \fn QDeclarativeEngine *qmlEngine(const QObject *object)
1841 \relates QDeclarativeEngine
1843 Returns the QDeclarativeEngine associated with \a object, if any. This is equivalent to
1844 QDeclarativeEngine::contextForObject(object)->engine(), but more efficient.
1848 \fn QDeclarativeContext *qmlContext(const QObject *object)
1849 \relates QDeclarativeEngine
1851 Returns the QDeclarativeContext associated with \a object, if any. This is equivalent to
1852 QDeclarativeEngine::contextForObject(object).