Doc: Enabling Qt QML linking to Qt Quick.
[profile/ivi/qtdeclarative.git] / src / qml / qml / qqmlengine.cpp
index 72c1c35..d7b6f70 100644 (file)
@@ -1,38 +1,38 @@
 /****************************************************************************
 **
-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
 **
 ** This file is part of the QtQml module of the Qt Toolkit.
 **
 ** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
 ** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 **
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 **
 ** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
 **
 **
 ** $QT_END_LICENSE$
 
 #include <private/qqmllocale_p.h>
 
+#include "qqmlbind_p.h"
+#include "qqmlconnections_p.h"
+#include "qqmltimer_p.h"
+
 #ifdef Q_OS_WIN // for %APPDATA%
 #include <qt_windows.h>
 #include <qlibrary.h>
@@ -113,7 +117,6 @@ void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
     \instantiates QObject
   \inqmlmodule QtQuick 2
   \ingroup qml-utility-elements
-  \since 4.7
   \brief A basic QML type
 
   The QtObject type is a non-visual element which contains only the
@@ -166,12 +169,17 @@ void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
 */
 
 bool QQmlEnginePrivate::qml_debugging_enabled = false;
+bool QQmlEnginePrivate::s_designerMode = false;
 
 // these types are part of the QML language
 void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
 {
     qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
     qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
+    qmlRegisterType<QQmlBind>(uri, versionMajor, versionMinor,"Binding");
+    qmlRegisterType<QQmlConnections>(uri, versionMajor, versionMinor,"Connections");
+    qmlRegisterType<QQmlTimer>(uri, versionMajor, versionMinor,"Timer");
+    qmlRegisterCustomType<QQmlConnections>(uri, versionMajor, versionMinor,"Connections", new QQmlConnectionsParser);
 }
 
 
@@ -193,11 +201,22 @@ void QQmlEnginePrivate::defineQtQuick2Module()
     qmlRegisterUncreatableType<QQmlLocale>("QtQuick", 2, 0, "Locale", QQmlEngine::tr("Locale cannot be instantiated.  Use Qt.locale()"));
 }
 
