aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/doc/snippets/qml/tablemodel/fruit-example-simpledelegate.qml1
-rw-r--r--src/qml/types/qqmltablemodel.cpp149
-rw-r--r--src/qml/types/qqmltablemodel_p.h19
-rw-r--r--tests/auto/qml/qqmltablemodel/data/TestModel.qml (renamed from tests/auto/qml/qqmltablemodel/data/defaultDisplayRoles.qml)42
-rw-r--r--tests/auto/qml/qqmltablemodel/data/TestUtils.js45
-rw-r--r--tests/auto/qml/qqmltablemodel/data/builtInRoles.qml47
-rw-r--r--tests/auto/qml/qqmltablemodel/data/common.qml18
-rw-r--r--tests/auto/qml/qqmltablemodel/data/empty.qml3
-rw-r--r--tests/auto/qml/qqmltablemodel/data/explicitDisplayRole.qml41
-rw-r--r--tests/auto/qml/qqmltablemodel/data/setDataThroughDelegate.qml32
-rw-r--r--tests/auto/qml/qqmltablemodel/data/setRowsMultipleTimes.qml18
-rw-r--r--tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp88
12 files changed, 317 insertions, 186 deletions
diff --git a/src/qml/doc/snippets/qml/tablemodel/fruit-example-simpledelegate.qml b/src/qml/doc/snippets/qml/tablemodel/fruit-example-simpledelegate.qml
index ae1f8d0b71..5f00eb484b 100644
--- a/src/qml/doc/snippets/qml/tablemodel/fruit-example-simpledelegate.qml
+++ b/src/qml/doc/snippets/qml/tablemodel/fruit-example-simpledelegate.qml
@@ -100,6 +100,7 @@ Window {
padding: 12
selectByMouse: true
+ // TODO: the property used here is undefined
onAccepted: model.display = text
Rectangle {
diff --git a/src/qml/types/qqmltablemodel.cpp b/src/qml/types/qqmltablemodel.cpp
index 0b1273a54b..c59a7584f7 100644
--- a/src/qml/types/qqmltablemodel.cpp
+++ b/src/qml/types/qqmltablemodel.cpp
@@ -119,6 +119,7 @@ static const QString displayRoleName = QStringLiteral("display");
QQmlTableModel::QQmlTableModel(QObject *parent)
: QAbstractTableModel(parent)
{
+ mRoleNames = QAbstractTableModel::roleNames();
}
QQmlTableModel::~QQmlTableModel()
@@ -167,6 +168,9 @@ void QQmlTableModel::setRows(const QVariant &rows)
}
if (mColumnCount > 0) {
+ qCDebug(lcTableModel) << "validating" << rowsAsVariantList.size()
+ << "rows against existing metadata";
+
// This is not the first time the rows have been set; validate the new columns.
for (int i = 0; i < rowsAsVariantList.size(); ++i) {
// validateNewRow() expects a QVariant wrapping a QJSValue, so to
@@ -178,95 +182,72 @@ void QQmlTableModel::setRows(const QVariant &rows)
}
}
- const bool resettingModel = mRowCount != rowsAsVariantList.size();
const int oldRowCount = mRowCount;
const int oldColumnCount = mColumnCount;
- if (resettingModel)
- beginResetModel();
+
+ beginResetModel();
// We don't clear the column or role data, because a TableModel should not be reused in that way.
// Once it has valid data, its columns and roles are fixed.
mRows = rowsAsVariantList;
mRowCount = mRows.size();
- if (mRowCount == 0) {
- // No elements.
- if (resettingModel)
- endResetModel();
-
- emit rowsChanged();
-
- if (mRowCount != oldRowCount)
- emit rowCountChanged();
- if (mColumnCount != oldColumnCount)
- emit columnCountChanged();
- return;
- }
-
- if (mColumnCount == 0) {
- // This is the first time the rows have been set, so establish the column count.
+ const bool isFirstTimeSet = mColumnCount == 0;
+ if (isFirstTimeSet && mRowCount > 0) {
+ // This is the first time the rows have been set, so establish
+ // the column count and gather column metadata.
mColumnCount = firstRow.size();
- }
+ qCDebug(lcTableModel) << "gathering metadata for" << mColumnCount << "columns from first row:";
- bool explicitDisplayRoleIndex = false;
-
- if (mRowCount > 0) {
// Go through each property of each cell in the first row
// and make a role name from it.
- int roleKey = Qt::UserRole;
+ int userRoleKey = Qt::UserRole;
for (int columnIndex = 0; columnIndex < mColumnCount; ++columnIndex) {
// We need it as a QVariantMap because we need to get
// the name of the property, which we can't do with QJSValue's API.
const QVariantMap column = firstRow.at(columnIndex).toMap();
const QStringList columnPropertyNames = column.keys();
+ ColumnProperties properties;
+ int propertyInfoIndex = 0;
+
+ qCDebug(lcTableModel).nospace() << "- column " << columnIndex << ":";
- const int firstRoleForColumn = roleKey;
- QVector<ColumnPropertyInfo> properties;
for (const QString &roleName : columnPropertyNames) {
// QML/JS supports utf8.
- mRoleNames[roleKey] = roleName.toUtf8().constData();
-
- if (!explicitDisplayRoleIndex && roleName == displayRoleName) {
- explicitDisplayRoleIndex = true;
- // The user explicitly declared a "display" role, so now they're on their own.
- mDefaultDisplayRoles.clear();
-
- qCDebug(lcTableModel).nospace() << "explicit \"display\" role found; "
- << "clearing default display roles";
+ const QByteArray roleNameUtf8 = roleName.toUtf8();
+ if (!mRoleNames.values().contains(roleNameUtf8)) {
+ // We don't already have this role name, so it's a user role.
+ mRoleNames[userRoleKey] = roleName.toUtf8().constData();
+ qCDebug(lcTableModel) << " - added new user role" << roleName << "with key" << userRoleKey;
+ ++userRoleKey;
+ } else {
+ qCDebug(lcTableModel) << " - found existing role" << roleName;
}
- qCDebug(lcTableModel).nospace() << "added role "
- << roleName << " with key " << roleKey << " found in column " << columnIndex;
+ if (properties.explicitDisplayRoleIndex == -1 && roleName == displayRoleName) {
+ // The user explicitly declared a "display" role,
+ // so now we don't need to make it the first role in the column for them.
+ properties.explicitDisplayRoleIndex = propertyInfoIndex;
+ }
+ // Keep track of the type of property so we can use it to validate new rows later on.
const QVariant roleValue = column.value(roleName);
- properties.append(ColumnPropertyInfo(roleName, roleValue.type(), QString::fromLatin1(roleValue.typeName())));
-
- ++roleKey;
- }
+ const auto propertyInfo = ColumnPropertyInfo(roleName, roleValue.type(),
+ QString::fromLatin1(roleValue.typeName()));
+ properties.infoForProperties.append(propertyInfo);
- mColumnProperties.append(properties);
+ qCDebug(lcTableModel) << " - column property" << propertyInfo.name
+ << "has type" << propertyInfo.typeName;
- if (!explicitDisplayRoleIndex) {
- // The "display" role wasn't specified for this column,
- // so we use the first role that was declared for that column.
- // TODO: make it possible to specify the display role?
- // e.g. { myRoleName: 123, displayRole: "myRoleName" }
- mDefaultDisplayRoles[columnIndex] = firstRoleForColumn;
-
- qCDebug(lcTableModel).nospace() << "added implicit \"display\" role with key "
- << int(Qt::DisplayRole) << " for column " << columnIndex
- << " which will display values from the " << mRoleNames.value(firstRoleForColumn) << " role";
+ ++propertyInfoIndex;
}
- }
- if (!explicitDisplayRoleIndex) {
- // There was no "display" role declared by the user, so we can provide one for them.
- mRoleNames[Qt::DisplayRole] = displayRoleName.toUtf8().constData();
+ mColumnProperties.append(properties);
}
-
- endResetModel();
}
+ endResetModel();
+
emit rowsChanged();
if (mRowCount != oldRowCount)
@@ -504,8 +485,8 @@ void QQmlTableModel::removeRow(int rowIndex, int rows)
endRemoveRows();
emit rowCountChanged();
- qCDebug(lcTableModel).nospace() << "removed" << rows
- << "items from the model, starting at index" << rowIndex;
+ qCDebug(lcTableModel).nospace() << "removed " << rows
+ << " items from the model, starting at index " << rowIndex;
}
/*!
@@ -678,7 +659,7 @@ QVariant QQmlTableModel::data(const QModelIndex &index, int role) const
if (column < 0 || column >= columnCount())
return QVariant();
- if ((role < Qt::UserRole || role >= Qt::UserRole + mRoleNames.size()) && role != Qt::DisplayRole)
+ if (!mRoleNames.contains(role))
return QVariant();
const QVariantList rowData = mRows.at(row).toList();
@@ -692,18 +673,11 @@ QVariant QQmlTableModel::data(const QModelIndex &index, int role) const
return const_cast<QQmlTableModel*>(this)->mRoleDataProvider.call(args).toVariant();
}
+ // TODO: should we also allow this code to be executed if roleDataProvider doesn't
+ // handle the role/column, so that it only has to handle the case where there is
+ // more than one role in a column?
const QVariantMap columnData = rowData.at(column).toMap();
-
- int effectiveRole = role;
- if (role == Qt::DisplayRole) {
- // If the execution got to this point, then the user is requesting data for the display role,
- // but didn't specify any role with the name "display".
- // So, we give them the data of the implicit display role.
- Q_ASSERT(mDefaultDisplayRoles.contains(column));
- effectiveRole = mDefaultDisplayRoles.value(column);
- }
-
- const QString propertyName = QString::fromUtf8(roleNames().value(effectiveRole));
+ const QString propertyName = columnPropertyNameFromRole(column, role);
const QVariant value = columnData.value(propertyName);
return value;
}
@@ -734,17 +708,11 @@ bool QQmlTableModel::setData(const QModelIndex &index, const QVariant &value, in
if (column < 0 || column >= columnCount())
return false;
- if ((role < Qt::UserRole || role >= Qt::UserRole + mRoleNames.size()) && role != Qt::DisplayRole)
+ if (!mRoleNames.contains(role))
return false;
- int effectiveRole = role;
- if (role == Qt::DisplayRole) {
- Q_ASSERT(mDefaultDisplayRoles.contains(column));
- effectiveRole = mDefaultDisplayRoles.value(column);
- }
-
const QVariantList rowData = mRows.at(row).toList();
- const QString propertyName = QString::fromUtf8(roleNames().value(effectiveRole));
+ const QString propertyName = columnPropertyNameFromRole(column, role);
qCDebug(lcTableModel).nospace() << "setData() called with index "
<< index << ", value " << value << " and role " << propertyName;
@@ -757,7 +725,7 @@ bool QQmlTableModel::setData(const QModelIndex &index, const QVariant &value, in
stream.nospace() << "setData(): no role named " << propertyName
<< " at column index " << column << ". The available roles for that column are:\n";
- const QVector<ColumnPropertyInfo> availableProperties = mColumnProperties.at(column);
+ const QVector<ColumnPropertyInfo> availableProperties = mColumnProperties.at(column).infoForProperties;
for (auto propertyInfo : availableProperties)
stream << " - " << propertyInfo.name << " (" << qPrintable(propertyInfo.typeName) << ")";
@@ -909,7 +877,7 @@ bool QQmlTableModel::validateColumnPropertyTypes(const char *functionName,
const QVariantList columnProperties = column.values();
const QStringList propertyNames = column.keys();
// Expected
- const QVector<ColumnPropertyInfo> properties = mColumnProperties.at(columnIndex);
+ const QVector<ColumnPropertyInfo> properties = mColumnProperties.at(columnIndex).infoForProperties;
// This iterates across the properties in the column. For example:
// 0 1 2
@@ -955,7 +923,7 @@ QQmlTableModel::ColumnPropertyInfo QQmlTableModel::findColumnPropertyInfo(
{
// TODO: check if a hash with its string-based lookup is faster,
// keeping in mind that we may be doing index-based lookups too.
- const QVector<ColumnPropertyInfo> properties = mColumnProperties.at(columnIndex);
+ const QVector<ColumnPropertyInfo> properties = mColumnProperties.at(columnIndex).infoForProperties;
for (int i = 0; i < properties.size(); ++i) {
const ColumnPropertyInfo &info = properties.at(i);
if (info.name == columnPropertyName)
@@ -965,4 +933,19 @@ QQmlTableModel::ColumnPropertyInfo QQmlTableModel::findColumnPropertyInfo(
return ColumnPropertyInfo();
}
+QString QQmlTableModel::columnPropertyNameFromRole(int columnIndex, int role) const
+{
+ QString propertyName;
+ if (role == Qt::DisplayRole && mColumnProperties.at(columnIndex).explicitDisplayRoleIndex == -1) {
+ // The user is getting or setting data for the display role,
+ // but didn't specify any role with the name "display" in this column.
+ // So, we give them the implicit display role, aka the first property we find.
+ propertyName = mColumnProperties.at(columnIndex).infoForProperties.first().name;
+ } else {
+ // QML/JS supports utf8.
+ propertyName = QString::fromUtf8(mRoleNames.value(role));
+ }
+ return propertyName;
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/types/qqmltablemodel_p.h b/src/qml/types/qqmltablemodel_p.h
index 3bbaff4183..33b2189fcd 100644
--- a/src/qml/types/qqmltablemodel_p.h
+++ b/src/qml/types/qqmltablemodel_p.h
@@ -114,6 +114,14 @@ private:
QString typeName;
};
+ struct ColumnProperties
+ {
+ QVector<ColumnPropertyInfo> infoForProperties;
+ // If there was a display role found in this column, it'll be stored here.
+ // The index is into infoForProperties.
+ int explicitDisplayRoleIndex = -1;
+ };
+
enum NewRowOperationFlag {
OtherOperation, // insert(), set(), etc.
AppendOperation
@@ -127,22 +135,19 @@ private:
bool validateColumnPropertyType(const char *functionName, const QString &propertyName,
const QVariant &propertyValue, const ColumnPropertyInfo &expectedPropertyFormat, int columnIndex) const;
- ColumnPropertyInfo findColumnPropertyInfo(int columnIndex, const QString &columnPropertyName) const;
+ ColumnPropertyInfo findColumnPropertyInfo(int columnIndex, const QString &columnPropertyNameFromRole) const;
+ QString columnPropertyNameFromRole(int columnIndex, int role) const;
void doInsert(int rowIndex, const QVariant &row);
QVariantList mRows;
int mRowCount = 0;
int mColumnCount = 0;
- QVector<QVector<ColumnPropertyInfo>> mColumnProperties;
+ // Each entry contains information about the properties of the column at that index.
+ QVector<ColumnProperties> mColumnProperties;
// key = property index (0 to number of properties across all columns)
// value = role name
QHash<int, QByteArray> mRoleNames;
- // Contains the role key to be used as the display role for each column
- // when "display" isn't explicitly specified.
- // key = column index
- // value = index (key) into mRoleNames
- QHash<int, int> mDefaultDisplayRoles;
QJSValue mRoleDataProvider;
};
diff --git a/tests/auto/qml/qqmltablemodel/data/defaultDisplayRoles.qml b/tests/auto/qml/qqmltablemodel/data/TestModel.qml
index 32daea61f9..7aeb5d03f4 100644
--- a/tests/auto/qml/qqmltablemodel/data/defaultDisplayRoles.qml
+++ b/tests/auto/qml/qqmltablemodel/data/TestModel.qml
@@ -26,36 +26,22 @@
**
****************************************************************************/
-import QtQuick 2.12
import Qt.labs.qmlmodels 1.0
-Item {
- id: root
- width: 200
- height: 200
+import "TestUtils.js" as TestUtils
- property alias testModel: testModel
-
- TableModel {
- id: testModel
- objectName: "testModel"
- rows: [
- [
- { name: "John", someOtherRole1: "foo" }, // column 0
- { age: 22, someOtherRole2: "foo" } // column 1
- ],
- [
- { name: "Oliver", someOtherRole1: "foo" }, // column 0
- { age: 33, someOtherRole2: "foo" } // column 1
- ]
+TableModel {
+ id: testModel
+ objectName: "testModel"
+ roleDataProvider: TestUtils.testModelRoleDataProvider
+ rows: [
+ [
+ { name: "John" },
+ { age: 22 }
+ ],
+ [
+ { name: "Oliver" },
+ { age: 33 }
]
- }
- TableView {
- anchors.fill: parent
- model: testModel
- delegate: Text {
- id: textItem
- text: model.display
- }
- }
+ ]
}
diff --git a/tests/auto/qml/qqmltablemodel/data/TestUtils.js b/tests/auto/qml/qqmltablemodel/data/TestUtils.js
new file mode 100644
index 0000000000..0b92a377bb
--- /dev/null
+++ b/tests/auto/qml/qqmltablemodel/data/TestUtils.js
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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$
+**
+****************************************************************************/
+
+function testModelRoleDataProvider(index, role, cellData) {
+ switch (role) {
+ case "display":
+ switch (index.column) {
+ case 0:
+ return cellData.name
+ case 1:
+ return cellData.age
+ }
+ break
+ case "name":
+ return cellData.name
+ case "age":
+ return cellData.age
+ }
+ return cellData
+}
diff --git a/tests/auto/qml/qqmltablemodel/data/builtInRoles.qml b/tests/auto/qml/qqmltablemodel/data/builtInRoles.qml
new file mode 100644
index 0000000000..d9882e4dea
--- /dev/null
+++ b/tests/auto/qml/qqmltablemodel/data/builtInRoles.qml
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 Qt.labs.qmlmodels 1.0
+
+import "TestUtils.js" as TestUtils
+
+TableModel {
+ id: testModel
+ objectName: "testModel"
+ roleDataProvider: TestUtils.testModelRoleDataProvider
+ rows: [
+ [
+ { name: "John", someOtherRole1: "foo" }, // column 0
+ { age: 22, someOtherRole2: "foo" } // column 1
+ ],
+ [
+ { name: "Oliver", someOtherRole1: "foo" }, // column 0
+ { age: 33, someOtherRole2: "foo" } // column 1
+ ]
+ ]
+}
diff --git a/tests/auto/qml/qqmltablemodel/data/common.qml b/tests/auto/qml/qqmltablemodel/data/common.qml
index 2ae9c50a1b..aec796bd4f 100644
--- a/tests/auto/qml/qqmltablemodel/data/common.qml
+++ b/tests/auto/qml/qqmltablemodel/data/common.qml
@@ -115,24 +115,12 @@ Item {
])
}
- TableModel {
- id: testModel
- objectName: "testModel"
- rows: [
- [
- { name: "John" },
- { age: 22 }
- ],
- [
- { name: "Oliver" },
- { age: 33 }
- ]
- ]
- }
TableView {
id: tableView
anchors.fill: parent
- model: testModel
+ model: TestModel {
+ id: testModel
+ }
delegate: Text {
text: model.display
}
diff --git a/tests/auto/qml/qqmltablemodel/data/empty.qml b/tests/auto/qml/qqmltablemodel/data/empty.qml
index 57f2f992d9..6e66b99145 100644
--- a/tests/auto/qml/qqmltablemodel/data/empty.qml
+++ b/tests/auto/qml/qqmltablemodel/data/empty.qml
@@ -29,6 +29,8 @@
import QtQuick 2.12
import Qt.labs.qmlmodels 1.0
+import "TestUtils.js" as TestUtils
+
Item {
id: root
width: 200
@@ -53,6 +55,7 @@ Item {
TableModel {
id: testModel
objectName: "testModel"
+ roleDataProvider: TestUtils.testModelRoleDataProvider
}
TableView {
id: tableView
diff --git a/tests/auto/qml/qqmltablemodel/data/explicitDisplayRole.qml b/tests/auto/qml/qqmltablemodel/data/explicitDisplayRole.qml
new file mode 100644
index 0000000000..510a62e74b
--- /dev/null
+++ b/tests/auto/qml/qqmltablemodel/data/explicitDisplayRole.qml
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 Qt.labs.qmlmodels 1.0
+
+import "TestUtils.js" as TestUtils
+
+TableModel {
+ id: testModel
+ rows: [
+ [
+ { name: "John", display: "foo" },
+ { age: 22, display: "bar" }
+ ]
+ ]
+}
diff --git a/tests/auto/qml/qqmltablemodel/data/setDataThroughDelegate.qml b/tests/auto/qml/qqmltablemodel/data/setDataThroughDelegate.qml
index 7a419d81c6..5f849c3350 100644
--- a/tests/auto/qml/qqmltablemodel/data/setDataThroughDelegate.qml
+++ b/tests/auto/qml/qqmltablemodel/data/setDataThroughDelegate.qml
@@ -52,25 +52,27 @@ Item {
shouldModifyInvalidType()
}
- TableModel {
- id: testModel
- objectName: "testModel"
- rows: [
- [
- { name: "John" },
- { age: 22 }
- ],
- [
- { name: "Oliver" },
- { age: 33 }
- ]
- ]
- }
TableView {
anchors.fill: parent
- model: testModel
+ model: TableModel {
+ id: testModel
+ objectName: "testModel"
+ rows: [
+ [
+ { name: "John" },
+ { age: 22 }
+ ],
+ [
+ { name: "Oliver" },
+ { age: 33 }
+ ]
+ ]
+ }
+
delegate: Text {
id: textItem
+ // TODO: this is currently random when no roleDataProvider handles it
+ // we should allow roleDataProvider to be used to handle specific roles only
text: model.display
Connections {
diff --git a/tests/auto/qml/qqmltablemodel/data/setRowsMultipleTimes.qml b/tests/auto/qml/qqmltablemodel/data/setRowsMultipleTimes.qml
index 15d52f93a6..6aaf79f2d4 100644
--- a/tests/auto/qml/qqmltablemodel/data/setRowsMultipleTimes.qml
+++ b/tests/auto/qml/qqmltablemodel/data/setRowsMultipleTimes.qml
@@ -71,24 +71,12 @@ Item {
]
}
- TableModel {
- id: testModel
- objectName: "testModel"
- rows: [
- [
- { name: "John" },
- { age: 22 }
- ],
- [
- { name: "Oliver" },
- { age: 33 }
- ]
- ]
- }
TableView {
id: tableView
anchors.fill: parent
- model: testModel
+ model: TestModel {
+ id: 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 eb1fbda45a..059ce082d9 100644
--- a/tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp
+++ b/tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp
@@ -55,11 +55,15 @@ private slots:
void setDataThroughDelegate();
void setRowsImperatively();
void setRowsMultipleTimes();
- void defaultDisplayRoles();
+ void builtInRoles_data();
+ void builtInRoles();
+ void explicitDisplayRole();
void roleDataProvider();
void dataAndEditing();
};
+static const int builtInRoleCount = 6;
+
void tst_QQmlTableModel::appendRemoveRow()
{
QQuickView view(testFileUrl("common.qml"));
@@ -80,11 +84,15 @@ void tst_QQmlTableModel::appendRemoveRow()
int heightSignalEmissions = 0;
const QHash<int, QByteArray> roleNames = model->roleNames();
- QCOMPARE(roleNames.size(), 3);
+ QCOMPARE(roleNames.size(), 2 + builtInRoleCount);
QVERIFY(roleNames.values().contains("name"));
QVERIFY(roleNames.values().contains("age"));
QVERIFY(roleNames.values().contains("display"));
-
+ QVERIFY(roleNames.values().contains("decoration"));
+ QVERIFY(roleNames.values().contains("edit"));
+ QVERIFY(roleNames.values().contains("toolTip"));
+ QVERIFY(roleNames.values().contains("statusTip"));
+ QVERIFY(roleNames.values().contains("whatsThis"));
QCOMPARE(model->data(model->index(0, 0, QModelIndex()), roleNames.key("name")).toString(), QLatin1String("John"));
QCOMPARE(model->data(model->index(0, 1, QModelIndex()), roleNames.key("age")).toInt(), 22);
QCOMPARE(model->data(model->index(1, 0, QModelIndex()), roleNames.key("name")).toString(), QLatin1String("Oliver"));
@@ -208,10 +216,9 @@ void tst_QQmlTableModel::clear()
QVERIFY(rowCountSpy.isValid());
const QHash<int, QByteArray> roleNames = model->roleNames();
- QCOMPARE(roleNames.size(), 3);
QVERIFY(roleNames.values().contains("name"));
QVERIFY(roleNames.values().contains("age"));
- QVERIFY(roleNames.values().contains("display"));
+ QCOMPARE(roleNames.size(), 2 + builtInRoleCount);
QQuickTableView *tableView = view.rootObject()->property("tableView").value<QQuickTableView*>();
QVERIFY(tableView);
@@ -221,8 +228,8 @@ void tst_QQmlTableModel::clear()
QVERIFY(QMetaObject::invokeMethod(model, "clear"));
QCOMPARE(model->rowCount(), 0);
QCOMPARE(model->columnCount(), 2);
- QCOMPARE(model->data(model->index(0, 0, QModelIndex()), roleNames.key("name")), QVariant());
- QCOMPARE(model->data(model->index(0, 1, QModelIndex()), roleNames.key("age")), QVariant());
+ QCOMPARE(model->data(model->index(0, 0, QModelIndex()), roleNames.key("display")), QVariant());
+ QCOMPARE(model->data(model->index(0, 1, QModelIndex()), roleNames.key("display")), QVariant());
QCOMPARE(columnCountSpy.count(), 0);
QCOMPARE(rowCountSpy.count(), 1);
// Wait until updatePolish() gets called, which is where the size is recalculated.
@@ -690,10 +697,9 @@ void tst_QQmlTableModel::setDataThroughDelegate()
QVERIFY(rowCountSpy.isValid());
const QHash<int, QByteArray> roleNames = model->roleNames();
- QCOMPARE(roleNames.size(), 3);
+ QCOMPARE(roleNames.size(), 2 + builtInRoleCount);
QVERIFY(roleNames.values().contains("name"));
QVERIFY(roleNames.values().contains("age"));
- QVERIFY(roleNames.values().contains("display"));
QCOMPARE(model->data(model->index(0, 0, QModelIndex()), roleNames.key("name")).toString(), QLatin1String("John"));
QCOMPARE(model->data(model->index(0, 1, QModelIndex()), roleNames.key("age")).toInt(), 22);
QCOMPARE(model->data(model->index(1, 0, QModelIndex()), roleNames.key("name")).toString(), QLatin1String("Oliver"));
@@ -836,29 +842,65 @@ void tst_QQmlTableModel::setRowsMultipleTimes()
QCOMPARE(tableView->columns(), 2);
}
-void tst_QQmlTableModel::defaultDisplayRoles()
+void tst_QQmlTableModel::builtInRoles_data()
{
- QQuickView view(testFileUrl("defaultDisplayRoles.qml"));
- QCOMPARE(view.status(), QQuickView::Ready);
- view.show();
- QVERIFY(QTest::qWaitForWindowActive(&view));
+ QTest::addColumn<int>("row");
+ QTest::addColumn<int>("column");
+ QTest::addColumn<QByteArray>("roleName");
+ QTest::addColumn<QVariant>("expectedValue");
- QQmlTableModel *model = view.rootObject()->property("testModel").value<QQmlTableModel*>();
+ const QByteArray displayRole = "display";
+
+ QTest::addRow("display(0,0)") << 0 << 0 << displayRole << QVariant(QLatin1String("John"));
+ QTest::addRow("display(0,1)") << 0 << 1 << displayRole << QVariant(QLatin1String("22"));
+ QTest::addRow("display(1,0)") << 1 << 0 << displayRole << QVariant(QLatin1String("Oliver"));
+ QTest::addRow("display(1,1)") << 1 << 1 << displayRole << QVariant(QLatin1String("33"));
+}
+
+void tst_QQmlTableModel::builtInRoles()
+{
+ QFETCH(int, row);
+ QFETCH(int, column);
+ QFETCH(QByteArray, roleName);
+ QFETCH(QVariant, expectedValue);
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("builtInRoles.qml"));
+ QCOMPARE(component.status(), QQmlComponent::Ready);
+
+ QScopedPointer<QQmlTableModel> model(qobject_cast<QQmlTableModel*>(component.create()));
QVERIFY(model);
QCOMPARE(model->rowCount(), 2);
QCOMPARE(model->columnCount(), 2);
- QSignalSpy columnCountSpy(model, SIGNAL(columnCountChanged()));
- QVERIFY(columnCountSpy.isValid());
+ const QHash<int, QByteArray> roleNames = model->roleNames();
+ QCOMPARE(roleNames.size(), 4 + builtInRoleCount);
+ QVERIFY(roleNames.values().contains("display"));
+ QVERIFY(roleNames.values().contains("decoration"));
+ QVERIFY(roleNames.values().contains("edit"));
+ QVERIFY(roleNames.values().contains("toolTip"));
+ QVERIFY(roleNames.values().contains("statusTip"));
+ QVERIFY(roleNames.values().contains("whatsThis"));
+ QVERIFY(roleNames.values().contains("name"));
+ QVERIFY(roleNames.values().contains("age"));
+ QVERIFY(roleNames.values().contains("someOtherRole1"));
+ QVERIFY(roleNames.values().contains("someOtherRole2"));
+ QCOMPARE(model->data(model->index(row, column, QModelIndex()), roleNames.key(roleName)), expectedValue);
+}
- QSignalSpy rowCountSpy(model, SIGNAL(rowCountChanged()));
- QVERIFY(rowCountSpy.isValid());
+void tst_QQmlTableModel::explicitDisplayRole()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("explicitDisplayRole.qml"));
+ QCOMPARE(component.status(), QQmlComponent::Ready);
+ QScopedPointer<QQmlTableModel> model(qobject_cast<QQmlTableModel*>(component.create()));
+ QVERIFY(model);
+ QCOMPARE(model->rowCount(), 1);
+ QCOMPARE(model->columnCount(), 2);
const QHash<int, QByteArray> roleNames = model->roleNames();
- QCOMPARE(model->data(model->index(0, 0, QModelIndex()), roleNames.key("display")).toString(), QLatin1String("John"));
- QCOMPARE(model->data(model->index(0, 1, QModelIndex()), roleNames.key("display")).toInt(), 22);
- QCOMPARE(model->data(model->index(1, 0, QModelIndex()), roleNames.key("display")).toString(), QLatin1String("Oliver"));
- QCOMPARE(model->data(model->index(1, 1, QModelIndex()), roleNames.key("display")).toInt(), 33);
+ QCOMPARE(model->data(model->index(0, 0, QModelIndex()), roleNames.key("display")).toString(), QLatin1String("foo"));
+ QCOMPARE(model->data(model->index(0, 1, QModelIndex()), roleNames.key("display")).toString(), QLatin1String("bar"));
}
void tst_QQmlTableModel::roleDataProvider()