aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Adams <christopher.adams@nokia.com>2011-12-15 12:01:39 +1000
committerQt by Nokia <qt-info@nokia.com>2011-12-19 01:13:53 +0100
commit8460eae44c241d5975b3041eedf6e08c9638fd41 (patch)
tree0e342e789966b86b2d320ecccee22477192ccfc0
parent6859056a0924b3da52b045aa14a34fae59a5c75e (diff)
Correctly resolve elements of QList<QUrl> properties
Previously, the value of a QList<QUrl> sequence was only resolved if there was only one element in the sequence. This commit ensures that all elements in the sequence are resolved correctly. Task-number: QTBUG-23131 Change-Id: Id27748853fe01ae22800fbd02d062e268ad7ec70 Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
-rw-r--r--src/declarative/qml/qdeclarativeproperty.cpp65
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/data/assignSequenceTypes.7.qml42
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp19
3 files changed, 101 insertions, 25 deletions
diff --git a/src/declarative/qml/qdeclarativeproperty.cpp b/src/declarative/qml/qdeclarativeproperty.cpp
index 1e0b14ee02..9941342723 100644
--- a/src/declarative/qml/qdeclarativeproperty.cpp
+++ b/src/declarative/qml/qdeclarativeproperty.cpp
@@ -1052,6 +1052,39 @@ QVariant QDeclarativePropertyPrivate::readValueProperty()
}
}
+// helper function to allow assignment / binding to QList<QUrl> properties.
+static QVariant resolvedUrlSequence(const QVariant &value, QDeclarativeContextData *context)
+{
+ QList<QUrl> urls;
+ if (value.userType() == qMetaTypeId<QUrl>()) {
+ urls.append(value.toUrl());
+ } else if (value.userType() == qMetaTypeId<QString>()) {
+ urls.append(QUrl(value.toString()));
+ } else if (value.userType() == qMetaTypeId<QByteArray>()) {
+ urls.append(QUrl(QString::fromUtf8(value.toByteArray())));
+ } else if (value.userType() == qMetaTypeId<QList<QUrl> >()) {
+ urls = value.value<QList<QUrl> >();
+ } else if (value.userType() == qMetaTypeId<QStringList>()) {
+ QStringList urlStrings = value.value<QStringList>();
+ for (int i = 0; i < urlStrings.size(); ++i)
+ urls.append(QUrl(urlStrings.at(i)));
+ } else if (value.userType() == qMetaTypeId<QList<QString> >()) {
+ QList<QString> urlStrings = value.value<QList<QString> >();
+ for (int i = 0; i < urlStrings.size(); ++i)
+ urls.append(QUrl(urlStrings.at(i)));
+ } // note: QList<QByteArray> is not currently supported.
+
+ QList<QUrl> resolvedUrls;
+ for (int i = 0; i < urls.size(); ++i) {
+ QUrl u = urls.at(i);
+ if (context && u.isRelative() && !u.isEmpty())
+ u = context->resolvedUrl(u);
+ resolvedUrls.append(u);
+ }
+
+ return QVariant::fromValue<QList<QUrl> >(resolvedUrls);
+}
+
//writeEnumProperty MIRRORS the relelvant bit of QMetaProperty::write AND MUST BE KEPT IN SYNC!
bool QDeclarativePropertyPrivate::writeEnumProperty(const QMetaProperty &prop, int idx, QObject *object, const QVariant &value, int flags)
{
@@ -1194,6 +1227,11 @@ bool QDeclarativePropertyPrivate::write(QObject *object,
void *argv[] = { &u, 0, &status, &flags };
QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, argv);
+ } else if (propertyType == qMetaTypeId<QList<QUrl> >()) {
+ QList<QUrl> urlSeq = resolvedUrlSequence(value, context).value<QList<QUrl> >();
+ int status = -1;
+ void *argv[] = { &urlSeq, 0, &status, &flags };
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, argv);
} else if (variantType == propertyType) {
void *a[] = { (void *)value.constData(), 0, &status, &flags };
@@ -1299,6 +1337,7 @@ bool QDeclarativePropertyPrivate::write(QObject *object,
if (!ok) {
// the only other option is that they are assigning a single value
// to a sequence type property (eg, an int to a QList<int> property).
+ // Note that we've already handled single-value assignment to QList<QUrl> properties.
if (variantType == QVariant::Int && propertyType == qMetaTypeId<QList<int> >()) {
QList<int> list;
list << value.toInt();
@@ -1314,28 +1353,6 @@ bool QDeclarativePropertyPrivate::write(QObject *object,
list << value.toBool();
v = QVariant::fromValue<QList<bool> >(list);
ok = true;
- } else if ((variantType == QVariant::Url || variantType == QVariant::String || variantType == QVariant::ByteArray)
- && propertyType == qMetaTypeId<QList<QUrl> >()) {
- QUrl u;
- bool found = false;
- if (variantType == QVariant::Url) {
- u = value.toUrl();
- found = true;
- } else if (variantType == QVariant::ByteArray) {
- u = QUrl(QString::fromUtf8(value.toByteArray()));
- found = true;
- } else if (variantType == QVariant::String) {
- u = QUrl(value.toString());
- found = true;
- }
- if (!found)
- return false;
- if (context && u.isRelative() && !u.isEmpty())
- u = context->resolvedUrl(u);
- QList<QUrl> list;
- list << u;
- v = QVariant::fromValue<QList<QUrl> >(list);
- ok = true;
} else if (variantType == QVariant::String && propertyType == qMetaTypeId<QList<QString> >()) {
QList<QString> list;
list << value.toString();
@@ -1423,9 +1440,7 @@ bool QDeclarativePropertyPrivate::writeBinding(QObject *object,
} else if (result->IsNull() && core.isQObject()) {
value = QVariant::fromValue((QObject *)0);
} else if (core.propType == qMetaTypeId<QList<QUrl> >()) {
- value = v8engine->toVariant(result, qMetaTypeId<QList<QUrl> >());
- if (value.userType() == qMetaTypeId<QString>())
- value = QVariant(QUrl(value.toString()));
+ value = resolvedUrlSequence(v8engine->toVariant(result, qMetaTypeId<QList<QUrl> >()), context);
} else if (!isVmeProperty) {
value = v8engine->toVariant(result, type);
}
diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/assignSequenceTypes.7.qml b/tests/auto/declarative/qdeclarativeecmascript/data/assignSequenceTypes.7.qml
new file mode 100644
index 0000000000..96c0684939
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativeecmascript/data/assignSequenceTypes.7.qml
@@ -0,0 +1,42 @@
+import QtQuick 2.0
+import Qt.test 1.0
+
+Item {
+ // single url assignment to url list property
+ MySequenceConversionObject {
+ id: msco1
+ objectName: "msco1"
+ }
+
+ // single url binding to url list property
+ MySequenceConversionObject {
+ id: msco2
+ objectName: "msco2"
+ urlListProperty: "example.html"
+ }
+
+ // multiple url assignment to url list property
+ MySequenceConversionObject {
+ id: msco3
+ objectName: "msco3"
+ }
+
+ // multiple url binding to url list property
+ MySequenceConversionObject {
+ id: msco4
+ objectName: "msco4"
+ urlListProperty: [ "example.html", "example2.html" ]
+ }
+
+ // multiple url binding to url list property - already resolved
+ MySequenceConversionObject {
+ id: msco5
+ objectName: "msco5"
+ urlListProperty: [ Qt.resolvedUrl("example.html"), Qt.resolvedUrl("example2.html") ]
+ }
+
+ Component.onCompleted: {
+ msco1.urlListProperty = "example.html";
+ msco3.urlListProperty = [ "example.html", "example2.html" ];
+ }
+}
diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
index 10ae0ccd09..251b89dd87 100644
--- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
+++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
@@ -4709,6 +4709,25 @@ void tst_qdeclarativeecmascript::assignSequenceTypes()
QCOMPARE(object->urlListProperty(), (QList<QUrl>() << QUrl(TEST_FILE("example.html"))));
delete object;
}
+
+ // test QList<QUrl> literal assignment and binding assignment causes url resolution when required
+ {
+ QDeclarativeComponent component(&engine, TEST_FILE("assignSequenceTypes.7.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ MySequenceConversionObject *msco1 = object->findChild<MySequenceConversionObject *>(QLatin1String("msco1"));
+ MySequenceConversionObject *msco2 = object->findChild<MySequenceConversionObject *>(QLatin1String("msco2"));
+ MySequenceConversionObject *msco3 = object->findChild<MySequenceConversionObject *>(QLatin1String("msco3"));
+ MySequenceConversionObject *msco4 = object->findChild<MySequenceConversionObject *>(QLatin1String("msco4"));
+ MySequenceConversionObject *msco5 = object->findChild<MySequenceConversionObject *>(QLatin1String("msco5"));
+ QVERIFY(msco1 != 0 && msco2 != 0 && msco3 != 0 && msco4 != 0 && msco5 != 0);
+ QCOMPARE(msco1->urlListProperty(), (QList<QUrl>() << QUrl(TEST_FILE("example.html"))));
+ QCOMPARE(msco2->urlListProperty(), (QList<QUrl>() << QUrl(TEST_FILE("example.html"))));
+ QCOMPARE(msco3->urlListProperty(), (QList<QUrl>() << QUrl(TEST_FILE("example.html")) << QUrl(TEST_FILE("example2.html"))));
+ QCOMPARE(msco4->urlListProperty(), (QList<QUrl>() << QUrl(TEST_FILE("example.html")) << QUrl(TEST_FILE("example2.html"))));
+ QCOMPARE(msco5->urlListProperty(), (QList<QUrl>() << QUrl(TEST_FILE("example.html")) << QUrl(TEST_FILE("example2.html"))));
+ delete object;
+ }
}
// Test that assigning a null object works