+bool QQmlEnginePrivate::designerMode()
+{
+    return s_designerMode;
+}
+
+void QQmlEnginePrivate::activateDesignerMode()
+{
+    s_designerMode = true;
+}
+
 
 /*!
     \class QQmlImageProviderBase
     \brief The QQmlImageProviderBase class is used to register image providers in the QML engine.
     \mainclass
+    \inmodule QtQml
 
     Image providers must be registered with the QML engine.  The only information the QML
     engine knows about image providers is the type of image data they provide.  To use an
@@ -217,7 +236,8 @@ void QQmlEnginePrivate::defineQtQuick2Module()
     \value Pixmap The Image Provider provides QPixmap images.
         The QQuickImageProvider::requestPixmap() method will be called for all image requests.
     \value Texture The Image Provider provides QSGTextureProvider based images.
-        The QQuickImageProvider::requestTexture() method will be called for all image requests. \omitvalue
+        The QQuickImageProvider::requestTexture() method will be called for all image requests.
+    \omitvalue Invalid
 */
 
 /*!
@@ -295,7 +315,7 @@ creating objects of specific data types are also available for clients to use:
 \li \c matrix4x4 - use \l{Qt::matrix4x4()}{Qt.matrix4x4()}
 \endlist
 
-There are also string based constructors for these types. See \l{qdeclarativebasictypes.html}{QML Basic Types} for more information.
+There are also string based constructors for these types. See \l{qtqml-typesystem-basictypes.html}{QML Basic Types} for more information.
 
 \section1 Date/Time Formatters
 
@@ -462,10 +482,6 @@ QQmlEnginePrivate::~QQmlEnginePrivate()
         (*iter)->release();
     for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
         (*iter)->release();
-    for(QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *>::Iterator iter = moduleApiInstances.begin(); iter != moduleApiInstances.end(); ++iter) {
-        delete (*iter)->qobjectApi;
-        delete *iter;
-    }
     for (QHash<int, QQmlCompiledData *>::Iterator iter = m_compositeTypes.begin(); iter != m_compositeTypes.end(); ++iter)
         iter.value()->isRegisteredWithEngine = false;
 }
@@ -483,6 +499,11 @@ void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
         // Mark this object as in the process of deletion to
         // prevent it resolving in bindings
         QQmlData::markAsDeleted(o);
+
+        // Disconnect the notifiers now - during object destruction this would be too late, since
+        // the disconnect call wouldn't be able to call disconnectNotify(), as it isn't possible to
+        // get the metaobject anymore.
+        d->disconnectNotifiers();
     }
 }
 
@@ -625,6 +646,22 @@ void QQmlData::setQueuedForDeletion(QObject *object)
     }
 }
 
+void QQmlData::flushPendingBindingImpl(int coreIndex)
+{
+    clearPendingBindingBit(coreIndex);
+
+    // Find the binding
+    QQmlAbstractBinding *b = bindings;
+    while (b && *b->m_mePtr && b->propertyIndex() != coreIndex)
+        b = b->nextBinding();
+
+    if (b) {
+        b->m_mePtr = 0;
+        b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor |
+                            QQmlPropertyPrivate::DontRemoveBinding);
+    }
+}
+
 void QQmlEnginePrivate::init()
 {
     Q_Q(QQmlEngine);
@@ -638,13 +675,13 @@ void QQmlEnginePrivate::init()
         firstTime = false;
     }
 
-    qRegisterMetaType<QVariant>("QVariant");
-    qRegisterMetaType<QQmlScriptString>("QQmlScriptString");
-    qRegisterMetaType<QJSValue>("QJSValue");
-    qRegisterMetaType<QQmlComponent::Status>("QQmlComponent::Status");
-    qRegisterMetaType<QList<QObject*> >("QList<QObject*>");
-    qRegisterMetaType<QList<int> >("QList<int>");
-    qRegisterMetaType<QQmlV8Handle>("QQmlV8Handle");
+    qRegisterMetaType<QVariant>();
+    qRegisterMetaType<QQmlScriptString>();
+    qRegisterMetaType<QJSValue>();
+    qRegisterMetaType<QQmlComponent::Status>();
+    qRegisterMetaType<QList<QObject*> >();
+    qRegisterMetaType<QList<int> >();
+    qRegisterMetaType<QQmlV8Handle>();
 
     v8engine()->setEngine(q);
 
@@ -734,25 +771,17 @@ QQmlEngine::~QQmlEngine()
     }
 
     // Emit onDestruction signals for the root context before
-    // we destroy the contexts, engine, Module APIs etc. that
+    // we destroy the contexts, engine, Singleton Types etc. that
     // may be required to handle the destruction signal.
     QQmlContextData::get(rootContext())->emitDestruction();
 
-    // if we are the parent of any of the qobject module api instances,
-    // we need to remove them from our internal list, in order to prevent
-    // a segfault in engine private dtor.
-    QList<QQmlMetaType::ModuleApi> keys = d->moduleApiInstances.keys();
-    QObject *currQObjectApi = 0;
-    QQmlMetaType::ModuleApiInstance *currInstance = 0;
-    foreach (const QQmlMetaType::ModuleApi &key, keys) {
-        currInstance = d->moduleApiInstances.value(key);
-        currQObjectApi = currInstance->qobjectApi;
-        if (this->children().contains(currQObjectApi)) {
-            delete currQObjectApi;
-            delete currInstance;
-            d->moduleApiInstances.remove(key);
-        }
-    }
+    // clean up all singleton type instances which we own.
+    // we do this here and not in the private dtor since otherwise a crash can
+    // occur (if we are the QObject parent of the QObject singleton instance)
+    // XXX TODO: performance -- store list of singleton types separately?
+    QList<QQmlType*> singletonTypes = QQmlMetaType::qmlSingletonTypes();
+    foreach (QQmlType *currType, singletonTypes)
+        currType->singletonInstanceInfo()->destroy(this);
 
     if (d->incubationController)
         d->incubationController->d = 0;
@@ -1088,8 +1117,10 @@ void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
   have been transferred to the C++ caller.
 
   Objects not-created by QML have CppOwnership by default.  The
-  exception to this is objects returned from a C++ method call.  The
-  ownership of these objects is passed to JavaScript.
+  exception to this is objects returned from C++ method calls; in these cases,
+  the ownership of the returned objects will be set to JavaScriptOwnerShip.
+  Note this applies only to explicit invocations of Q_INVOKABLE methods or slots,
+  and not to property getter invocations.
 
   Calling setObjectOwnership() overrides the default ownership
   heuristic used by QML.
@@ -1330,6 +1361,21 @@ bool QQmlData::signalHasEndpoint(int index)
     return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
 }
 
+void QQmlData::disconnectNotifiers()
+{
+    if (notifyList) {
+        while (notifyList->todo)
+            notifyList->todo->disconnect();
+        for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
+            while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
+                ep->disconnect();
+        }
+        free(notifyList->notifies);
+        free(notifyList);
+        notifyList = 0;
+    }
+}
+
 QHash<int, QObject *> *QQmlData::attachedProperties() const
 {
     if (!extendedData) extendedData = new QQmlDataExtended;
@@ -1410,17 +1456,7 @@ void QQmlData::destroyed(QObject *object)
         guard->objectDestroyed(object);
     }
 
-    if (notifyList) {
-        while (notifyList->todo)
-            notifyList->todo->disconnect();
-        for (int ii = 0; ii < notifyList->notifiesSize; ++ii) {
-            while (QQmlNotifierEndpoint *ep = notifyList->notifies[ii])
-                ep->disconnect();
-        }
-        free(notifyList->notifies);
-        free(notifyList);
-        notifyList = 0;
-    }
+    disconnectNotifiers();
 
     if (extendedData)
         delete extendedData;
@@ -1455,40 +1491,52 @@ void QQmlData::parentChanged(QObject *object, QObject *parent)
     }
 }
 
-bool QQmlData::hasBindingBit(int bit) const
-{
-    if (bindingBitsSize > bit)
-        return bindingBits[bit / 32] & (1 << (bit % 32));
-    else
-        return false;
-}
-
-void QQmlData::clearBindingBit(int bit)
+static void QQmlData_setBit(QQmlData *data, QObject *obj, int bit)
 {
-    if (bindingBitsSize > bit)
-        bindingBits[bit / 32] &= ~(1 << (bit % 32));
-}
-
-void QQmlData::setBindingBit(QObject *obj, int bit)
-{
-    if (bindingBitsSize <= bit) {
+    if (data->bindingBitsSize <= bit) {
         int props = QQmlMetaObject(obj).propertyCount();
-        Q_ASSERT(bit < props);
+        Q_ASSERT(bit < 2 * props);
 
-        int arraySize = (props + 31) / 32;
-        int oldArraySize = bindingBitsSize / 32;
+        int arraySize = (2 * props + 31) / 32;
+        int oldArraySize = data->bindingBitsSize / 32;
 
-        bindingBits = (quint32 *)realloc(bindingBits,
-                                         arraySize * sizeof(quint32));
+        data->bindingBits = (quint32 *)realloc(data->bindingBits,
+                                               arraySize * sizeof(quint32));
 
-        memset(bindingBits + oldArraySize,
+        memset(data->bindingBits + oldArraySize,
                0x00,
                sizeof(quint32) * (arraySize - oldArraySize));
 
-        bindingBitsSize = arraySize * 32;
+        data->bindingBitsSize = arraySize * 32;
     }
 
-    bindingBits[bit / 32] |= (1 << (bit % 32));
+    data->bindingBits[bit / 32] |= (1 << (bit % 32));
+}
+
+static void QQmlData_clearBit(QQmlData *data, int bit)
+{
+    if (data->bindingBitsSize > bit)
+        data->bindingBits[bit / 32] &= ~(1 << (bit % 32));
+}
+
+void QQmlData::clearBindingBit(int coreIndex)
+{
+    QQmlData_clearBit(this, coreIndex * 2);
+}
+
+void QQmlData::setBindingBit(QObject *obj, int coreIndex)
+{
+    QQmlData_setBit(this, obj, coreIndex * 2);
+}
+
+void QQmlData::clearPendingBindingBit(int coreIndex)
+{
+    QQmlData_clearBit(this, coreIndex * 2 + 1);
+}
+
+void QQmlData::setPendingBindingBit(QObject *obj, int coreIndex)
+{
+    QQmlData_setBit(this, obj, coreIndex * 2 + 1);
 }
 
 void QQmlEnginePrivate::sendQuit()
@@ -1641,8 +1689,8 @@ void QQmlEngine::addImportPath(const QString& path)
   type version mapping and possibly QML extensions plugins.
 
   By default, the list contains the directory of the application executable,
-  paths specified in the \c QML_IMPORT_PATH environment variable,
-  and the builtin \c ImportsPath from QLibraryInfo.
+  paths specified in the \c QML2_IMPORT_PATH environment variable,
+  and the builtin \c Qml2ImportsPath from QLibraryInfo.
 
   \sa addImportPath(), setImportPathList()
 */
