Remove "All rights reserved" line from license headers.
[profile/ivi/qtdeclarative.git] / src / declarative / qml / v4 / qv4bindings.cpp
index 2e8a360..5f71809 100644 (file)
@@ -1,8 +1,7 @@
 /****************************************************************************
 **
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
 **
 ** This file is part of the QtDeclarative module of the Qt Toolkit.
 **
@@ -35,6 +34,7 @@
 **
 **
 **
+**
 ** $QT_END_LICENSE$
 **
 ****************************************************************************/
 #include "qv4compiler_p.h"
 #include "qv4compiler_p_p.h"
 
-#include <private/qdeclarativefastproperties_p.h>
+#include <private/qdeclarativeaccessors_p.h>
 #include <private/qdeclarativedebugtrace_p.h>
-#include <private/qsganchors_p_p.h> // For AnchorLine
+#include <private/qdeclarativemetatype_p.h>
+#include <private/qdeclarativetrace_p.h>
 
 #include <QtDeclarative/qdeclarativeinfo.h>
 #include <QtCore/qnumeric.h>
@@ -212,7 +213,8 @@ QV4Bindings::~QV4Bindings()
 }
 
 QDeclarativeAbstractBinding *QV4Bindings::configBinding(int index, QObject *target, 
-                                                                   QObject *scope, int property)
+                                                        QObject *scope, int property,
+                                                        int line, int column)
 {
     Binding *rv = bindings + index;
 
@@ -220,6 +222,8 @@ QDeclarativeAbstractBinding *QV4Bindings::configBinding(int index, QObject *targ
     rv->property = property;
     rv->target = target;
     rv->scope = scope;
+    rv->line = line;
+    rv->column = column;
     rv->parent = this;
 
     addref(); // This is decremented in Binding::destroy()
@@ -239,6 +243,9 @@ void QV4Bindings::Binding::setEnabled(bool e, QDeclarativePropertyPrivate::Write
 void QV4Bindings::Binding::update(QDeclarativePropertyPrivate::WriteFlags flags)
 {
     QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Binding);
+    if (parent->context())
+        QDeclarativeDebugTrace::rangeLocation(QDeclarativeDebugTrace::Binding,
+                                              parent->context()->url, line, column);
     parent->run(this, flags);
     QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Binding);
 }
@@ -266,8 +273,10 @@ void QV4Bindings::subscriptionNotify(int id)
         QV4Program::BindingReference *bindingRef = list->bindings + ii;
 
         Binding *binding = bindings + bindingRef->binding;
-        if (binding->executedBlocks & bindingRef->blockMask)
+
+        if (binding->executedBlocks & bindingRef->blockMask) {
             run(binding, QDeclarativePropertyPrivate::DontRemoveBinding);
+        }
     }
 }
 
