diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2014-04-26 14:42:39 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-04-28 12:50:17 +0200 |
commit | 68a662a2e15b790080ea12c2434f6e1fe60bda1b (patch) | |
tree | 2ac79cccf047e4ed5f61f06f9a3823715975daa1 | |
parent | da4f5504822189a7efd279d2380e0737f9de3968 (diff) |
Fix translations in states causing failing assertions
This is a smaller fix suitable for the release branch, merely adding support
for translations to the bytearray compilation step for states and ensuring a
consistent error message when qsTr is used in list models.
The proper fix will be done in dev that eliminates the entire intermediate
QByteArray storage for custom compilers.
Task-number: QTBUG-38492
Change-Id: If5171f16eb742c718e48b8bbcb265b0c241cd5e7
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
-rw-r--r-- | src/qml/types/qqmllistmodel.cpp | 4 | ||||
-rw-r--r-- | src/quick/util/qquickpropertychanges.cpp | 37 | ||||
-rw-r--r-- | tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp | 50 | ||||
-rw-r--r-- | tests/auto/quick/qquickstates/data/QTBUG-38492.qml | 16 | ||||
-rw-r--r-- | tests/auto/quick/qquickstates/tst_qquickstates.cpp | 16 |
5 files changed, 111 insertions, 12 deletions
diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp index 8eab51a99f..0056276d52 100644 --- a/src/qml/types/qqmllistmodel.cpp +++ b/src/qml/types/qqmllistmodel.cpp @@ -2325,6 +2325,10 @@ bool QQmlListModelParser::compileProperty(const QV4::CompiledData::QmlUnit *qmlU } else if (binding->type == QV4::CompiledData::Binding::Type_Boolean) { d += char(Boolean); d += char(binding->valueAsBoolean()); + } else if (binding->type == QV4::CompiledData::Binding::Type_Translation + || binding->type == QV4::CompiledData::Binding::Type_TranslationById) { + error(binding, QQmlListModel::tr("ListElement: cannot use script for property value")); + return false; } else if (binding->type == QV4::CompiledData::Binding::Type_Script) { QString scriptStr = binding->valueAsScriptString(&qmlUnit->header); if (definesEmptyList(scriptStr)) { diff --git a/src/quick/util/qquickpropertychanges.cpp b/src/quick/util/qquickpropertychanges.cpp index 188b91b15e..1786317356 100644 --- a/src/quick/util/qquickpropertychanges.cpp +++ b/src/quick/util/qquickpropertychanges.cpp @@ -272,12 +272,11 @@ QByteArray QQuickPropertyChangesParser::compile(const QV4::CompiledData::QmlUnit ds << data.count(); for (int ii = 0; ii < data.count(); ++ii) { const QV4::CompiledData::Binding *binding = data.at(ii).second; + ds << data.at(ii).first << int(binding->type); QVariant var; - bool isScript = binding->type == QV4::CompiledData::Binding::Type_Script; - QQmlBinding::Identifier id = QQmlBinding::Invalid; switch (binding->type) { case QV4::CompiledData::Binding::Type_Script: - id = bindingIdentifier(binding); + ds << bindingIdentifier(binding); // Fall through as we also need the expression string. // Signal handlers still need to be constructed by string ;( case QV4::CompiledData::Binding::Type_String: @@ -291,13 +290,12 @@ QByteArray QQuickPropertyChangesParser::compile(const QV4::CompiledData::QmlUnit break; case QV4::CompiledData::Binding::Type_Translation: case QV4::CompiledData::Binding::Type_TranslationById: - Q_UNREACHABLE(); + ds << binding->value.translationData.commentIndex << binding->value.translationData.number; + var = binding->stringIndex; default: break; } - ds << data.at(ii).first << isScript << var; - if (isScript) - ds << id; + ds << var; } return rv; @@ -315,14 +313,21 @@ void QQuickPropertyChangesPrivate::decode() ds >> count; for (int ii = 0; ii < count; ++ii) { QString name; - bool isScript; + int type; QVariant data; QQmlBinding::Identifier id = QQmlBinding::Invalid; + QV4::CompiledData::TranslationData tsd; ds >> name; - ds >> isScript; - ds >> data; - if (isScript) + ds >> type; + + if (type == QV4::CompiledData::Binding::Type_Script) { ds >> id; + } else if (type == QV4::CompiledData::Binding::Type_Translation + || type == QV4::CompiledData::Binding::Type_TranslationById) { + ds >> tsd.commentIndex >> tsd.number; + } + + ds >> data; QQmlProperty prop = property(name); //### better way to check for signal property? if (prop.type() & QQmlProperty::SignalProperty) { @@ -331,7 +336,7 @@ void QQuickPropertyChangesPrivate::decode() handler->expression.take(new QQmlBoundSignalExpression(object, QQmlPropertyPrivate::get(prop)->signalIndex(), QQmlContextData::get(qmlContext(q)), object, cdata->functionForBindingId(id))); signalReplacements << handler; - } else if (isScript) { // binding + } else if (type == QV4::CompiledData::Binding::Type_Script) { // binding QString expression = data.toString(); QUrl url = QUrl(); int line = -1; @@ -346,6 +351,14 @@ void QQuickPropertyChangesPrivate::decode() expressions << ExpressionChange(name, id, expression, url, line, column); } else { + if (type == QV4::CompiledData::Binding::Type_Translation + || type == QV4::CompiledData::Binding::Type_TranslationById) { + QV4::CompiledData::Binding tmpBinding; + tmpBinding.type = type; + tmpBinding.stringIndex = data.toInt(); + tmpBinding.value.translationData = tsd; + data = tmpBinding.valueAsString(&cdata->qmlUnit->header); + } properties << qMakePair(name, data); } } diff --git a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp index 678849c371..9b57eeffa9 100644 --- a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp +++ b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp @@ -101,6 +101,8 @@ private slots: void static_types_data(); void static_i18n(); void static_i18n_data(); + void dynamic_i18n(); + void dynamic_i18n_data(); void static_nestedElements(); void static_nestedElements_data(); void dynamic_data(); @@ -341,6 +343,54 @@ void tst_qqmllistmodel::static_i18n() delete obj; } +void tst_qqmllistmodel::dynamic_i18n_data() +{ + QTest::addColumn<QString>("qml"); + QTest::addColumn<QVariant>("value"); + QTest::addColumn<QString>("error"); + + QTest::newRow("qsTr") + << QString::fromUtf8("ListElement { foo: qsTr(\"test\") }") + << QVariant(QString::fromUtf8("test")) + << QString("ListElement: cannot use script for property value"); + + QTest::newRow("qsTrId") + << "ListElement { foo: qsTrId(\"qtn_test\") }" + << QVariant(QString("qtn_test")) + << QString("ListElement: cannot use script for property value"); +} + +void tst_qqmllistmodel::dynamic_i18n() +{ + QFETCH(QString, qml); + QFETCH(QVariant, value); + QFETCH(QString, error); + + qml = "import QtQuick 2.0\nItem { property variant test: model.get(0).foo; ListModel { id: model; " + qml + " } }"; + + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData(qml.toUtf8(), + QUrl::fromLocalFile(QString("dummy.qml"))); + + if (!error.isEmpty()) { + QVERIFY(component.isError()); + QCOMPARE(component.errors().at(0).description(), error); + return; + } + + QVERIFY(!component.isError()); + + QObject *obj = component.create(); + QVERIFY(obj != 0); + + QVariant actual = obj->property("test"); + + QCOMPARE(actual, value); + QCOMPARE(actual.toString(), value.toString()); + + delete obj; +} void tst_qqmllistmodel::static_nestedElements() { QFETCH(int, elementCount); diff --git a/tests/auto/quick/qquickstates/data/QTBUG-38492.qml b/tests/auto/quick/qquickstates/data/QTBUG-38492.qml new file mode 100644 index 0000000000..d6d6d81fd3 --- /dev/null +++ b/tests/auto/quick/qquickstates/data/QTBUG-38492.qml @@ -0,0 +1,16 @@ +import QtQuick 2.0 + +Item { + id: root + property string text; + + states: [ + State { + name: 'apply' + PropertyChanges { + target: root + text: qsTr("Test") + } + } + ] +} diff --git a/tests/auto/quick/qquickstates/tst_qquickstates.cpp b/tests/auto/quick/qquickstates/tst_qquickstates.cpp index 0c9b75636f..6b46ab1fae 100644 --- a/tests/auto/quick/qquickstates/tst_qquickstates.cpp +++ b/tests/auto/quick/qquickstates/tst_qquickstates.cpp @@ -148,6 +148,7 @@ private slots: void QTBUG_14830(); void avoidFastForward(); void revertListBug(); + void QTBUG_38492(); }; void tst_qquickstates::initTestCase() @@ -1626,6 +1627,21 @@ void tst_qquickstates::revertListBug() QCOMPARE(rect2->parentItem(), origParent2); //QTBUG-22583 causes rect2's parent item to be origParent1 } +void tst_qquickstates::QTBUG_38492() +{ + QQmlEngine engine; + + QQmlComponent rectComponent(&engine, testFileUrl("QTBUG-38492.qml")); + QQuickItem *item = qobject_cast<QQuickItem*>(rectComponent.create()); + QVERIFY(item != 0); + + QQuickItemPrivate::get(item)->setState("apply"); + + QCOMPARE(item->property("text").toString(), QString("Test")); + + delete item; +} + QTEST_MAIN(tst_qquickstates) #include "tst_qquickstates.moc" |