aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Shaw <andy.shaw@qt.io>2020-02-28 11:04:36 +0100
committerAndy Shaw <andy.shaw@qt.io>2020-02-28 15:28:23 +0100
commitd4748c7c936cdf603e0b72bfdb4e39f822ab2e9d (patch)
treea22d2290f4929fd0c8e14d6eb314ff7dd514bf84
parent83fdcbf3be0ddbbee1fd2c8c9ff1a4e3c707e3f0 (diff)
TableModel: Allow a double to be added to a field seen as int previously
Since the type for a TableModelColumn can be seen as an int when it is in the first row, it is still possible that it is representing a double value in other rows. Therefore it should be allowed to add/change a row that would display a double for that column. Change-Id: I994a8ead595f836a20a4e82fbf94953b1aa4b7da Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
-rw-r--r--src/qmlmodels/qqmltablemodel.cpp21
-rw-r--r--tests/auto/qml/qqmltablemodel/data/intAndDouble.qml86
-rw-r--r--tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp71
3 files changed, 174 insertions, 4 deletions
diff --git a/src/qmlmodels/qqmltablemodel.cpp b/src/qmlmodels/qqmltablemodel.cpp
index f190ad86b1..fab20f7410 100644
--- a/src/qmlmodels/qqmltablemodel.cpp
+++ b/src/qmlmodels/qqmltablemodel.cpp
@@ -1028,11 +1028,24 @@ bool QQmlTableModel::validateNewRow(const char *functionName, const QVariant &ro
}
const QVariant rolePropertyValue = rowAsMap.value(roleData.name);
+
if (rolePropertyValue.type() != roleData.type) {
- qmlWarning(this).quote() << functionName << ": expected the property named "
- << roleData.name << " to be of type " << roleData.typeName
- << ", but got " << QString::fromLatin1(rolePropertyValue.typeName()) << " instead";
- return false;
+ if (!rolePropertyValue.canConvert(int(roleData.type))) {
+ qmlWarning(this).quote() << functionName << ": expected the property named "
+ << roleData.name << " to be of type " << roleData.typeName
+ << ", but got " << QString::fromLatin1(rolePropertyValue.typeName())
+ << " instead";
+ return false;
+ }
+
+ QVariant effectiveValue = rolePropertyValue;
+ if (!effectiveValue.convert(int(roleData.type))) {
+ qmlWarning(this).nospace() << functionName << ": failed converting value "
+ << rolePropertyValue << " set at column " << columnIndex << " with role "
+ << QString::fromLatin1(rolePropertyValue.typeName()) << " to "
+ << roleData.typeName;
+ return false;
+ }
}
}
}
diff --git a/tests/auto/qml/qqmltablemodel/data/intAndDouble.qml b/tests/auto/qml/qqmltablemodel/data/intAndDouble.qml
new file mode 100644
index 0000000000..261bc8a115
--- /dev/null
+++ b/tests/auto/qml/qqmltablemodel/data/intAndDouble.qml
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import Qt.labs.qmlmodels 1.0
+
+Item {
+ id: root
+ width: 200
+ height: 200
+
+ property alias testModel: testModel
+ property alias tableView: tableView
+
+ function appendBanana() {
+ testModel.appendRow({
+ fruit: "Banana",
+ price: 3.5
+ })
+ }
+
+ function appendStrawberry() {
+ testModel.appendRow({
+ fruit: "Strawberry",
+ price: "5"
+ })
+ }
+
+ function appendInvalid() {
+ testModel.appendRow({
+ fruit: "Pear",
+ price: "Invalid"
+ })
+ }
+
+ TableModel {
+ id: testModel
+ objectName: "testModel"
+
+ TableModelColumn { display: "fruit" }
+ TableModelColumn { display: "price" }
+ rows: [
+ {
+ fruit: "Apple",
+ price: 1
+ },
+ {
+ fruit: "Orange",
+ price: 2
+ }
+ ]
+ }
+ TableView {
+ id: tableView
+ anchors.fill: parent
+ model: testModel
+ delegate: Text {
+ text: model.display
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp b/tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp
index d913bcdf9a..321896a8f3 100644
--- a/tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp
+++ b/tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp
@@ -59,6 +59,7 @@ private slots:
void dataAndEditing();
void omitTableModelColumnIndex();
void complexRow();
+ void appendRowWithDouble();
};
void tst_QQmlTableModel::appendRemoveRow()
@@ -975,6 +976,76 @@ void tst_QQmlTableModel::complexRow()
QCOMPARE(model->data(model->index(1, 1, QModelIndex()), roleNames.key("display")).toInt(), 33);
}
+void tst_QQmlTableModel::appendRowWithDouble()
+{
+ QQuickView view(testFileUrl("intAndDouble.qml"));
+ QCOMPARE(view.status(), QQuickView::Ready);
+ view.show();
+ QVERIFY(QTest::qWaitForWindowActive(&view));
+
+ QQmlTableModel *model = view.rootObject()->property("testModel").value<QQmlTableModel*>();
+ QVERIFY(model);
+ QCOMPARE(model->rowCount(), 2);
+ QCOMPARE(model->columnCount(), 2);
+
+ QSignalSpy columnCountSpy(model, SIGNAL(columnCountChanged()));
+ QVERIFY(columnCountSpy.isValid());
+
+ QSignalSpy rowCountSpy(model, SIGNAL(rowCountChanged()));
+ QVERIFY(rowCountSpy.isValid());
+
+ QQuickTableView *tableView = view.rootObject()->property("tableView").value<QQuickTableView*>();
+ QVERIFY(tableView);
+ QCOMPARE(tableView->rows(), 2);
+ QCOMPARE(tableView->columns(), 2);
+
+ QVERIFY(QMetaObject::invokeMethod(view.rootObject(), "appendBanana"));
+ QCOMPARE(model->rowCount(), 3);
+ QCOMPARE(model->columnCount(), 2);
+ const QHash<int, QByteArray> roleNames = model->roleNames();
+ const int roleKey = roleNames.key("display");
+ QCOMPARE(model->data(model->index(0, 1, QModelIndex()), roleKey).toString(),
+ QLatin1String("1"));
+ QCOMPARE(model->data(model->index(2, 0, QModelIndex()), roleKey).toString(),
+ QLatin1String("Banana"));
+ QCOMPARE(model->data(model->index(2, 1, QModelIndex()), roleKey).toDouble(), 3.5);
+ QCOMPARE(model->data(model->index(2, 1, QModelIndex()), roleKey).toString(),
+ QLatin1String("3.5"));
+ QCOMPARE(columnCountSpy.count(), 0);
+ QCOMPARE(rowCountSpy.count(), 1);
+ QTRY_COMPARE(tableView->rows(), 3);
+ QCOMPARE(tableView->columns(), 2);
+
+ rowCountSpy.clear();
+
+ QVERIFY(QMetaObject::invokeMethod(view.rootObject(), "appendStrawberry"));
+ QCOMPARE(model->rowCount(), 4);
+ QCOMPARE(model->columnCount(), 2);
+ QCOMPARE(model->data(model->index(3, 0, QModelIndex()), roleKey).toString(),
+ QLatin1String("Strawberry"));
+ QCOMPARE(model->data(model->index(3, 1, QModelIndex()), roleKey).toDouble(), 5);
+ QCOMPARE(model->data(model->index(3, 1, QModelIndex()), roleKey).toString(),
+ QLatin1String("5"));
+ QCOMPARE(columnCountSpy.count(), 0);
+ QCOMPARE(rowCountSpy.count(), 1);
+ QTRY_COMPARE(tableView->rows(), 4);
+ QCOMPARE(tableView->columns(), 2);
+
+ rowCountSpy.clear();
+ QTest::ignoreMessage(QtWarningMsg,
+ QRegularExpression(".*appendRow\\(\\): failed converting value "
+ "QVariant\\(QString, \"Invalid\"\\) set at column 1 with "
+ "role \"QString\" to \"int\""));
+ QVERIFY(QMetaObject::invokeMethod(view.rootObject(), "appendInvalid"));
+ // Nothing should change
+ QCOMPARE(model->rowCount(), 4);
+ QCOMPARE(model->columnCount(), 2);
+ QCOMPARE(columnCountSpy.count(), 0);
+ QCOMPARE(rowCountSpy.count(), 0);
+ QCOMPARE(tableView->rows(), 4);
+ QCOMPARE(tableView->columns(), 2);
+}
+
QTEST_MAIN(tst_QQmlTableModel)
#include "tst_qqmltablemodel.moc"