Doc: Enabling Qt QML linking to Qt Quick.
[profile/ivi/qtdeclarative.git] / src / qml / qml / qqmlengine.cpp
index 589d7b7..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,6 +201,16 @@ 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
@@ -218,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
 */
 
 /*!
@@ -463,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;
 }
@@ -484,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();
     }
 }
 
@@ -626,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);
@@ -639,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);
 
@@ -735,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;
@@ -1089,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.
@@ -1331,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;
@@ -1411,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;
@@ -1456,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()
@@ -1642,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()
 */
@@ -1658,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()
   */
@@ -1881,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);
@@ -2001,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));
@@ -2048,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];
@@ -2070,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);
@@ -2081,6 +2125,7 @@ bool QQml_isFileCaseCorrect(const QString &fileName)
             return false;
     }
 #else
+    Q_UNUSED(lengthIn)
     Q_UNUSED(fileName)
 #endif
     return true;