@@ -1657,8 +1705,8 @@ QStringList QQmlEngine::importPathList() const
   installed modules in a URL-based directory structure.
 
   By default, the list contains the directory of the application executable,
-  paths specified in the \c QML_IMPORT_PATH environment variable,
-  and the builtin \c ImportsPath from QLibraryInfo.
+  paths specified in the \c QML2_IMPORT_PATH environment variable,
+  and the builtin \c Qml2ImportsPath from QLibraryInfo.
 
   \sa importPathList(), addImportPath()
   */
@@ -1729,7 +1777,7 @@ void QQmlEngine::setPluginPathList(const QStringList &paths)
 bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
 {
     Q_D(QQmlEngine);
-    return d->importDatabase.importPlugin(filePath, uri, errors);
+    return d->importDatabase.importPlugin(filePath, uri, QString(), errors);
 }
 
 /*!
@@ -1880,23 +1928,6 @@ QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersi
     return raw;
 }
 
-QQmlMetaType::ModuleApiInstance *
-QQmlEnginePrivate::moduleApiInstance(const QQmlMetaType::ModuleApi &module)
-{
-    Locker locker(this);
-
-    QQmlMetaType::ModuleApiInstance *a = moduleApiInstances.value(module);
-    if (!a) {
-        a = new QQmlMetaType::ModuleApiInstance;
-        a->scriptCallback = module.script;
-        a->qobjectCallback = module.qobject;
-        a->instanceMetaObject = module.instanceMetaObject;
-        moduleApiInstances.insert(module, a);
-    }
-
-    return a;
-}
-
 bool QQmlEnginePrivate::isQObject(int t)
 {
     Locker locker(this);
@@ -2000,18 +2031,18 @@ void QQmlEnginePrivate::registerCompositeType(QQmlCompiledData *data)
     QByteArray lst = "QQmlListProperty<" + name + '>';
 
     int ptr_type = QMetaType::registerNormalizedType(ptr,
-                                                     qMetaTypeDeleteHelper<QObject*>,
-                                                     qMetaTypeCreateHelper<QObject*>,
-                                                     qMetaTypeDestructHelper<QObject*>,
-                                                     qMetaTypeConstructHelper<QObject*>,
+                                                     QtMetaTypePrivate::QMetaTypeFunctionHelper<QObject*>::Delete,
+                                                     QtMetaTypePrivate::QMetaTypeFunctionHelper<QObject*>::Create,
+                                                     QtMetaTypePrivate::QMetaTypeFunctionHelper<QObject*>::Destruct,
+                                                     QtMetaTypePrivate::QMetaTypeFunctionHelper<QObject*>::Construct,
                                                      sizeof(QObject*),
                                                      static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QObject*>::Flags),
                                                      0);
     int lst_type = QMetaType::registerNormalizedType(lst,
-                                                     qMetaTypeDeleteHelper<QQmlListProperty<QObject> >,
-                                                     qMetaTypeCreateHelper<QQmlListProperty<QObject> >,
-                                                     qMetaTypeDestructHelper<QQmlListProperty<QObject> >,
-                                                     qMetaTypeConstructHelper<QQmlListProperty<QObject> >,
+                                                     QtMetaTypePrivate::QMetaTypeFunctionHelper<QQmlListProperty<QObject> >::Delete,
+                                                     QtMetaTypePrivate::QMetaTypeFunctionHelper<QQmlListProperty<QObject> >::Create,
+                                                     QtMetaTypePrivate::QMetaTypeFunctionHelper<QQmlListProperty<QObject> >::Destruct,
+                                                     QtMetaTypePrivate::QMetaTypeFunctionHelper<QQmlListProperty<QObject> >::Construct,
                                                      sizeof(QQmlListProperty<QObject>),
                                                      static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<QObject> >::Flags),
                                                      static_cast<QMetaObject*>(0));
@@ -2047,13 +2078,13 @@ bool QQmlEnginePrivate::isScriptLoaded(const QUrl &url) const
     return typeLoader.isScriptLoaded(url);
 }
 
-bool QQml_isFileCaseCorrect(const QString &fileName)
+bool QQml_isFileCaseCorrect(const QString &fileName, int lengthIn /* = -1 */)
 {
 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
     QFileInfo info(fileName);
     const QString absolute = info.absoluteFilePath();
 
-#if defined(Q_OS_MAC)
+#if defined(Q_OS_MAC) || defined(Q_OS_WINCE)
     const QString canonical = info.canonicalFilePath();
 #elif defined(Q_OS_WIN)
     wchar_t buffer[1024];
@@ -2069,7 +2100,21 @@ bool QQml_isFileCaseCorrect(const QString &fileName)
     const int absoluteLength = absolute.length();
     const int canonicalLength = canonical.length();
 
-    const int length = qMin(absoluteLength, canonicalLength);
+    int length = qMin(absoluteLength, canonicalLength);
+    if (lengthIn >= 0) {
+        length = qMin(lengthIn, length);
+    } else {
+        // No length given: Limit to file name. Do not trigger
+        // on drive letters or folder names.
+        int lastSlash = absolute.lastIndexOf(QLatin1Char('/'));
+        if (lastSlash < 0)
+            lastSlash = absolute.lastIndexOf(QLatin1Char('\\'));
+        if (lastSlash >= 0) {
+            const int fileNameLength = absoluteLength - 1 - lastSlash;
+            length = qMin(length, fileNameLength);
+        }
+    }
+
     for (int ii = 0; ii < length; ++ii) {
         const QChar &a = absolute.at(absoluteLength - 1 - ii);
         const QChar &c = canonical.at(canonicalLength - 1 - ii);
@@ -2080,6 +2125,7 @@ bool QQml_isFileCaseCorrect(const QString &fileName)
             return false;
     }
 #else
+    Q_UNUSED(lengthIn)
     Q_UNUSED(fileName)
 #endif
     return true;