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 "private/qdeclarativeengine_p.h"
43 #include "qdeclarativeengine.h"
45 #include "private/qdeclarativecontext_p.h"
46 #include "private/qdeclarativecompiler_p.h"
47 #include "qdeclarative.h"
48 #include "qdeclarativecontext.h"
49 #include "qdeclarativeexpression.h"
50 #include "qdeclarativecomponent.h"
51 #include "private/qdeclarativebinding_p_p.h"
52 #include "private/qdeclarativevme_p.h"
53 #include "private/qdeclarativeenginedebug_p.h"
54 #include "private/qdeclarativestringconverters_p.h"
55 #include "private/qdeclarativexmlhttprequest_p.h"
56 #include "private/qdeclarativesqldatabase_p.h"
57 #include "qdeclarativescriptstring.h"
58 #include "private/qdeclarativeglobal_p.h"
59 #include "private/qdeclarativeworkerscript_p.h"
60 #include "private/qdeclarativecomponent_p.h"
61 #include "qdeclarativenetworkaccessmanagerfactory.h"
62 #include "qdeclarativeimageprovider.h"
63 #include "private/qdeclarativedirparser_p.h"
64 #include "qdeclarativeextensioninterface.h"
65 #include "private/qdeclarativelist_p.h"
66 #include "private/qdeclarativetypenamecache_p.h"
67 #include "private/qdeclarativenotifier_p.h"
68 #include "private/qdeclarativedebugtrace_p.h"
69 #include "private/qdeclarativeapplication_p.h"
70 #include "private/qjsdebugservice_p.h"
72 #include <QtCore/qmetaobject.h>
73 #include <QNetworkReply>
74 #include <QNetworkRequest>
75 #include <QNetworkAccessManager>
76 #include <QDesktopServices>
81 #include <QMetaObject>
84 #include <QPluginLoader>
85 #include <QtGui/qfontdatabase.h>
86 #include <QtCore/qlibraryinfo.h>
87 #include <QtCore/qthreadstorage.h>
88 #include <QtCore/qthread.h>
89 #include <QtCore/qcoreapplication.h>
90 #include <QtCore/qdir.h>
91 #include <QtCore/qmutex.h>
92 #include <QtGui/qcolor.h>
93 #include <QtGui/qvector3d.h>
94 #include <QtGui/qsound.h>
95 #include <QtCore/qcryptographichash.h>
97 #include <private/qobject_p.h>
99 #include <private/qdeclarativeitemsmodule_p.h>
100 #include <private/qdeclarativeutilmodule_p.h>
101 #include <private/qsgitemsmodule_p.h>
102 #include <private/qsgparticlesmodule_p.h>
103 #include <qsgtexture.h>
105 #ifdef Q_OS_WIN // for %APPDATA%
106 #include <qt_windows.h>
107 #include <qlibrary.h>
110 #define CSIDL_APPDATA 0x001a // <username>\Application Data
113 Q_DECLARE_METATYPE(QDeclarativeProperty)
118 \qmlclass QtObject QObject
119 \ingroup qml-utility-elements
121 \brief The QtObject element is the most basic element in QML.
123 The QtObject element is a non-visual element which contains only the
126 It can be useful to create a QtObject if you need an extremely
127 lightweight element to enclose a set of custom properties:
129 \snippet doc/src/snippets/declarative/qtobject.qml 0
131 It can also be useful for C++ integration, as it is just a plain
132 QObject. See the QObject documentation for further details.
135 \qmlproperty string QML:QtObject::objectName
136 This property holds the QObject::objectName for this specific object instance.
138 This allows a C++ application to locate an item within a QML component
139 using the QObject::findChild() method. For example, the following C++
140 application locates the child \l Rectangle item and dynamically changes its
149 width: 200; height: 200
162 QDeclarativeView view;
163 view.setSource(QUrl::fromLocalFile("MyRect.qml"));
166 QDeclarativeItem *item = view.rootObject()->findChild<QDeclarativeItem*>("myRect");
168 item->setProperty("color", QColor(Qt::yellow));
172 struct StaticQtMetaObject : public QObject
174 static const QMetaObject *get()
175 { return &static_cast<StaticQtMetaObject*> (0)->staticQtMetaObject; }
178 static bool qt_QmlQtModule_registered = false;
179 bool QDeclarativeEnginePrivate::qml_debugging_enabled = false;
181 void QDeclarativeEnginePrivate::defineModule()
183 qmlRegisterType<QDeclarativeComponent>("QtQuick",1,0,"Component");
184 qmlRegisterType<QObject>("QtQuick",1,0,"QtObject");
185 qmlRegisterType<QDeclarativeWorkerScript>("QtQuick",1,0,"WorkerScript");
187 #ifndef QT_NO_IMPORT_QT47_QML
188 qmlRegisterType<QDeclarativeComponent>("Qt",4,7,"Component");
189 qmlRegisterType<QObject>("Qt",4,7,"QtObject");
190 qmlRegisterType<QDeclarativeWorkerScript>("Qt",4,7,"WorkerScript");
193 qmlRegisterType<QDeclarativeBinding>();
197 \qmlclass QML:Qt QDeclarativeEnginePrivate
198 \ingroup qml-utility-elements
199 \brief The QML global Qt object provides useful enums and functions from Qt.
201 \keyword QmlGlobalQtObject
203 \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files.
205 The \c Qt object is a global object with utility functions, properties and enums.
207 It is not instantiable; to use it, call the members of the global \c Qt object directly.
214 color: Qt.rgba(1, 0, 0, 1)
215 text: Qt.md5("hello, world")
222 The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access
223 the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton.
227 The Qt object also contains helper functions for creating objects of specific
228 data types. This is primarily useful when setting the properties of an item
229 when the property has one of the following types:
232 \o \c color - use \l{QML:Qt::rgba()}{Qt.rgba()}, \l{QML:Qt::hsla()}{Qt.hsla()}, \l{QML:Qt::darker()}{Qt.darker()}, \l{QML:Qt::lighter()}{Qt.lighter()} or \l{QML:Qt::tint()}{Qt.tint()}
233 \o \c rect - use \l{QML:Qt::rect()}{Qt.rect()}
234 \o \c point - use \l{QML:Qt::point()}{Qt.point()}
235 \o \c size - use \l{QML:Qt::size()}{Qt.size()}
236 \o \c vector3d - use \l{QML:Qt::vector3d()}{Qt.vector3d()}
239 There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
241 \section1 Date/Time Formatters
243 The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
246 \o \l{QML:Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
247 \o \l{QML:Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
248 \o \l{QML:Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
251 The format specification is described at \l{QML:Qt::formatDateTime}{Qt.formatDateTime}.
254 \section1 Dynamic Object Creation
255 The following functions on the global object allow you to dynamically create QML
256 items from files or strings. See \l{Dynamic Object Management in QML} for an overview
260 \o \l{QML:Qt::createComponent()}{object Qt.createComponent(url)}
261 \o \l{QML:Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, string filepath)}
267 \qmlproperty object QML:Qt::application
270 The \c application object provides access to global application state
271 properties shared by many QML components.
277 \o \c application.active
279 This read-only property indicates whether the application is the top-most and focused
280 application, and the user is able to interact with the application. The property
281 is false when the application is in the background, the device keylock or screen
282 saver is active, the screen backlight is turned off, or the global system dialog
283 is being displayed on top of the application. It can be used for stopping and
284 pausing animations, timers and active processing of data in order to save device
285 battery power and free device memory and processor load when the application is not
289 \o \c application.layoutDirection
291 This read-only property can be used to query the default layout direction of the
292 application. On system start-up, the default layout direction depends on the
293 application's language. The property has a value of \c Qt.RightToLeft in locales
294 where text and graphic elements are read from right to left, and \c Qt.LeftToRight
295 where the reading direction flows from left to right. You can bind to this
296 property to customize your application layouts to support both layout directions.
301 \o Qt.LeftToRight - Text and graphics elements should be positioned
303 \o Qt.RightToLeft - Text and graphics elements should be positioned
308 The following example uses the \c application object to indicate
309 whether the application is currently active:
311 \snippet doc/src/snippets/declarative/application.qml document
317 \qmlmethod object Qt::include(string url, jsobject callback)
319 Includes another JavaScript file. This method can only be used from within JavaScript files,
320 and not regular QML files.
322 This imports all functions from \a url into the current script's namespace.
324 Qt.include() returns an object that describes the status of the operation. The object has
325 a single property, \c {status}, that is set to one of the following values:
328 \header \o Symbol \o Value \o Description
329 \row \o result.OK \o 0 \o The include completed successfully.
330 \row \o result.LOADING \o 1 \o Data is being loaded from the network.
331 \row \o result.NETWORK_ERROR \o 2 \o A network error occurred while fetching the url.
332 \row \o result.EXCEPTION \o 3 \o A JavaScript exception occurred while executing the included code.
333 An additional \c exception property will be set in this case.
336 The \c status property will be updated as the operation progresses.
338 If provided, \a callback is invoked when the operation completes. The callback is passed
339 the same object as is returned from the Qt.include() call.
341 // Qt.include() is implemented in qv8include.cpp
344 QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e)
345 : captureProperties(false), rootContext(0), isDebugging(false),
346 outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
347 cleanup(0), erroredBindings(0), inProgressCreations(0),
348 workerScriptEngine(0), componentAttached(0), inBeginCreate(false),
349 networkAccessManager(0), networkAccessManagerFactory(0),
350 scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
353 if (!qt_QmlQtModule_registered) {
354 qt_QmlQtModule_registered = true;
355 QDeclarativeItemModule::defineModule();
356 QDeclarativeUtilModule::defineModule();
357 QDeclarativeEnginePrivate::defineModule();
358 QSGItemsModule::defineModule();
359 QSGParticlesModule::defineModule();
360 QDeclarativeValueTypeFactory::registerValueTypes();
364 QDeclarativeEnginePrivate::~QDeclarativeEnginePrivate()
366 Q_ASSERT(inProgressCreations == 0);
367 Q_ASSERT(bindValues.isEmpty());
368 Q_ASSERT(parserStatus.isEmpty());
371 QDeclarativeCleanup *c = cleanup;
373 if (cleanup) cleanup->prev = &cleanup;
382 for(QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
384 for(QHash<const QMetaObject *, QDeclarativePropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
386 for(QHash<QPair<QDeclarativeType *, int>, QDeclarativePropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
388 for(QHash<QDeclarativeMetaType::ModuleApi, QDeclarativeMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
389 delete (*iter)->qobjectApi;
394 void QDeclarativeEnginePrivate::clear(SimpleList<QDeclarativeAbstractBinding> &bvs)
399 void QDeclarativeEnginePrivate::clear(SimpleList<QDeclarativeParserStatus> &pss)
401 for (int ii = 0; ii < pss.count; ++ii) {
402 QDeclarativeParserStatus *ps = pss.at(ii);
409 void QDeclarativePrivate::qdeclarativeelement_destructor(QObject *o)
411 QObjectPrivate *p = QObjectPrivate::get(o);
412 if (p->declarativeData) {
413 QDeclarativeData *d = static_cast<QDeclarativeData*>(p->declarativeData);
414 if (d->ownContext && d->context) {
415 d->context->destroy();
421 void QDeclarativeData::destroyed(QAbstractDeclarativeData *d, QObject *o)
423 static_cast<QDeclarativeData *>(d)->destroyed(o);
426 void QDeclarativeData::parentChanged(QAbstractDeclarativeData *d, QObject *o, QObject *p)
428 static_cast<QDeclarativeData *>(d)->parentChanged(o, p);
431 void QDeclarativeData::objectNameChanged(QAbstractDeclarativeData *d, QObject *o)
433 static_cast<QDeclarativeData *>(d)->objectNameChanged(o);
436 void QDeclarativeEnginePrivate::init()
438 Q_Q(QDeclarativeEngine);
439 qRegisterMetaType<QVariant>("QVariant");
440 qRegisterMetaType<QDeclarativeScriptString>("QDeclarativeScriptString");
441 qRegisterMetaType<QScriptValue>("QScriptValue");
442 qRegisterMetaType<QDeclarativeComponent::Status>("QDeclarativeComponent::Status");
444 QDeclarativeData::init();
449 rootContext = new QDeclarativeContext(q,true);
451 if (QCoreApplication::instance()->thread() == q->thread() &&
452 QDeclarativeEngineDebugServer::isDebuggingEnabled()) {
454 QDeclarativeEngineDebugServer::instance()->addEngine(q);
455 QJSDebugService::instance()->addEngine(q);
459 QDeclarativeWorkerScriptEngine *QDeclarativeEnginePrivate::getWorkerScriptEngine()
461 Q_Q(QDeclarativeEngine);
462 if (!workerScriptEngine)
463 workerScriptEngine = new QDeclarativeWorkerScriptEngine(q);
464 return workerScriptEngine;
468 \class QDeclarativeEngine
470 \brief The QDeclarativeEngine class provides an environment for instantiating QML components.
473 Each QML component is instantiated in a QDeclarativeContext.
474 QDeclarativeContext's are essential for passing data to QML
475 components. In QML, contexts are arranged hierarchically and this
476 hierarchy is managed by the QDeclarativeEngine.
478 Prior to creating any QML components, an application must have
479 created a QDeclarativeEngine to gain access to a QML context. The
480 following example shows how to create a simple Text item.
483 QDeclarativeEngine engine;
484 QDeclarativeComponent component(&engine);
485 component.setData("import QtQuick 1.0\nText { text: \"Hello world!\" }", QUrl());
486 QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(component.create());
488 //add item to view, etc
492 In this case, the Text item will be created in the engine's
493 \l {QDeclarativeEngine::rootContext()}{root context}.
495 \sa QDeclarativeComponent QDeclarativeContext
499 Create a new QDeclarativeEngine with the given \a parent.
501 QDeclarativeEngine::QDeclarativeEngine(QObject *parent)
502 : QObject(*new QDeclarativeEnginePrivate(this), parent)
504 Q_D(QDeclarativeEngine);
509 Destroys the QDeclarativeEngine.
511 Any QDeclarativeContext's created on this engine will be
512 invalidated, but not destroyed (unless they are parented to the
513 QDeclarativeEngine object).
515 QDeclarativeEngine::~QDeclarativeEngine()
517 Q_D(QDeclarativeEngine);
519 QDeclarativeEngineDebugServer::instance()->remEngine(this);
521 // if we are the parent of any of the qobject module api instances,
522 // we need to remove them from our internal list, in order to prevent
523 // a segfault in engine private dtor.
524 QList<QDeclarativeMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
525 QObject *currQObjectApi = 0;
526 QDeclarativeMetaType::ModuleApiInstance *currInstance = 0;
527 foreach (const QDeclarativeMetaType::ModuleApi &key, keys) {
528 currInstance = d->moduleApiInstances.value(key);
529 currQObjectApi = currInstance->qobjectApi;
530 if (this->children().contains(currQObjectApi)) {
531 delete currQObjectApi;
533 d->moduleApiInstances.remove(key);
538 /*! \fn void QDeclarativeEngine::quit()
539 This signal is emitted when the QML loaded by the engine would like to quit.
542 /*! \fn void QDeclarativeEngine::warnings(const QList<QDeclarativeError> &warnings)
543 This signal is emitted when \a warnings messages are generated by QML.
547 Clears the engine's internal component cache.
549 Normally the QDeclarativeEngine caches components loaded from qml
550 files. This method clears this cache and forces the component to be
553 void QDeclarativeEngine::clearComponentCache()
555 Q_D(QDeclarativeEngine);
556 d->typeLoader.clearCache();
560 Returns the engine's root context.
562 The root context is automatically created by the QDeclarativeEngine.
563 Data that should be available to all QML component instances
564 instantiated by the engine should be put in the root context.
566 Additional data that should only be available to a subset of
567 component instances should be added to sub-contexts parented to the
570 QDeclarativeContext *QDeclarativeEngine::rootContext() const
572 Q_D(const QDeclarativeEngine);
573 return d->rootContext;
577 Sets the \a factory to use for creating QNetworkAccessManager(s).
579 QNetworkAccessManager is used for all network access by QML. By
580 implementing a factory it is possible to create custom
581 QNetworkAccessManager with specialized caching, proxy and cookie
584 The factory must be set before executing the engine.
586 void QDeclarativeEngine::setNetworkAccessManagerFactory(QDeclarativeNetworkAccessManagerFactory *factory)
588 Q_D(QDeclarativeEngine);
589 QMutexLocker locker(&d->mutex);
590 d->networkAccessManagerFactory = factory;
594 Returns the current QDeclarativeNetworkAccessManagerFactory.
596 \sa setNetworkAccessManagerFactory()
598 QDeclarativeNetworkAccessManagerFactory *QDeclarativeEngine::networkAccessManagerFactory() const
600 Q_D(const QDeclarativeEngine);
601 return d->networkAccessManagerFactory;
604 QNetworkAccessManager *QDeclarativeEnginePrivate::createNetworkAccessManager(QObject *parent) const
606 QMutexLocker locker(&mutex);
607 QNetworkAccessManager *nam;
608 if (networkAccessManagerFactory) {
609 nam = networkAccessManagerFactory->create(parent);
611 nam = new QNetworkAccessManager(parent);
617 QNetworkAccessManager *QDeclarativeEnginePrivate::getNetworkAccessManager() const
619 Q_Q(const QDeclarativeEngine);
620 if (!networkAccessManager)
621 networkAccessManager = createNetworkAccessManager(const_cast<QDeclarativeEngine*>(q));
622 return networkAccessManager;
626 Returns a common QNetworkAccessManager which can be used by any QML
627 element instantiated by this engine.
629 If a QDeclarativeNetworkAccessManagerFactory has been set and a
630 QNetworkAccessManager has not yet been created, the
631 QDeclarativeNetworkAccessManagerFactory will be used to create the
632 QNetworkAccessManager; otherwise the returned QNetworkAccessManager
633 will have no proxy or cache set.
635 \sa setNetworkAccessManagerFactory()
637 QNetworkAccessManager *QDeclarativeEngine::networkAccessManager() const
639 Q_D(const QDeclarativeEngine);
640 return d->getNetworkAccessManager();
645 Sets the \a provider to use for images requested via the \e
646 image: url scheme, with host \a providerId. The QDeclarativeEngine
647 takes ownership of \a provider.
649 Image providers enable support for pixmap and threaded image
650 requests. See the QDeclarativeImageProvider documentation for details on
651 implementing and using image providers.
653 All required image providers should be added to the engine before any
654 QML sources files are loaded.
656 \sa removeImageProvider()
658 void QDeclarativeEngine::addImageProvider(const QString &providerId, QDeclarativeImageProvider *provider)
660 Q_D(QDeclarativeEngine);
661 QMutexLocker locker(&d->mutex);
662 d->imageProviders.insert(providerId.toLower(), QSharedPointer<QDeclarativeImageProvider>(provider));
666 Returns the QDeclarativeImageProvider set for \a providerId.
668 QDeclarativeImageProvider *QDeclarativeEngine::imageProvider(const QString &providerId) const
670 Q_D(const QDeclarativeEngine);
671 QMutexLocker locker(&d->mutex);
672 return d->imageProviders.value(providerId).data();
676 Removes the QDeclarativeImageProvider for \a providerId.
678 Returns the provider if it was found; otherwise returns 0.
680 \sa addImageProvider()
682 void QDeclarativeEngine::removeImageProvider(const QString &providerId)
684 Q_D(QDeclarativeEngine);
685 QMutexLocker locker(&d->mutex);
686 d->imageProviders.take(providerId);
689 QDeclarativeImageProvider::ImageType QDeclarativeEnginePrivate::getImageProviderType(const QUrl &url)
691 QMutexLocker locker(&mutex);
692 QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
695 return provider->imageType();
696 return QDeclarativeImageProvider::Invalid;
699 QSGTexture *QDeclarativeEnginePrivate::getTextureFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
701 QMutexLocker locker(&mutex);
702 QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
705 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
706 return provider->requestTexture(imageId, size, req_size);
711 QImage QDeclarativeEnginePrivate::getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
713 QMutexLocker locker(&mutex);
715 QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
718 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
719 image = provider->requestImage(imageId, size, req_size);
724 QPixmap QDeclarativeEnginePrivate::getPixmapFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
726 QMutexLocker locker(&mutex);
728 QSharedPointer<QDeclarativeImageProvider> provider = imageProviders.value(url.host());
731 QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
732 pixmap = provider->requestPixmap(imageId, size, req_size);
738 Return the base URL for this engine. The base URL is only used to
739 resolve components when a relative URL is passed to the
740 QDeclarativeComponent constructor.
742 If a base URL has not been explicitly set, this method returns the
743 application's current working directory.
747 QUrl QDeclarativeEngine::baseUrl() const
749 Q_D(const QDeclarativeEngine);
750 if (d->baseUrl.isEmpty()) {
751 return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
758 Set the base URL for this engine to \a url.
762 void QDeclarativeEngine::setBaseUrl(const QUrl &url)
764 Q_D(QDeclarativeEngine);
769 Returns true if warning messages will be output to stderr in addition
770 to being emitted by the warnings() signal, otherwise false.
772 The default value is true.
774 bool QDeclarativeEngine::outputWarningsToStandardError() const
776 Q_D(const QDeclarativeEngine);
777 return d->outputWarningsToStdErr;
781 Set whether warning messages will be output to stderr to \a enabled.
783 If \a enabled is true, any warning messages generated by QML will be
784 output to stderr and emitted by the warnings() signal. If \a enabled
785 is false, on the warnings() signal will be emitted. This allows
786 applications to handle warning output themselves.
788 The default value is true.
790 void QDeclarativeEngine::setOutputWarningsToStandardError(bool enabled)
792 Q_D(QDeclarativeEngine);
793 d->outputWarningsToStdErr = enabled;
797 Attempt to free unused memory.
799 void QDeclarativeEngine::collectGarbage()
805 Returns the QDeclarativeContext for the \a object, or 0 if no
806 context has been set.
808 When the QDeclarativeEngine instantiates a QObject, the context is
811 QDeclarativeContext *QDeclarativeEngine::contextForObject(const QObject *object)
816 QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
818 QDeclarativeData *data =
819 static_cast<QDeclarativeData *>(priv->declarativeData);
823 else if (data->outerContext)
824 return data->outerContext->asQDeclarativeContext();
830 Sets the QDeclarativeContext for the \a object to \a context.
831 If the \a object already has a context, a warning is
832 output, but the context is not changed.
834 When the QDeclarativeEngine instantiates a QObject, the context is
837 void QDeclarativeEngine::setContextForObject(QObject *object, QDeclarativeContext *context)
839 if (!object || !context)
842 QDeclarativeData *data = QDeclarativeData::get(object, true);
844 qWarning("QDeclarativeEngine::setContextForObject(): Object already has a QDeclarativeContext");
848 QDeclarativeContextData *contextData = QDeclarativeContextData::get(context);
849 contextData->addObject(object);
853 \enum QDeclarativeEngine::ObjectOwnership
855 Ownership controls whether or not QML automatically destroys the
856 QObject when the object is garbage collected by the JavaScript
857 engine. The two ownership options are:
859 \value CppOwnership The object is owned by C++ code, and will
860 never be deleted by QML. The JavaScript destroy() method cannot be
861 used on objects with CppOwnership. This option is similar to
862 QScriptEngine::QtOwnership.
864 \value JavaScriptOwnership The object is owned by JavaScript.
865 When the object is returned to QML as the return value of a method
866 call or property access, QML will delete the object if there are no
867 remaining JavaScript references to it and it has no
868 QObject::parent(). This option is similar to
869 QScriptEngine::ScriptOwnership.
871 Generally an application doesn't need to set an object's ownership
872 explicitly. QML uses a heuristic to set the default object
873 ownership. By default, an object that is created by QML has
874 JavaScriptOwnership. The exception to this are the root objects
875 created by calling QDeclarativeCompnent::create() or
876 QDeclarativeComponent::beginCreate() which have CppOwnership by
877 default. The ownership of these root-level objects is considered to
878 have been transferred to the C++ caller.
880 Objects not-created by QML have CppOwnership by default. The
881 exception to this is objects returned from a C++ method call. The
882 ownership of these objects is passed to JavaScript.
884 Calling setObjectOwnership() overrides the default ownership
885 heuristic used by QML.
889 Sets the \a ownership of \a object.
891 void QDeclarativeEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
896 QDeclarativeData *ddata = QDeclarativeData::get(object, true);
900 ddata->indestructible = (ownership == CppOwnership)?true:false;
901 ddata->explicitIndestructibleSet = true;
905 Returns the ownership of \a object.
907 QDeclarativeEngine::ObjectOwnership QDeclarativeEngine::objectOwnership(QObject *object)
912 QDeclarativeData *ddata = QDeclarativeData::get(object, false);
916 return ddata->indestructible?CppOwnership:JavaScriptOwnership;
919 Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object)
921 QDeclarativeData *data = QDeclarativeData::get(object);
923 if (data && data->deferredComponent) {
924 if (QDeclarativeDebugService::isDebuggingEnabled()) {
925 QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Creating);
926 QDeclarativeType *type = QDeclarativeMetaType::qmlType(object->metaObject());
927 QString typeName = type ? QLatin1String(type->qmlTypeName()) : QString::fromLatin1(object->metaObject()->className());
928 QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Creating, typeName);
929 if (data->outerContext)
930 QDeclarativeDebugTrace::rangeLocation(QDeclarativeDebugTrace::Creating, data->outerContext->url, data->lineNumber);
932 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(data->context->engine);
934 QDeclarativeComponentPrivate::ConstructionState state;
935 QDeclarativeComponentPrivate::beginDeferred(ep, object, &state);
937 data->deferredComponent->release();
938 data->deferredComponent = 0;
940 QDeclarativeComponentPrivate::complete(ep, &state);
941 QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Creating);
945 QDeclarativeContext *qmlContext(const QObject *obj)
947 return QDeclarativeEngine::contextForObject(obj);
950 QDeclarativeEngine *qmlEngine(const QObject *obj)
952 QDeclarativeContext *context = QDeclarativeEngine::contextForObject(obj);
953 return context?context->engine():0;
956 QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
958 QDeclarativeData *data = QDeclarativeData::get(object);
960 return 0; // Attached properties are only on objects created by QML
962 QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
966 QDeclarativeAttachedPropertiesFunc pf = QDeclarativeMetaType::attachedPropertiesFuncById(id);
970 rv = pf(const_cast<QObject *>(object));
973 data->attachedProperties()->insert(id, rv);
978 QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
979 const QMetaObject *attachedMetaObject, bool create)
982 *idCache = QDeclarativeMetaType::attachedPropertiesFuncId(attachedMetaObject);
984 if (*idCache == -1 || !object)
987 return qmlAttachedPropertiesObjectById(*idCache, object, create);
990 class QDeclarativeDataExtended {
992 QDeclarativeDataExtended();
993 ~QDeclarativeDataExtended();
995 QHash<int, QObject *> attachedProperties;
996 QDeclarativeNotifier objectNameNotifier;
999 QDeclarativeDataExtended::QDeclarativeDataExtended()
1003 QDeclarativeDataExtended::~QDeclarativeDataExtended()
1007 QDeclarativeNotifier *QDeclarativeData::objectNameNotifier() const
1009 if (!extendedData) extendedData = new QDeclarativeDataExtended;
1010 return &extendedData->objectNameNotifier;
1013 QHash<int, QObject *> *QDeclarativeData::attachedProperties() const
1015 if (!extendedData) extendedData = new QDeclarativeDataExtended;
1016 return &extendedData->attachedProperties;
1019 void QDeclarativeData::destroyed(QObject *object)
1021 if (deferredComponent)
1022 deferredComponent->release();
1024 if (nextContextObject)
1025 nextContextObject->prevContextObject = prevContextObject;
1026 if (prevContextObject)
1027 *prevContextObject = nextContextObject;
1029 QDeclarativeAbstractBinding *binding = bindings;
1031 QDeclarativeAbstractBinding *next = binding->m_nextBinding;
1032 binding->m_prevBinding = 0;
1033 binding->m_nextBinding = 0;
1042 propertyCache->release();
1044 if (ownContext && context)
1048 QDeclarativeGuard<QObject> *guard = guards;
1049 *guard = (QObject *)0;
1050 guard->objectDestroyed(object);
1054 delete extendedData;
1056 v8object.Clear(); // The WeakReference handler will clean the actual handle
1062 void QDeclarativeData::parentChanged(QObject *object, QObject *parent)
1068 void QDeclarativeData::objectNameChanged(QObject *)
1070 if (extendedData) objectNameNotifier()->notify();
1073 bool QDeclarativeData::hasBindingBit(int bit) const
1075 if (bindingBitsSize > bit)
1076 return bindingBits[bit / 32] & (1 << (bit % 32));
1081 void QDeclarativeData::clearBindingBit(int bit)
1083 if (bindingBitsSize > bit)
1084 bindingBits[bit / 32] &= ~(1 << (bit % 32));
1087 void QDeclarativeData::setBindingBit(QObject *obj, int bit)
1089 if (bindingBitsSize <= bit) {
1090 int props = obj->metaObject()->propertyCount();
1091 Q_ASSERT(bit < props);
1093 int arraySize = (props + 31) / 32;
1094 int oldArraySize = bindingBitsSize / 32;
1096 bindingBits = (quint32 *)realloc(bindingBits,
1097 arraySize * sizeof(quint32));
1099 memset(bindingBits + oldArraySize,
1101 sizeof(quint32) * (arraySize - oldArraySize));
1103 bindingBitsSize = arraySize * 32;
1106 bindingBits[bit / 32] |= (1 << (bit % 32));
1109 QString QDeclarativeEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
1111 if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
1112 if (url.authority().isEmpty())
1113 return QLatin1Char(':') + url.path();
1116 return url.toLocalFile();
1119 void QDeclarativeEnginePrivate::sendQuit()
1121 Q_Q(QDeclarativeEngine);
1123 if (q->receivers(SIGNAL(quit())) == 0) {
1124 qWarning("Signal QDeclarativeEngine::quit() emitted, but no receivers connected to handle it.");
1128 static void dumpwarning(const QDeclarativeError &error)
1130 qWarning().nospace() << qPrintable(error.toString());
1133 static void dumpwarning(const QList<QDeclarativeError> &errors)
1135 for (int ii = 0; ii < errors.count(); ++ii)
1136 dumpwarning(errors.at(ii));
1139 void QDeclarativeEnginePrivate::warning(const QDeclarativeError &error)
1141 Q_Q(QDeclarativeEngine);
1142 q->warnings(QList<QDeclarativeError>() << error);
1143 if (outputWarningsToStdErr)
1147 void QDeclarativeEnginePrivate::warning(const QList<QDeclarativeError> &errors)
1149 Q_Q(QDeclarativeEngine);
1150 q->warnings(errors);
1151 if (outputWarningsToStdErr)
1152 dumpwarning(errors);
1155 void QDeclarativeEnginePrivate::warning(QDeclarativeEngine *engine, const QDeclarativeError &error)
1158 QDeclarativeEnginePrivate::get(engine)->warning(error);
1163 void QDeclarativeEnginePrivate::warning(QDeclarativeEngine *engine, const QList<QDeclarativeError> &error)
1166 QDeclarativeEnginePrivate::get(engine)->warning(error);
1171 void QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate *engine, const QDeclarativeError &error)
1174 engine->warning(error);
1179 void QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate *engine, const QList<QDeclarativeError> &error)
1182 engine->warning(error);
1188 This function should be called prior to evaluation of any js expression,
1189 so that scarce resources are not freed prematurely (eg, if there is a
1190 nested javascript expression).
1192 void QDeclarativeEnginePrivate::referenceScarceResources()
1194 scarceResourcesRefCount += 1;
1198 This function should be called after evaluation of the js expression is
1199 complete, and so the scarce resources may be freed safely.
1201 void QDeclarativeEnginePrivate::dereferenceScarceResources()
1203 Q_ASSERT(scarceResourcesRefCount > 0);
1204 scarceResourcesRefCount -= 1;
1206 // if the refcount is zero, then evaluation of the "top level"
1207 // expression must have completed. We can safely release the
1208 // scarce resources.
1209 if (scarceResourcesRefCount == 0) {
1210 // iterate through the list and release them all.
1211 // note that the actual SRD is owned by the JS engine,
1212 // so we cannot delete the SRD; but we can free the
1213 // memory used by the variant in the SRD.
1214 while (ScarceResourceData *sr = scarceResources.first()) {
1215 sr->data = QVariant();
1216 scarceResources.remove(sr);
1222 Adds \a path as a directory where the engine searches for
1223 installed modules in a URL-based directory structure.
1224 The \a path may be a local filesystem directory or a URL.
1226 The newly added \a path will be first in the importPathList().
1228 \sa setImportPathList(), {QML Modules}
1230 void QDeclarativeEngine::addImportPath(const QString& path)
1232 Q_D(QDeclarativeEngine);
1233 d->importDatabase.addImportPath(path);
1237 Returns the list of directories where the engine searches for
1238 installed modules in a URL-based directory structure.
1240 For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
1241 imports \c com.mycompany.Feature will cause the QDeclarativeEngine to look
1242 in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
1243 provided by that module. A \c qmldir file is required for defining the
1244 type version mapping and possibly declarative extensions plugins.
1246 By default, the list contains the directory of the application executable,
1247 paths specified in the \c QML_IMPORT_PATH environment variable,
1248 and the builtin \c ImportsPath from QLibraryInfo.
1250 \sa addImportPath() setImportPathList()
1252 QStringList QDeclarativeEngine::importPathList() const
1254 Q_D(const QDeclarativeEngine);
1255 return d->importDatabase.importPathList();
1259 Sets \a paths as the list of directories where the engine searches for
1260 installed modules in a URL-based directory structure.
1262 By default, the list contains the directory of the application executable,
1263 paths specified in the \c QML_IMPORT_PATH environment variable,
1264 and the builtin \c ImportsPath from QLibraryInfo.
1266 \sa importPathList() addImportPath()
1268 void QDeclarativeEngine::setImportPathList(const QStringList &paths)
1270 Q_D(QDeclarativeEngine);
1271 d->importDatabase.setImportPathList(paths);
1276 Adds \a path as a directory where the engine searches for
1277 native plugins for imported modules (referenced in the \c qmldir file).
1279 By default, the list contains only \c ., i.e. the engine searches
1280 in the directory of the \c qmldir file itself.
1282 The newly added \a path will be first in the pluginPathList().
1284 \sa setPluginPathList()
1286 void QDeclarativeEngine::addPluginPath(const QString& path)
1288 Q_D(QDeclarativeEngine);
1289 d->importDatabase.addPluginPath(path);
1294 Returns the list of directories where the engine searches for
1295 native plugins for imported modules (referenced in the \c qmldir file).
1297 By default, the list contains only \c ., i.e. the engine searches
1298 in the directory of the \c qmldir file itself.
1300 \sa addPluginPath() setPluginPathList()
1302 QStringList QDeclarativeEngine::pluginPathList() const
1304 Q_D(const QDeclarativeEngine);
1305 return d->importDatabase.pluginPathList();
1309 Sets the list of directories where the engine searches for
1310 native plugins for imported modules (referenced in the \c qmldir file)
1313 By default, the list contains only \c ., i.e. the engine searches
1314 in the directory of the \c qmldir file itself.
1316 \sa pluginPathList() addPluginPath()
1318 void QDeclarativeEngine::setPluginPathList(const QStringList &paths)
1320 Q_D(QDeclarativeEngine);
1321 d->importDatabase.setPluginPathList(paths);
1325 Imports the plugin named \a filePath with the \a uri provided.
1326 Returns true if the plugin was successfully imported; otherwise returns false.
1328 On failure and if non-null, the \a errors list will have any errors which occurred prepended to it.
1330 The plugin has to be a Qt plugin which implements the QDeclarativeExtensionPlugin interface.
1332 bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &uri, QList<QDeclarativeError> *errors)
1334 Q_D(QDeclarativeEngine);
1335 return d->importDatabase.importPlugin(filePath, uri, errors);
1339 Imports the plugin named \a filePath with the \a uri provided.
1340 Returns true if the plugin was successfully imported; otherwise returns false.
1342 On failure and if non-null, *\a errorString will be set to a message describing the failure.
1344 The plugin has to be a Qt plugin which implements the QDeclarativeExtensionPlugin interface.
1346 bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString)
1348 Q_D(QDeclarativeEngine);
1349 QList<QDeclarativeError> errors;
1350 bool retn = d->importDatabase.importPlugin(filePath, uri, &errors);
1351 if (!errors.isEmpty()) {
1353 for (int i = 0; i < errors.size(); ++i) {
1354 builtError = QString(QLatin1String("%1\n %2"))
1356 .arg(errors.at(i).toString());
1358 *errorString = builtError;
1364 \property QDeclarativeEngine::offlineStoragePath
1365 \brief the directory for storing offline user data
1367 Returns the directory where SQL and other offline
1370 QDeclarativeWebView and the SQL databases created with openDatabase()
1373 The default is QML/OfflineStorage in the platform-standard
1374 user application data directory.
1376 Note that the path may not currently exist on the filesystem, so
1377 callers wanting to \e create new files at this location should create
1378 it first - see QDir::mkpath().
1380 void QDeclarativeEngine::setOfflineStoragePath(const QString& dir)
1382 Q_D(QDeclarativeEngine);
1383 qt_qmlsqldatabase_setOfflineStoragePath(&d->v8engine, dir);
1386 QString QDeclarativeEngine::offlineStoragePath() const
1388 Q_D(const QDeclarativeEngine);
1389 return qt_qmlsqldatabase_getOfflineStoragePath(&d->v8engine);
1392 static void voidptr_destructor(void *v)
1394 void **ptr = (void **)v;
1398 static void *voidptr_constructor(const void *v)
1403 return new void*(*(void **)v);
1407 QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(const QMetaObject *mo)
1409 Q_Q(QDeclarativeEngine);
1411 if (!mo->superClass()) {
1412 QDeclarativePropertyCache *rv = new QDeclarativePropertyCache(q, mo);
1413 propertyCache.insert(mo, rv);
1416 QDeclarativePropertyCache *super = cache(mo->superClass());
1417 QDeclarativePropertyCache *rv = super->copy();
1419 propertyCache.insert(mo, rv);
1424 QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(QDeclarativeType *type, int minorVersion,
1425 QDeclarativeError &error)
1427 QList<QDeclarativeType *> types;
1429 int maxMinorVersion = 0;
1431 const QMetaObject *metaObject = type->metaObject();
1432 while (metaObject) {
1433 QDeclarativeType *t = QDeclarativeMetaType::qmlType(metaObject, type->module(),
1434 type->majorVersion(), minorVersion);
1436 maxMinorVersion = qMax(maxMinorVersion, t->minorVersion());
1442 metaObject = metaObject->superClass();
1445 if (QDeclarativePropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) {
1447 typePropertyCache.insert(qMakePair(type, minorVersion), c);
1451 QDeclarativePropertyCache *raw = cache(type->metaObject());
1453 bool hasCopied = false;
1455 for (int ii = 0; ii < types.count(); ++ii) {
1456 QDeclarativeType *currentType = types.at(ii);
1460 int rev = currentType->metaObjectRevision();
1461 int moIndex = types.count() - 1 - ii;
1463 if (raw->allowedRevisionCache[moIndex] != rev) {
1468 raw->allowedRevisionCache[moIndex] = rev;
1472 // Test revision compatibility - the basic rule is:
1473 // * Anything that is excluded, cannot overload something that is not excluded *
1475 // Signals override:
1476 // * other signals and methods of the same name.
1477 // * properties named on<Signal Name>
1478 // * automatic <property name>Changed notify signals
1480 // Methods override:
1481 // * other methods of the same name
1483 // Properties override:
1484 // * other elements of the same name
1486 bool overloadError = false;
1487 QString overloadName;
1490 for (QDeclarativePropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin();
1491 !overloadError && iter != raw->stringCache.end();
1494 QDeclarativePropertyCache::Data *d = *iter;
1495 if (raw->isAllowedInRevision(d))
1496 continue; // Not excluded - no problems
1498 // check that a regular "name" overload isn't happening
1499 QDeclarativePropertyCache::Data *current = d;
1500 while (!overloadError && current) {
1501 current = d->overrideData(current);
1502 if (current && raw->isAllowedInRevision(current))
1503 overloadError = true;
1508 if (overloadError) {
1509 if (hasCopied) raw->release();
1511 error.setDescription(QLatin1String("Type ") + QString::fromUtf8(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."));
1515 if (!hasCopied) raw->addref();
1516 typePropertyCache.insert(qMakePair(type, minorVersion), raw);
1518 if (minorVersion != maxMinorVersion) {
1520 typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw);
1526 void QDeclarativeEnginePrivate::registerCompositeType(QDeclarativeCompiledData *data)
1528 QByteArray name = data->root->className();
1530 QByteArray ptr = name + '*';
1531 QByteArray lst = "QDeclarativeListProperty<" + name + '>';
1533 int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
1534 voidptr_constructor);
1535 int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
1536 voidptr_constructor);
1538 m_qmlLists.insert(lst_type, ptr_type);
1539 m_compositeTypes.insert(ptr_type, data);
1543 bool QDeclarativeEnginePrivate::isList(int t) const
1545 return m_qmlLists.contains(t) || QDeclarativeMetaType::isList(t);
1548 int QDeclarativeEnginePrivate::listType(int t) const
1550 QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
1551 if (iter != m_qmlLists.end())
1554 return QDeclarativeMetaType::listType(t);
1557 bool QDeclarativeEnginePrivate::isQObject(int t)
1559 return m_compositeTypes.contains(t) || QDeclarativeMetaType::isQObject(t);
1562 QObject *QDeclarativeEnginePrivate::toQObject(const QVariant &v, bool *ok) const
1564 int t = v.userType();
1565 if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) {
1567 return *(QObject **)(v.constData());
1569 return QDeclarativeMetaType::toQObject(v, ok);
1573 QDeclarativeMetaType::TypeCategory QDeclarativeEnginePrivate::typeCategory(int t) const
1575 if (m_compositeTypes.contains(t))
1576 return QDeclarativeMetaType::Object;
1577 else if (m_qmlLists.contains(t))
1578 return QDeclarativeMetaType::List;
1580 return QDeclarativeMetaType::typeCategory(t);
1583 const QMetaObject *QDeclarativeEnginePrivate::rawMetaObjectForType(int t) const
1585 QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1586 if (iter != m_compositeTypes.end()) {
1587 return (*iter)->root;
1589 QDeclarativeType *type = QDeclarativeMetaType::qmlType(t);
1590 return type?type->baseMetaObject():0;
1594 const QMetaObject *QDeclarativeEnginePrivate::metaObjectForType(int t) const
1596 QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
1597 if (iter != m_compositeTypes.end()) {
1598 return (*iter)->root;
1600 QDeclarativeType *type = QDeclarativeMetaType::qmlType(t);
1601 return type?type->metaObject():0;
1605 bool QDeclarative_isFileCaseCorrect(const QString &fileName)
1607 #if defined(Q_OS_MAC) || defined(Q_OS_WIN32)
1608 QFileInfo info(fileName);
1610 QString absolute = info.absoluteFilePath();
1612 #if defined(Q_OS_MAC)
1613 QString canonical = info.canonicalFilePath();
1614 #elif defined(Q_OS_WIN32)
1615 wchar_t buffer[1024];
1617 DWORD rv = ::GetShortPathName((wchar_t*)absolute.utf16(), buffer, 1024);
1618 if (rv == 0 || rv >= 1024) return true;
1619 rv = ::GetLongPathName(buffer, buffer, 1024);
1620 if (rv == 0 || rv >= 1024) return true;
1622 QString canonical((QChar *)buffer);
1625 int absoluteLength = absolute.length();
1626 int canonicalLength = canonical.length();
1628 int length = qMin(absoluteLength, canonicalLength);
1629 for (int ii = 0; ii < length; ++ii) {
1630 const QChar &a = absolute.at(absoluteLength - 1 - ii);
1631 const QChar &c = canonical.at(canonicalLength - 1 - ii);
1633 if (a.toLower() != c.toLower())