@@ -280,6 +289,11 @@ void QV4Bindings::run(Binding *binding, QDeclarativePropertyPrivate::WriteFlags
     if (!context || !context->isValid()) 
         return;
 
+    QDeclarativeTrace trace("V4 Binding Update");
+    trace.addDetail("URL", context->url);
+    trace.addDetail("Line", binding->line);
+    trace.addDetail("Column", binding->column);
+
     if (binding->updating) {
         QString name;
         if (binding->property & 0xFFFF0000) {
@@ -338,6 +352,8 @@ void QV4Bindings::subscribeId(QDeclarativeContextData *p, int idIndex, int subIn
 void QV4Bindings::subscribe(QObject *o, int notifyIndex, int subIndex)
 {
     Subscription *sub = (subscriptions + subIndex);
+    if (sub->isConnected(o, notifyIndex))
+        return;
     sub->bindings = this;
     sub->method = subIndex; 
     if (o)
@@ -404,15 +420,16 @@ inline static QUrl toUrl(Register *reg, int type, QDeclarativeContextData *conte
         if (vt == QVariant::Url) {
             base = var->toUrl();
         } else if (vt == QVariant::ByteArray) {
-            base = QUrl(QString::fromUtf8(var->toByteArray()));
+            // Preserve any valid percent-encoded octets supplied by the source
+            base.setEncodedUrl(var->toByteArray(), QUrl::TolerantMode);
         } else if (vt == QVariant::String) {
-            base = QUrl(var->toString());
+            base.setEncodedUrl(var->toString().toUtf8(), QUrl::TolerantMode);
         } else {
             if (ok) *ok = false;
             return QUrl();
         }
     } else if (type == QMetaType::QString) {
-        base = QUrl(*reg->getstringptr());
+        base.setEncodedUrl(reg->getstringptr()->toUtf8(), QUrl::TolerantMode);
     } else {
         if (ok) *ok = false;
         return QUrl();
@@ -444,11 +461,8 @@ static bool testCompareVariants(const QVariant &qtscriptRaw, const QVariant &v4)
         QDeclarative1AnchorLine ra = qvariant_cast<QDeclarative1AnchorLine>(v4);
 
         return la == ra;
-    } else if (type == qMetaTypeId<QSGAnchorLine>()) {
-        QSGAnchorLine la = qvariant_cast<QSGAnchorLine>(qtscript);
-        QSGAnchorLine ra = qvariant_cast<QSGAnchorLine>(v4);
-
-        return la == ra;
+    } else if (type == QDeclarativeMetaType::QQuickAnchorLineMetaTypeId()) {
+        return QDeclarativeMetaType::QQuickAnchorLineCompare(qtscript.constData(), v4.constData());
     } else if (type == QMetaType::Double) {
 
         double la = qvariant_cast<double>(qtscript);
@@ -529,8 +543,8 @@ static void testBindingResult(const QString &binding, int line, int column,
         default:
             if (resultType == qMetaTypeId<QDeclarative1AnchorLine>()) {
                 v4value = qVariantFromValue<QDeclarative1AnchorLine>(*(QDeclarative1AnchorLine *)result.typeDataPtr());
-            } else if (resultType == qMetaTypeId<QSGAnchorLine>()) {
-                v4value = qVariantFromValue<QSGAnchorLine>(*(QSGAnchorLine *)result.typeDataPtr());
+            } else if (resultType == QDeclarativeMetaType::QQuickAnchorLineMetaTypeId()) {
+                v4value = QVariant(QDeclarativeMetaType::QQuickAnchorLineMetaTypeId(), result.typeDataPtr());
             } else {
                 iserror = true;
                 v4Result = "Unknown V4 type";
@@ -757,7 +771,17 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
             reg.init((Register::Type)instr->fetchAndSubscribe.valueType);
             if (instr->fetchAndSubscribe.valueType >= FirstCleanupType)
                 MARK_REGISTER(instr->fetchAndSubscribe.reg);
-            QDeclarativeFastProperties::instance()->accessor(instr->fetchAndSubscribe.function)(object, reg.typeDataPtr(), sub);
+            QDeclarativeAccessors *accessors = instr->fetchAndSubscribe.property.accessors;
+            accessors->read(object, instr->fetchAndSubscribe.property.accessorData,
+                            reg.typeDataPtr());
+
+            if (accessors->notifier) {
+                QDeclarativeNotifier *notifier = 0;
+                accessors->notifier(object, instr->fetchAndSubscribe.property.accessorData, &notifier);
+                if (notifier) sub->connect(notifier);
+            } else if (instr->fetchAndSubscribe.property.notifyIndex != -1) {
+                sub->connect(object, instr->fetchAndSubscribe.property.notifyIndex);
+            }
         }
     }
     QML_V4_END_INSTR(FetchAndSubscribe, fetchAndSubscribe)
@@ -951,7 +975,7 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
                 output.cleanupString();
                 MARK_CLEAN_REGISTER(instr->unaryop.output);
             }
-            output.setint(tmp.toInt32());
+            output.setint(tmp.toInt());
         }
     }
     QML_V4_END_INSTR(ConvertStringToInt, unaryop)
@@ -976,6 +1000,83 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
     }
     QML_V4_END_INSTR(ConvertStringToReal, unaryop)
 
+    QML_V4_BEGIN_INSTR(ConvertStringToUrl, unaryop)
+    {
+        const Register &src = registers[instr->unaryop.src];
+        Register &output = registers[instr->unaryop.output];
+        // ### NaN
+        if (src.isUndefined()) {
+            output.setUndefined();
+        } else {
+            const QString tmp(*src.getstringptr());
+            if (instr->unaryop.src == instr->unaryop.output) {
+                output.cleanupString();
+                MARK_CLEAN_REGISTER(instr->unaryop.output);
+            }
+            QUrl *urlPtr = output.geturlptr();
+            new (urlPtr) QUrl();
+            urlPtr->setEncodedUrl(tmp.toUtf8(), QUrl::TolerantMode);
+
+            URL_REGISTER(instr->unaryop.output);
+        }
+    }
+    QML_V4_END_INSTR(ConvertStringToUrl, unaryop)
+
+    QML_V4_BEGIN_INSTR(ConvertUrlToBool, unaryop)
+    {
+        const Register &src = registers[instr->unaryop.src];
+        Register &output = registers[instr->unaryop.output];
+        // ### NaN
+        if (src.isUndefined()) {
+            output.setUndefined();
+        } else {
+            const QUrl tmp(*src.geturlptr());
+            if (instr->unaryop.src == instr->unaryop.output) {
+                output.cleanupUrl();
+                MARK_CLEAN_REGISTER(instr->unaryop.output);
+            }
+            output.setbool(!tmp.isEmpty());
+        }
+    }
+    QML_V4_END_INSTR(ConvertUrlToBool, unaryop)
+
+    QML_V4_BEGIN_INSTR(ConvertUrlToString, unaryop)
+    {
+        const Register &src = registers[instr->unaryop.src];
+        Register &output = registers[instr->unaryop.output];
+        // ### NaN
+        if (src.isUndefined()) {
+            output.setUndefined();
+        } else {
+            const QUrl tmp(*src.geturlptr());
+            if (instr->unaryop.src == instr->unaryop.output) {
+                output.cleanupUrl();
+                MARK_CLEAN_REGISTER(instr->unaryop.output);
+            }
+            new (output.getstringptr()) QString(tmp.toString());
+            STRING_REGISTER(instr->unaryop.output);
+        }
+    }
+    QML_V4_END_INSTR(ConvertUrlToString, unaryop)
+
+    QML_V4_BEGIN_INSTR(ResolveUrl, unaryop)
+    {
+        const Register &src = registers[instr->unaryop.src];
+        Register &output = registers[instr->unaryop.output];
+        if (src.isUndefined()) {
+            output.setUndefined();
+        } else {
+            const QUrl tmp(*src.geturlptr());
+            if (instr->unaryop.src == instr->unaryop.output) {
+                *output.geturlptr() = context->resolvedUrl(tmp);
+            } else {
+                new (output.geturlptr()) QUrl(context->resolvedUrl(tmp));
+                URL_REGISTER(instr->unaryop.output);
+            }
+        }
+    }
+    QML_V4_END_INSTR(ResolveUrl, unaryop)
+
     QML_V4_BEGIN_INSTR(MathSinReal, unaryop)
     {
         const Register &src = registers[instr->unaryop.src];