1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
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"
45 #include "qdeclarativecontext_p.h"
46 #include "qdeclarativecompiler_p.h"
47 #include "qdeclarative.h"
48 #include "qdeclarativecontext.h"
49 #include "qdeclarativeexpression.h"
50 #include "qdeclarativecomponent.h"
51 #include "qdeclarativebinding_p_p.h"
52 #include "qdeclarativevme_p.h"
53 #include <private/qdeclarativeenginedebugservice_p.h>
54 #include "qdeclarativestringconverters_p.h"
55 #include "qdeclarativexmlhttprequest_p.h"
56 #include "qdeclarativesqldatabase_p.h"
57 #include "qdeclarativescriptstring.h"
58 #include "qdeclarativeglobal_p.h"
59 #include "qdeclarativeworkerscript_p.h"
60 #include "qdeclarativecomponent_p.h"
61 #include "qdeclarativenetworkaccessmanagerfactory.h"
62 #include "qdeclarativeimageprovider.h"
63 #include "qdeclarativedirparser_p.h"
64 #include "qdeclarativeextensioninterface.h"
65 #include "qdeclarativelist_p.h"
66 #include "qdeclarativetypenamecache_p.h"
67 #include "qdeclarativenotifier_p.h"
68 #include <private/qdeclarativedebugtrace_p.h>
69 #include <private/qdeclarativeapplication_p.h>
70 #include <private/qv8debugservice_p.h>
71 #include "qdeclarativeincubator.h"
72 #include <private/qv8profilerservice_p.h>
74 #include <QtCore/qmetaobject.h>
75 #include <QNetworkAccessManager>
77 #include <QMetaObject>
78 #include <QtCore/qcoreapplication.h>
79 #include <QtCore/qdir.h>
80 #include <QtCore/qmutex.h>
81 #include <QtNetwork/qnetworkconfigmanager.h>
83 #include <private/qobject_p.h>
85 #include <private/qdeclarativeutilmodule_p.h>
86 #include <private/qsgitemsmodule_p.h>
87 #include <private/qsgparticlesmodule_p.h>
89 #ifdef Q_OS_WIN // for %APPDATA%
90 #include <qt_windows.h>
94 #define CSIDL_APPDATA 0x001a // <username>\Application Data
97 Q_DECLARE_METATYPE(QDeclarativeProperty)
101 void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
103 QDeclarativeEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
104 QDeclarativeValueTypeFactory::registerBaseTypes(uri, versionMajor, versionMinor);
105 QDeclarativeUtilModule::registerBaseTypes(uri, versionMajor, versionMinor);
109 \qmlclass QtObject QObject
110 \ingroup qml-utility-elements
112 \brief The QtObject element is the most basic element in QML.
114 The QtObject element is a non-visual element which contains only the
117 It can be useful to create a QtObject if you need an extremely
118 lightweight element to enclose a set of custom properties:
120 \snippet doc/src/snippets/declarative/qtobject.qml 0
122 It can also be useful for C++ integration, as it is just a plain
123 QObject. See the QObject documentation for further details.
126 \qmlproperty string QtObject::objectName
127 This property holds the QObject::objectName for this specific object instance.
129 This allows a C++ application to locate an item within a QML component
130 using the QObject::findChild() method. For example, the following C++
131 application locates the child \l Rectangle item and dynamically changes its
140 width: 200; height: 200
153 QDeclarativeView view;
154 view.setSource(QUrl::fromLocalFile("MyRect.qml"));
157 QDeclarativeItem *item = view.rootObject()->findChild<QDeclarativeItem*>("myRect");
159 item->setProperty("color", QColor(Qt::yellow));
163 static bool qt_QmlQtModule_registered = false;
164 bool QDeclarativeEnginePrivate::qml_debugging_enabled = false;
166 void QDeclarativeEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
168 qmlRegisterType<QDeclarativeComponent>(uri,versionMajor,versionMinor,"Component");
169 qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
170 qmlRegisterType<QDeclarativeWorkerScript>(uri,versionMajor,versionMinor,"WorkerScript");
173 void QDeclarativeEnginePrivate::defineModule()
175 registerBaseTypes("QtQuick", 2, 0);
176 qmlRegisterType<QDeclarativeBinding>();
180 \qmlclass Qt QDeclarativeEnginePrivate
181 \ingroup qml-utility-elements
182 \brief The QML global Qt object provides useful enums and functions from Qt.
184 \keyword QmlGlobalQtObject
186 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
188 The \c Qt object is a global object with utility functions, properties and enums.
190 It is not instantiable; to use it, call the members of the global \c Qt object directly.
197 color: Qt.rgba(1, 0, 0, 1)
198 text: Qt.md5("hello, world")
205 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
206 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
210 The Qt object also contains helper functions for creating objects of specific
211 data types. This is primarily useful when setting the properties of an item
212 when the property has one of the following types:
215 \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()}
216 \o \c rect - use \l{Qt::rect()}{Qt.rect()}
217 \o \c point - use \l{Qt::point()}{Qt.point()}
218 \o \c size - use \l{Qt::size()}{Qt.size()}
219 \o \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
222 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
224 \section1 Date/Time Formatters
226 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
229 \o \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
230 \o \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
231 \o \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
234 The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
237 \section1 Dynamic Object Creation
238 The following functions on the global object allow you to dynamically create QML
239 items from files or strings. See \l{Dynamic Object Management in QML} for an overview
243 \o \l{Qt::createComponent()}{object Qt.createComponent(url)}
244 \o \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
250 \qmlproperty object Qt::application
253 The \c application object provides access to global application state
254 properties shared by many QML components.
260 \o \c application.active
262 This read-only property indicates whether the application is the top-most and focused
263 application, and the user is able to interact with the application. The property
264 is false when the application is in the background, the device keylock or screen
265 saver is active, the screen backlight is turned off, or the global system dialog
266 is being displayed on top of the application. It can be used for stopping and
267 pausing animations, timers and active processing of data in order to save device
268 battery power and free device memory and processor load when the application is not
272 \o \c application.layoutDirection
274 This read-only property can be used to query the default layout direction of the
275 application. On system start-up, the default layout direction depends on the
276 application's language. The property has a value of \c Qt.RightToLeft in locales
277 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
278 where the reading direction flows from left to right. You can bind to this
279 property to customize your application layouts to support both layout directions.
284 \o Qt.LeftToRight - Text and graphics elements should be positioned
286 \o Qt.RightToLeft - Text and graphics elements should be positioned
291 \o \c application.inputPanel
293 This read-only property allows access to application's QInputPanel object
294 and all its properties and slots. See the QInputPanel documentation for
298 The following example uses the \c application object to indicate
299 whether the application is currently active:
301 \snippet doc/src/snippets/declarative/application.qml document
307 \qmlmethod object Qt::include(string url, jsobject callback)
309 Includes another JavaScript file. This method can only be used from within JavaScript files,
310 and not regular QML files.
312 This imports all functions from \a url into the current script's namespace.
314 Qt.include() returns an object that describes the status of the operation. The object has
315 a single property, \c {status}, that is set to one of the following values:
318 \header \o Symbol \o Value \o Description
319 \row \o result.OK \o 0 \o The include completed successfully.
320 \row \o result.LOADING \o 1 \o Data is being loaded from the network.
321 \row \o result.NETWORK_ERROR \o 2 \o A network error occurred while fetching the url.
322 \row \o result.EXCEPTION \o 3 \o A JavaScript exception occurred while executing the included code.
323 An additional \c exception property will be set in this case.
326 The \c status property will be updated as the operation progresses.
328 If provided, \a callback is invoked when the operation completes. The callback is passed
329 the same object as is returned from the Qt.include() call.
331 // Qt.include() is implemented in qv8include.cpp
334 QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e)
335 : captureProperties(false), rootContext(0), isDebugging(false),
336 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
337 cleanup(0), erroredBindings(0), inProgressCreations(0),
338 workerScriptEngine(0), activeVME(0),
339 networkAccessManager(0), networkAccessManagerFactory(0),
340 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
341 incubatorCount(0), incubationController(0), sgContext(0), mutex(QMutex::Recursive)
343 if (!qt_QmlQtModule_registered) {
344 qt_QmlQtModule_registered = true;
345 QDeclarativeUtilModule::defineModule();
346 QDeclarativeEnginePrivate::defineModule();
347 QSGItemsModule::defineModule();
348 QSGParticlesModule::defineModule();
349 QDeclarativeValueTypeFactory::registerValueTypes();
353 QDeclarativeEnginePrivate::~QDeclarativeEnginePrivate()
355 Q_ASSERT(inProgressCreations == 0);
358 QDeclarativeCleanup *c = cleanup;
360 if (cleanup) cleanup->prev = &cleanup;
366 doDeleteInEngineThread();
368 if (incubationController) incubationController->d = 0;
369 incubationController = 0;
374 for(QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
376 for(QHash<const QMetaObject *, QDeclarativePropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
378 for(QHash<QPair<QDeclarativeType *, int>, QDeclarativePropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
380 for(QHash<QDeclarativeMetaType::ModuleApi, QDeclarativeMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
381 delete (*iter)->qobjectApi;
386 void QDeclarativePrivate::qdeclarativeelement_destructor(QObject *o)
388 QObjectPrivate *p = QObjectPrivate::get(o);
389 if (p->declarativeData) {
390 QDeclarativeData *d = static_cast<QDeclarativeData*>(p->declarativeData);
391 if (d->ownContext && d->context) {
392 d->context->destroy();
398 void QDeclarativeData::destroyed(QAbstractDeclarativeData *d, QObject *o)
400 static_cast<QDeclarativeData *>(d)->destroyed(o);
403 void QDeclarativeData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
405 static_cast<QDeclarativeData *>(d)->parentChanged(o, p);
408 void QDeclarativeData::objectNameChanged(QAbstractDeclarativeData *d, QObject *o)
410 static_cast<QDeclarativeData *>(d)->objectNameChanged(o);
413 void QDeclarativeData::signalEmitted(QAbstractDeclarativeData *, QObject *object, int index, void **)
415 QDeclarativeData *ddata = QDeclarativeData::get(object, false);
416 if (!ddata) return; // Probably being deleted
418 QDeclarativeNotifierEndpoint *ep = ddata->notify(index);
419 if (ep) QDeclarativeNotifier::emitNotify(ep);
422 void QDeclarativeEnginePrivate::init()
424 Q_Q(QDeclarativeEngine);
426 static bool firstTime = true;
428 // This is a nasty hack as QNetworkAccessManager will issue a
429 // BlockingQueuedConnection to the main thread if it is initialized for the
430 // first time on a non-main thread. This can cause a lockup if the main thread
431 // is blocking on the thread that initialize the network access manager.
432 QNetworkConfigurationManager man;
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::instance()->addEngine(q);
456 QV8ProfilerService::instance()->addEngine(q);
457 QDeclarativeDebugTrace::addEngine(q);
461 QDeclarativeWorkerScriptEngine *QDeclarativeEnginePrivate::getWorkerScriptEngine()
463 Q_Q(QDeclarativeEngine);
464 if (!workerScriptEngine)
465 workerScriptEngine = new QDeclarativeWorkerScriptEngine(q);
466 return workerScriptEngine;
470 \class QDeclarativeEngine
472 \brief The QDeclarativeEngine class provides an environment for instantiating QML components.
475 Each QML component is instantiated in a QDeclarativeContext.
476 QDeclarativeContext's are essential for passing data to QML
477 components. In QML, contexts are arranged hierarchically and this
478 hierarchy is managed by the QDeclarativeEngine.
480 Prior to creating any QML components, an application must have
481 created a QDeclarativeEngine to gain access to a QML context. The
482 following example shows how to create a simple Text item.
485 QDeclarativeEngine engine;
486 QDeclarativeComponent component(&engine);
487 component.setData("import QtQuick 1.0\nText { text: \"Hello world!\" }", QUrl());
488 QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(component.create());
490 //add item to view, etc
494 In this case, the Text item will be created in the engine's
495 \l {QDeclarativeEngine::rootContext()}{root context}.
497 \sa QDeclarativeComponent QDeclarativeContext
501 Create a new QDeclarativeEngine with the given \a parent.
503 QDeclarativeEngine::QDeclarativeEngine(QObject *parent)
504 : QJSEngine(*new QDeclarativeEnginePrivate(this), parent)
506 Q_D(QDeclarativeEngine);
511 Destroys the QDeclarativeEngine.
513 Any QDeclarativeContext's created on this engine will be
514 invalidated, but not destroyed (unless they are parented to the
515 QDeclarativeEngine object).
517 QDeclarativeEngine::~QDeclarativeEngine()
519 Q_D(QDeclarativeEngine);
520 if (d->isDebugging) {
521 QDeclarativeEngineDebugService::instance()->remEngine(this);
522 QV8DebugService::instance()->removeEngine(this);
523 QV8ProfilerService::instance()->removeEngine(this);
524 QDeclarativeDebugTrace::removeEngine(this);
527 // if we are the parent of any of the qobject module api instances,
528 // we need to remove them from our internal list, in order to prevent
529 // a segfault in engine private dtor.
530 QList<QDeclarativeMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
531 QObject *currQObjectApi = 0;
532 QDeclarativeMetaType::ModuleApiInstance *currInstance = 0;
533 foreach (const QDeclarativeMetaType::ModuleApi &key, keys) {
534 currInstance = d->moduleApiInstances.value(key);
535 currQObjectApi = currInstance->qobjectApi;
536 if (this->children().contains(currQObjectApi)) {
537 delete currQObjectApi;
539 d->moduleApiInstances.remove(key);
543 // ensure we clean up QObjects with JS ownership
547 /*! \fn void QDeclarativeEngine::quit()
548 This signal is emitted when the QML loaded by the engine would like to quit.
551 /*! \fn void QDeclarativeEngine::warnings(const QList<QDeclarativeError> &warnings)
552 This signal is emitted when \a warnings messages are generated by QML.
556 Clears the engine's internal component cache.
558 Normally the QDeclarativeEngine caches components loaded from qml
559 files. This method clears this cache and forces the component to be
562 void QDeclarativeEngine::clearComponentCache()
564 Q_D(QDeclarativeEngine);
565 d->typeLoader.clearCache();
569 Returns the engine's root context.
571 The root context is automatically created by the QDeclarativeEngine.
572 Data that should be available to all QML component instances
573 instantiated by the engine should be put in the root context.
575 Additional data that should only be available to a subset of
576 component instances should be added to sub-contexts parented to the
579 QDeclarativeContext *QDeclarativeEngine::rootContext() const
581 Q_D(const QDeclarativeEngine);
582 return d->rootContext;
586 Sets the \a factory to use for creating QNetworkAccessManager(s).
588 QNetworkAccessManager is used for all network access by QML. By
589 implementing a factory it is possible to create custom
590 QNetworkAccessManager with specialized caching, proxy and cookie
593 The factory must be set before executing the engine.
595 void QDeclarativeEngine::setNetworkAccessManagerFactory(QDeclarativeNetworkAccessManagerFactory *factory)
597 Q_D(QDeclarativeEngine);
598 QMutexLocker locker(&d->mutex);
599 d->networkAccessManagerFactory = factory;
603 Returns the current QDeclarativeNetworkAccessManagerFactory.
605 \sa setNetworkAccessManagerFactory()
607 QDeclarativeNetworkAccessManagerFactory *QDeclarativeEngine::networkAccessManagerFactory() const
609 Q_D(const QDeclarativeEngine);
610 return d->networkAccessManagerFactory;
613 void QDeclarativeEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
616 activeVME->finalizeCallbacks.append(qMakePair(QDeclarativeGuard<QObject>(obj), index));
618 void *args[] = { 0 };
619 QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args);
623 QNetworkAccessManager *QDeclarativeEnginePrivate::createNetworkAccessManager(QObject *parent) const
625 QMutexLocker locker(&mutex);
626 QNetworkAccessManager *nam;
627 if (networkAccessManagerFactory) {
628 nam = networkAccessManagerFactory->create(parent);
630 nam = new QNetworkAccessManager(parent);
636 QNetworkAccessManager *QDeclarativeEnginePrivate::getNetworkAccessManager() const
638 Q_Q(const QDeclarativeEngine);
639 if (!networkAccessManager)
640 networkAccessManager = createNetworkAccessManager(const_cast<QDeclarativeEngine*>(q));
641 return networkAccessManager;
645 Returns a common QNetworkAccessManager which can be used by any QML
646 element instantiated by this engine.
648 If a QDeclarativeNetworkAccessManagerFactory has been set and a
649 QNetworkAccessManager has not yet been created, the
650 QDeclarativeNetworkAccessManagerFactory will be used to create the
651 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
652 will have no proxy or cache set.
654 \sa setNetworkAccessManagerFactory()
656 QNetworkAccessManager *QDeclarativeEngine::networkAccessManager() const
658 Q_D(const QDeclarativeEngine);
659 return d->getNetworkAccessManager();
664 Sets the \a provider to use for images requested via the \e
665 image: url scheme, with host \a providerId. The QDeclarativeEngine
666 takes ownership of \a provider.
668 Image providers enable support for pixmap and threaded image
669 requests. See the QDeclarativeImageProvider documentation for details on
670 implementing and using image providers.
672 All required image providers should be added to the engine before any
673 QML sources files are loaded.
675 \sa removeImageProvider()
677 void QDeclarativeEngine::addImageProvider(const QString &providerId, QDeclarativeImageProvider *provider)
679 Q_D(QDeclarativeEngine);
680 QMutexLocker locker(&d->mutex);
681 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QDeclarativeImageProvider>(provider));
685 Returns the QDeclarativeImageProvider set for \a providerId.
687 Returns the provider if it was found; otherwise returns 0.
689 QDeclarativeImageProvider *QDeclarativeEngine::imageProvider(const QString &providerId) const
691 Q_D(const QDeclarativeEngine);
692 QMutexLocker locker(&d->mutex);
693 return d->imageProviders.value(providerId).data();
697 Removes the QDeclarativeImageProvider for \a providerId.
699 \sa addImageProvider()
701 void QDeclarativeEngine::removeImageProvider(const QString &providerId)
703 Q_D(QDeclarativeEngine);
704 QMutexLocker locker(&d->mutex);
705 d->imageProviders.take(providerId);
708 QDeclarativeImageProvider::ImageType QDeclarativeEnginePrivate::getImageProviderType(const QUrl &url)
710 QMutexLocker locker(&mutex);
711 QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
714 return provider->imageType();
715 return QDeclarativeImageProvider::Invalid;
718 QSGTexture *QDeclarativeEnginePrivate::getTextureFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
720 QMutexLocker locker(&mutex);
721 QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
724 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
725 return provider->requestTexture(imageId, size, req_size);
730 QImage QDeclarativeEnginePrivate::getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
732 QMutexLocker locker(&mutex);
734 QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
737 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
738 image = provider->requestImage(imageId, size, req_size);
743 QPixmap QDeclarativeEnginePrivate::getPixmapFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
745 QMutexLocker locker(&mutex);
747 QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
750 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
751 pixmap = provider->requestPixmap(imageId, size, req_size);
757 Return the base URL for this engine. The base URL is only used to
758 resolve components when a relative URL is passed to the
759 QDeclarativeComponent constructor.
761 If a base URL has not been explicitly set, this method returns the
762 application's current working directory.
766 QUrl QDeclarativeEngine::baseUrl() const
768 Q_D(const QDeclarativeEngine);
769 if (d->baseUrl.isEmpty()) {
770 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
777 Set the base URL for this engine to \a url.
781 void QDeclarativeEngine::setBaseUrl(const QUrl &url)
783 Q_D(QDeclarativeEngine);
788 Returns true if warning messages will be output to stderr in addition
789 to being emitted by the warnings() signal, otherwise false.
791 The default value is true.
793 bool QDeclarativeEngine::outputWarningsToStandardError() const
795 Q_D(const QDeclarativeEngine);
796 return d->outputWarningsToStdErr;
800 Set whether warning messages will be output to stderr to \a enabled.
802 If \a enabled is true, any warning messages generated by QML will be
803 output to stderr and emitted by the warnings() signal. If \a enabled
804 is false, on the warnings() signal will be emitted. This allows
805 applications to handle warning output themselves.
807 The default value is true.
809 void QDeclarativeEngine::setOutputWarningsToStandardError(bool enabled)
811 Q_D(QDeclarativeEngine);
812 d->outputWarningsToStdErr = enabled;
816 Attempt to free unused memory.
818 void QDeclarativeEngine::collectGarbage()
824 Returns the QDeclarativeContext for the \a object, or 0 if no
825 context has been set.
827 When the QDeclarativeEngine instantiates a QObject, the context is
830 QDeclarativeContext *QDeclarativeEngine::contextForObject(const QObject *object)
835 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
837 QDeclarativeData *data =
838 static_cast<QDeclarativeData *>(priv->declarativeData);
842 else if (data->outerContext)
843 return data->outerContext->asQDeclarativeContext();
849 Sets the QDeclarativeContext for the \a object to \a context.
850 If the \a object already has a context, a warning is
851 output, but the context is not changed.
853 When the QDeclarativeEngine instantiates a QObject, the context is
856 void QDeclarativeEngine::setContextForObject(QObject *object, QDeclarativeContext *context)
858 if (!object || !context)
861 QDeclarativeData *data = QDeclarativeData::get(object, true);
863 qWarning("QDeclarativeEngine::setContextForObject(): Object already has a QDeclarativeContext");
867 QDeclarativeContextData *contextData = QDeclarativeContextData::get(context);
868 contextData->addObject(object);
872 \enum QDeclarativeEngine::ObjectOwnership
874 Ownership controls whether or not QML automatically destroys the
875 QObject when the object is garbage collected by the JavaScript
876 engine. The two ownership options are:
878 \value CppOwnership The object is owned by C++ code, and will
879 never be deleted by QML. The JavaScript destroy() method cannot be
880 used on objects with CppOwnership. This option is similar to
881 QScriptEngine::QtOwnership.
883 \value JavaScriptOwnership The object is owned by JavaScript.
884 When the object is returned to QML as the return value of a method
885 call or property access, QML will delete the object if there are no
886 remaining JavaScript references to it and it has no
887 QObject::parent(). This option is similar to
888 QScriptEngine::ScriptOwnership.
890 Generally an application doesn't need to set an object's ownership
891 explicitly. QML uses a heuristic to set the default object
892 ownership. By default, an object that is created by QML has
893 JavaScriptOwnership. The exception to this are the root objects
894 created by calling QDeclarativeCompnent::create() or
895 QDeclarativeComponent::beginCreate() which have CppOwnership by
896 default. The ownership of these root-level objects is considered to
897 have been transferred to the C++ caller.
899 Objects not-created by QML have CppOwnership by default. The
900 exception to this is objects returned from a C++ method call. The
901 ownership of these objects is passed to JavaScript.
903 Calling setObjectOwnership() overrides the default ownership
904 heuristic used by QML.
908 Sets the \a ownership of \a object.
910 void QDeclarativeEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
915 QDeclarativeData *ddata = QDeclarativeData::get(object, true);
919 ddata->indestructible = (ownership == CppOwnership)?true:false;
920 ddata->explicitIndestructibleSet = true;
924 Returns the ownership of \a object.
926 QDeclarativeEngine::ObjectOwnership QDeclarativeEngine::objectOwnership(QObject *object)
931 QDeclarativeData *ddata = QDeclarativeData::get(object, false);
935 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
938 bool QDeclarativeEngine::event(QEvent *e)
940 Q_D(QDeclarativeEngine);
941 if (e->type() == QEvent::User)
942 d->doDeleteInEngineThread();
944 return QJSEngine::event(e);
947 void QDeclarativeEnginePrivate::doDeleteInEngineThread()
949 QFieldList<Deletable, &Deletable::next> list;
951 list.copyAndClear(toDeleteInEngineThread);
954 while (Deletable *d = list.takeFirst())
958 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
960 QDeclarativeData *data = QDeclarativeData::get(object);
962 if (data && data->deferredComponent) {
963 if (QDeclarativeDebugService::isDebuggingEnabled()) {
964 QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Creating);
965 QDeclarativeType *type = QDeclarativeMetaType::qmlType(object->metaObject());
966 QString typeName = type ? type->qmlTypeName() : QString::fromUtf8(object->metaObject()->className());
967 QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Creating, typeName);
968 if (data->outerContext)
969 QDeclarativeDebugTrace::rangeLocation(QDeclarativeDebugTrace::Creating, data->outerContext->url, data->lineNumber);
971 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(data->context->engine);
973 QDeclarativeComponentPrivate::ConstructionState state;
974 QDeclarativeComponentPrivate::beginDeferred(ep, object, &state);
976 data->deferredComponent->release();
977 data->deferredComponent = 0;
979 QDeclarativeComponentPrivate::complete(ep, &state);
980 QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Creating);
984 QDeclarativeContext *qmlContext(const QObject *obj)
986 return QDeclarativeEngine::contextForObject(obj);
989 QDeclarativeEngine *qmlEngine(const QObject *obj)
991 QDeclarativeData *data = QDeclarativeData::get(obj, false);
992 if (!data || !data->context)
994 return data->context->engine;
997 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
999 QDeclarativeData *data = QDeclarativeData::get(object);
1001 return 0; // Attached properties are only on objects created by QML
1003 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
1007 QDeclarativeAttachedPropertiesFunc pf = QDeclarativeMetaType::attachedPropertiesFuncById(id);
1011 rv = pf(const_cast<QObject *>(object));
1014 data->attachedProperties()->insert(id, rv);
1019 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
1020 const QMetaObject *attachedMetaObject, bool create)
1023 *idCache = QDeclarativeMetaType::attachedPropertiesFuncId(attachedMetaObject);
1025 if (*idCache == -1 || !object)
1028 return qmlAttachedPropertiesObjectById(*idCache, object, create);
1031 QDeclarativeDebuggingEnabler::QDeclarativeDebuggingEnabler()
1033 #ifndef QDECLARATIVE_NO_DEBUG_PROTOCOL
1034 if (!QDeclarativeEnginePrivate::qml_debugging_enabled) {
1035 qWarning("Qml debugging is enabled. Only use this in a safe environment!");
1037 QDeclarativeEnginePrivate::qml_debugging_enabled = true;
1042 class QDeclarativeDataExtended {
1044 QDeclarativeDataExtended();
1045 ~QDeclarativeDataExtended();
1047 QHash<int, QObject *> attachedProperties;
1048 QDeclarativeNotifier objectNameNotifier;
1051 QDeclarativeDataExtended::QDeclarativeDataExtended()
1055 QDeclarativeDataExtended::~QDeclarativeDataExtended()
1059 void QDeclarativeData::NotifyList::layout(QDeclarativeNotifierEndpoint *endpoint)
1062 layout(endpoint->next);
1064 int index = endpoint->sourceSignal;
1065 index = qMin(index, 0xFFFF - 1);
1067 endpoint->next = notifies[index];
1068 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1069 endpoint->prev = ¬ifies[index];
1070 notifies[index] = endpoint;
1073 void QDeclarativeData::NotifyList::layout()
1075 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1078 QDeclarativeNotifierEndpoint **old = notifies;
1079 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QDeclarativeNotifierEndpoint*);
1080 notifies = (QDeclarativeNotifierEndpoint**)realloc(notifies, reallocSize);
1081 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1082 sizeof(QDeclarativeNotifierEndpoint*);
1083 memset(notifies + notifiesSize, 0, memsetSize);
1085 if (notifies != old) {
1086 for (int ii = 0; ii < notifiesSize; ++ii)
1088 notifies[ii]->prev = ¬ifies[ii];
1091 notifiesSize = maximumTodoIndex + 1;
1096 maximumTodoIndex = 0;
1100 void QDeclarativeData::addNotify(int index, QDeclarativeNotifierEndpoint *endpoint)
1103 notifyList = (NotifyList *)malloc(sizeof(NotifyList));
1104 notifyList->connectionMask = 0;
1105 notifyList->maximumTodoIndex = 0;
1106 notifyList->notifiesSize = 0;
1107 notifyList->todo = 0;
1108 notifyList->notifies = 0;
1111 Q_ASSERT(!endpoint->isConnected());
1113 index = qMin(index, 0xFFFF - 1);
1114 notifyList->connectionMask |= (1 << (quint64(index) % 64));
1116 if (index < notifyList->notifiesSize) {
1118 endpoint->next = notifyList->notifies[index];
1119 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1120 endpoint->prev = ¬ifyList->notifies[index];
1121 notifyList->notifies[index] = endpoint;
1124 notifyList->maximumTodoIndex = qMax(int(notifyList->maximumTodoIndex), index);
1126 endpoint->next = notifyList->todo;
1127 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1128 endpoint->prev = ¬ifyList->todo;
1129 notifyList->todo = endpoint;
1133 QDeclarativeNotifier *QDeclarativeData::objectNameNotifier() const
1135 if (!extendedData) extendedData = new QDeclarativeDataExtended;
1136 return &extendedData->objectNameNotifier;
1139 QHash<int, QObject *> *QDeclarativeData::attachedProperties() const
1141 if (!extendedData) extendedData = new QDeclarativeDataExtended;
1142 return &extendedData->attachedProperties;
1145 void QDeclarativeData::destroyed(QObject *object)
1147 if (deferredComponent)
1148 deferredComponent->release();
1150 if (nextContextObject)
1151 nextContextObject->prevContextObject = prevContextObject;
1152 if (prevContextObject)
1153 *prevContextObject = nextContextObject;
1155 QDeclarativeAbstractBinding *binding = bindings;
1157 QDeclarativeAbstractBinding *next = binding->m_nextBinding;
1158 binding->m_prevBinding = 0;
1159 binding->m_nextBinding = 0;
1168 propertyCache->release();
1170 if (ownContext && context)
1174 QDeclarativeGuard<QObject> *guard = static_cast<QDeclarativeGuard<QObject> *>(guards);
1175 *guard = (QObject *)0;
1176 guard->objectDestroyed(object);
1180 while (notifyList->todo)
1181 notifyList->todo->disconnect();
1182 for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
1183 while (QDeclarativeNotifierEndpoint *ep = notifyList->notifies[ii])
1186 free(notifyList->notifies);
1191 delete extendedData;
1193 v8object.Clear(); // The WeakReference handler will clean the actual handle
1199 void QDeclarativeData::parentChanged(QObject *object, QObject *parent)
1205 void QDeclarativeData::objectNameChanged(QObject *)
1207 if (extendedData) objectNameNotifier()->notify();
1210 bool QDeclarativeData::hasBindingBit(int bit) const
1212 if (bindingBitsSize > bit)
1213 return bindingBits[bit / 32] & (1 << (bit % 32));
1218 void QDeclarativeData::clearBindingBit(int bit)
1220 if (bindingBitsSize > bit)
1221 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1224 void QDeclarativeData::setBindingBit(QObject *obj, int bit)
1226 if (bindingBitsSize <= bit) {
1227 int props = obj->metaObject()->propertyCount();
1228 Q_ASSERT(bit < props);
1230 int arraySize = (props + 31) / 32;
1231 int oldArraySize = bindingBitsSize / 32;
1233 bindingBits = (quint32 *)realloc(bindingBits,
1234 arraySize * sizeof(quint32));
1236 memset(bindingBits + oldArraySize,
1238 sizeof(quint32) * (arraySize - oldArraySize));
1240 bindingBitsSize = arraySize * 32;
1243 bindingBits[bit / 32] |= (1 << (bit % 32));
1246 QString QDeclarativeEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
1248 if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
1249 if (url.authority().isEmpty())
1250 return QLatin1Char(':') + url.path();
1253 return url.toLocalFile();
1257 static QString toLocalFile(const QString &url)
1259 if (!url.startsWith(QLatin1String("file://"), Qt::CaseInsensitive))
1262 QString file = url.mid(7);
1264 //XXX TODO: handle windows hostnames: "//servername/path/to/file.txt"
1266 // magic for drives on windows
1267 if (file.length() > 2 && file.at(0) == QLatin1Char('/') && file.at(2) == QLatin1Char(':'))
1273 QString QDeclarativeEnginePrivate::urlToLocalFileOrQrc(const QString& url)
1275 if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) {
1276 if (url.length() > 4)
1277 return QLatin1Char(':') + url.mid(4);
1281 return toLocalFile(url);
1284 void QDeclarativeEnginePrivate::sendQuit()
1286 Q_Q(QDeclarativeEngine);
1288 if (q->receivers(SIGNAL(quit())) == 0) {
1289 qWarning("Signal QDeclarativeEngine::quit() emitted, but no receivers connected to handle it.");
1293 static void dumpwarning(const QDeclarativeError &error)
1295 qWarning().nospace() << qPrintable(error.toString());
1298 static void dumpwarning(const QList<QDeclarativeError> &errors)
1300 for (int ii = 0; ii < errors.count(); ++ii)
1301 dumpwarning(errors.at(ii));
1304 void QDeclarativeEnginePrivate::warning(const QDeclarativeError &error)
1306 Q_Q(QDeclarativeEngine);
1307 q->warnings(QList<QDeclarativeError>() << error);
1308 if (outputWarningsToStdErr)
1312 void QDeclarativeEnginePrivate::warning(const QList<QDeclarativeError> &errors)
1314 Q_Q(QDeclarativeEngine);
1315 q->warnings(errors);
1316 if (outputWarningsToStdErr)
1317 dumpwarning(errors);
1320 void QDeclarativeEnginePrivate::warning(QDeclarativeEngine *engine, const QDeclarativeError &error)
1323 QDeclarativeEnginePrivate::get(engine)->warning(error);
1328 void QDeclarativeEnginePrivate::warning(QDeclarativeEngine *engine, const QList<QDeclarativeError> &error)
1331 QDeclarativeEnginePrivate::get(engine)->warning(error);
1336 void QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate *engine, const QDeclarativeError &error)
1339 engine->warning(error);
1344 void QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate *engine, const QList<QDeclarativeError> &error)
1347 engine->warning(error);
1353 This function should be called prior to evaluation of any js expression,
1354 so that scarce resources are not freed prematurely (eg, if there is a
1355 nested javascript expression).
1357 void QDeclarativeEnginePrivate::referenceScarceResources()
1359 scarceResourcesRefCount += 1;
1363 This function should be called after evaluation of the js expression is
1364 complete, and so the scarce resources may be freed safely.
1366 void QDeclarativeEnginePrivate::dereferenceScarceResources()
1368 Q_ASSERT(scarceResourcesRefCount > 0);
1369 scarceResourcesRefCount -= 1;
1371 // if the refcount is zero, then evaluation of the "top level"
1372 // expression must have completed. We can safely release the
1373 // scarce resources.
1374 if (scarceResourcesRefCount == 0) {
1375 // iterate through the list and release them all.
1376 // note that the actual SRD is owned by the JS engine,
1377 // so we cannot delete the SRD; but we can free the
1378 // memory used by the variant in the SRD.
1379 while (ScarceResourceData *sr = scarceResources.first()) {
1380 sr->data = QVariant();
1381 scarceResources.remove(sr);
1387 Adds \a path as a directory where the engine searches for
1388 installed modules in a URL-based directory structure.
1389 The \a path may be a local filesystem directory or a URL.
1391 The newly added \a path will be first in the importPathList().
1393 \sa setImportPathList(), {QML Modules}
1395 void QDeclarativeEngine::addImportPath(const QString& path)
1397 Q_D(QDeclarativeEngine);
1398 d->importDatabase.addImportPath(path);
1402 Returns the list of directories where the engine searches for
1403 installed modules in a URL-based directory structure.
1405 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1406 imports \c com.mycompany.Feature will cause the QDeclarativeEngine to look
1407 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1408 provided by that module. A \c qmldir file is required for defining the
1409 type version mapping and possibly declarative extensions plugins.
1411 By default, the list contains the directory of the application executable,
1412 paths specified in the \c QML_IMPORT_PATH environment variable,
1413 and the builtin \c ImportsPath from QLibraryInfo.
1415 \sa addImportPath() setImportPathList()
1417 QStringList QDeclarativeEngine::importPathList() const
1419 Q_D(const QDeclarativeEngine);
1420 return d->importDatabase.importPathList();
1424 Sets \a paths as the list of directories where the engine searches for
1425 installed modules in a URL-based directory structure.
1427 By default, the list contains the directory of the application executable,
1428 paths specified in the \c QML_IMPORT_PATH environment variable,
1429 and the builtin \c ImportsPath from QLibraryInfo.
1431 \sa importPathList() addImportPath()
1433 void QDeclarativeEngine::setImportPathList(const QStringList &paths)
1435 Q_D(QDeclarativeEngine);
1436 d->importDatabase.setImportPathList(paths);
1441 Adds \a path as a directory where the engine searches for
1442 native plugins for imported modules (referenced in the \c qmldir file).
1444 By default, the list contains only \c ., i.e. the engine searches
1445 in the directory of the \c qmldir file itself.
1447 The newly added \a path will be first in the pluginPathList().
1449 \sa setPluginPathList()
1451 void QDeclarativeEngine::addPluginPath(const QString& path)
1453 Q_D(QDeclarativeEngine);
1454 d->importDatabase.addPluginPath(path);
1459 Returns the list of directories where the engine searches for
1460 native plugins for imported modules (referenced in the \c qmldir file).
1462 By default, the list contains only \c ., i.e. the engine searches
1463 in the directory of the \c qmldir file itself.
1465 \sa addPluginPath() setPluginPathList()
1467 QStringList QDeclarativeEngine::pluginPathList() const
1469 Q_D(const QDeclarativeEngine);
1470 return d->importDatabase.pluginPathList();
1474 Sets the list of directories where the engine searches for
1475 native plugins for imported modules (referenced in the \c qmldir file)
1478 By default, the list contains only \c ., i.e. the engine searches
1479 in the directory of the \c qmldir file itself.
1481 \sa pluginPathList() addPluginPath()
1483 void QDeclarativeEngine::setPluginPathList(const QStringList &paths)
1485 Q_D(QDeclarativeEngine);
1486 d->importDatabase.setPluginPathList(paths);
1490 Imports the plugin named \a filePath with the \a uri provided.
1491 Returns true if the plugin was successfully imported; otherwise returns false.
1493 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1495 The plugin has to be a Qt plugin which implements the QDeclarativeExtensionPlugin interface.
1497 bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &uri, QList<QDeclarativeError> *errors)
1499 Q_D(QDeclarativeEngine);
1500 return d->importDatabase.importPlugin(filePath, uri, errors);
1504 Imports the plugin named \a filePath with the \a uri provided.
1505 Returns true if the plugin was successfully imported; otherwise returns false.
1507 On failure and if non-null, *\a errorString will be set to a message describing the failure.
1509 The plugin has to be a Qt plugin which implements the QDeclarativeExtensionPlugin interface.
1511 bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1513 Q_D(QDeclarativeEngine);
1514 QList<QDeclarativeError> errors;
1515 bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1516 if (!errors.isEmpty()) {
1518 for (int i = 0; i < errors.size(); ++i) {
1519 builtError = QString(QLatin1String("%1\n %2"))
1521 .arg(errors.at(i).toString());
1523 *errorString = builtError;
1529 \property QDeclarativeEngine::offlineStoragePath
1530 \brief the directory for storing offline user data
1532 Returns the directory where SQL and other offline
1535 QDeclarativeWebView and the SQL databases created with openDatabase()
1538 The default is QML/OfflineStorage in the platform-standard
1539 user application data directory.
1541 Note that the path may not currently exist on the filesystem, so
1542 callers wanting to \e create new files at this location should create
1543 it first - see QDir::mkpath().
1545 void QDeclarativeEngine::setOfflineStoragePath(const QString& dir)
1547 Q_D(QDeclarativeEngine);
1548 qt_qmlsqldatabase_setOfflineStoragePath(d->v8engine(), dir);
1551 QString QDeclarativeEngine::offlineStoragePath() const
1553 Q_D(const QDeclarativeEngine);
1554 return qt_qmlsqldatabase_getOfflineStoragePath(d->v8engine());
1557 static void voidptr_destructor(void *v)
1559 void **ptr = (void **)v;
1563 static void *voidptr_constructor(const void *v)
1568 return new void*(*(void **)v);
1572 QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(const QMetaObject *mo)
1574 Q_Q(QDeclarativeEngine);
1576 if (!mo->superClass()) {
1577 QDeclarativePropertyCache *rv = new QDeclarativePropertyCache(q, mo);
1578 propertyCache.insert(mo, rv);
1581 QDeclarativePropertyCache *super = cache(mo->superClass());
1582 QDeclarativePropertyCache *rv = super->copy(mo->propertyCount() + mo->methodCount() -
1583 mo->superClass()->propertyCount() -
1584 mo->superClass()->methodCount());
1586 propertyCache.insert(mo, rv);
1591 QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(QDeclarativeType *type, int minorVersion,
1592 QDeclarativeError &error)
1594 QList<QDeclarativeType *> types;
1596 int maxMinorVersion = 0;
1598 const QMetaObject *metaObject = type->metaObject();
1600 while (metaObject) {
1601 QDeclarativeType *t = QDeclarativeMetaType::qmlType(metaObject, type->module(),
1602 type->majorVersion(), minorVersion);
1604 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1610 metaObject = metaObject->superClass();
1613 if (QDeclarativePropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1615 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1619 QDeclarativePropertyCache *raw = cache(type->metaObject());
1621 bool hasCopied = false;
1623 for (int ii = 0; ii < types.count(); ++ii) {
1624 QDeclarativeType *currentType = types.at(ii);
1628 int rev = currentType->metaObjectRevision();
1629 int moIndex = types.count() - 1 - ii;
1631 if (raw->allowedRevisionCache[moIndex] != rev) {
1636 raw->allowedRevisionCache[moIndex] = rev;
1640 // Test revision compatibility - the basic rule is:
1641 // * Anything that is excluded, cannot overload something that is not excluded *
1643 // Signals override:
1644 // * other signals and methods of the same name.
1645 // * properties named on<Signal Name>
1646 // * automatic <property name>Changed notify signals
1648 // Methods override:
1649 // * other methods of the same name
1651 // Properties override:
1652 // * other elements of the same name
1654 bool overloadError = false;
1655 QString overloadName;
1658 for (QDeclarativePropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1659 !overloadError && iter != raw->stringCache.end();
1662 QDeclarativePropertyCache::Data *d = *iter;
1663 if (raw->isAllowedInRevision(d))
1664 continue; // Not excluded - no problems
1666 // check that a regular "name" overload isn't happening
1667 QDeclarativePropertyCache::Data *current = d;
1668 while (!overloadError && current) {
1669 current = d->overrideData(current);
1670 if (current && raw->isAllowedInRevision(current))
1671 overloadError = true;
1676 if (overloadError) {
1677 if (hasCopied) raw->release();
1679 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."));
1683 if (!hasCopied) raw->addref();
1684 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1686 if (minorVersion != maxMinorVersion) {
1688 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1694 QDeclarativeMetaType::ModuleApiInstance *
1695 QDeclarativeEnginePrivate::moduleApiInstance(const QDeclarativeMetaType::ModuleApi &module)
1697 Locker locker(this);
1699 QDeclarativeMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
1701 a = new QDeclarativeMetaType::ModuleApiInstance;
1702 a->scriptCallback = module.script;
1703 a->qobjectCallback = module.qobject;
1704 moduleApiInstances.insert(module, a);
1710 bool QDeclarativeEnginePrivate::isQObject(int t)
1712 Locker locker(this);
1713 return m_compositeTypes.contains(t) || QDeclarativeMetaType::isQObject(t);
1716 QObject *QDeclarativeEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1718 Locker locker(this);
1719 int t = v.userType();
1720 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1722 return *(QObject **)(v.constData());
1724 return QDeclarativeMetaType::toQObject(v, ok);
1728 QDeclarativeMetaType::TypeCategory QDeclarativeEnginePrivate::typeCategory(int t) const
1730 Locker locker(this);
1731 if (m_compositeTypes.contains(t))
1732 return QDeclarativeMetaType::Object;
1733 else if (m_qmlLists.contains(t))
1734 return QDeclarativeMetaType::List;
1736 return QDeclarativeMetaType::typeCategory(t);
1739 bool QDeclarativeEnginePrivate::isList(int t) const
1741 Locker locker(this);
1742 return m_qmlLists.contains(t) || QDeclarativeMetaType::isList(t);
1745 int QDeclarativeEnginePrivate::listType(int t) const
1747 Locker locker(this);
1748 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1749 if (iter != m_qmlLists.end())
1752 return QDeclarativeMetaType::listType(t);
1755 const QMetaObject *QDeclarativeEnginePrivate::rawMetaObjectForType(int t) const
1757 Locker locker(this);
1758 QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1759 if (iter != m_compositeTypes.end()) {
1760 return (*iter)->root;
1762 QDeclarativeType *type = QDeclarativeMetaType::qmlType(t);
1763 return type?type->baseMetaObject():0;
1767 const QMetaObject *QDeclarativeEnginePrivate::metaObjectForType(int t) const
1769 Locker locker(this);
1770 QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1771 if (iter != m_compositeTypes.end()) {
1772 return (*iter)->root;
1774 QDeclarativeType *type = QDeclarativeMetaType::qmlType(t);
1775 return type?type->metaObject():0;
1779 void QDeclarativeEnginePrivate::registerCompositeType(QDeclarativeCompiledData *data)
1781 QByteArray name = data->root->className();
1783 QByteArray ptr = name + '*';
1784 QByteArray lst = "QDeclarativeListProperty<" + name + '>';
1786 int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
1787 voidptr_constructor);
1788 int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
1789 voidptr_constructor);
1793 Locker locker(this);
1794 m_qmlLists.insert(lst_type, ptr_type);
1795 m_compositeTypes.insert(ptr_type, data);
1798 bool QDeclarative_isFileCaseCorrect(const QString &fileName)
1800 #if defined(Q_OS_MAC) || defined(Q_OS_WIN32)
1801 QFileInfo info(fileName);
1803 QString absolute = info.absoluteFilePath();
1805 #if defined(Q_OS_MAC)
1806 QString canonical = info.canonicalFilePath();
1807 #elif defined(Q_OS_WIN32)
1808 wchar_t buffer[1024];
1810 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1811 if (rv == 0 || rv >= 1024) return true;
1812 rv = ::GetLongPathName(buffer, buffer, 1024);
1813 if (rv == 0 || rv >= 1024) return true;
1815 QString canonical((QChar *)buffer);
1818 int absoluteLength = absolute.length();
1819 int canonicalLength = canonical.length();
1821 int length = qMin(absoluteLength, canonicalLength);
1822 for (int ii = 0; ii < length; ++ii) {
1823 const QChar &a = absolute.at(absoluteLength - 1 - ii);
1824 const QChar &c = canonical.at(canonicalLength - 1 - ii);
1826 if (a.toLower() != c.toLower())
1838 \fn QDeclarativeEngine *qmlEngine(const QObject *object)
1839 \relates QDeclarativeEngine
1841 Returns the QDeclarativeEngine associated with \a object, if any. This is equivalent to
1842 QDeclarativeEngine::contextForObject(object)->engine(), but more efficient.
1846 \fn QDeclarativeContext *qmlContext(const QObject *object)
1847 \relates QDeclarativeEngine
1849 Returns the QDeclarativeContext associated with \a object, if any. This is equivalent to
1850 QDeclarativeEngine::contextForObject(object).