aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/doc/snippets/qml/tablemodel/roleDataProvider.qml83
-rw-r--r--src/qml/types/qqmltablemodel.cpp40
-rw-r--r--src/qml/types/qqmltablemodel_p.h6
-rw-r--r--tests/auto/qml/qqmltablemodel/data/roleDataProvider.qml65
-rw-r--r--tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp19
5 files changed, 213 insertions, 0 deletions
diff --git a/src/qml/doc/snippets/qml/tablemodel/roleDataProvider.qml b/src/qml/doc/snippets/qml/tablemodel/roleDataProvider.qml
new file mode 100644
index 0000000000..6c8ae3f1fc
--- /dev/null
+++ b/src/qml/doc/snippets/qml/tablemodel/roleDataProvider.qml
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//![0]
+import QtQuick 2.12
+import Qt.labs.qmlmodels 1.0
+
+TableView {
+ columnSpacing: 1; rowSpacing: 1
+ model: TableModel {
+ property real taxPercent: 10
+ rows: [
+ [{ fruitType: "Apple" }, { fruitPrice: 1.50 }],
+ [{ fruitType: "Orange" }, { fruitPrice: 2.50 }]
+ ]
+ roleDataProvider: function(row, column, role, cellData) {
+ if (role === "display") {
+ if (cellData.hasOwnProperty("fruitPrice")) {
+ console.log("taxing your fruit " + JSON.stringify(cellData))
+ return (cellData.fruitPrice * (1 + taxPercent / 100)).toFixed(2);
+ }
+ else if (cellData.hasOwnProperty("fruitType"))
+ return cellData.fruitType;
+ }
+ return cellData;
+ }
+ }
+ delegate: Rectangle {
+ implicitWidth: 150; implicitHeight: 30
+ color: "lightsteelblue"
+ Text {
+ x: 6; anchors.verticalCenter: parent.verticalCenter
+ text: display
+ }
+ }
+}
+//![0]
diff --git a/src/qml/types/qqmltablemodel.cpp b/src/qml/types/qqmltablemodel.cpp
index cf3fc0298a..9bf8c7f562 100644
--- a/src/qml/types/qqmltablemodel.cpp
+++ b/src/qml/types/qqmltablemodel.cpp
@@ -548,6 +548,38 @@ void QQmlTableModel::setRow(int rowIndex, const QVariant &row)
}
}
+/*!
+ \qmlproperty var TableModel::roleDataProvider
+
+ This property can hold a function that will map roles to values.
+
+ When assigned, it will be called each time data() is called, to enable
+ extracting arbitrary values, converting the data in arbitrary ways, or even
+ doing calculations. It takes 4 arguments: \c row, \c column, \c role (as a
+ string), and \c cellData, which is the complete data that is stored in the
+ given cell. (If the cell contains a JS object with multiple named values,
+ the entire object will be given in cellData.) The function that you define
+ must return the value to be used; for example a typical delegate will
+ display the value returned for the \c display role, so you can check
+ whether that is the role and return data in a form that is suitable for the
+ delegate to show:
+
+ \snippet qml/tablemodel/roleDataProvider.qml 0
+*/
+QJSValue QQmlTableModel::roleDataProvider() const
+{
+ return mRoleDataProvider;
+}
+
+void QQmlTableModel::setRoleDataProvider(QJSValue roleDataProvider)
+{
+ if (roleDataProvider.strictlyEquals(mRoleDataProvider))
+ return;
+
+ mRoleDataProvider = roleDataProvider;
+ emit roleDataProviderChanged();
+}
+
QModelIndex QQmlTableModel::index(int row, int column, const QModelIndex &parent) const
{
return row >= 0 && row < rowCount() && column >= 0 && column < columnCount() && !parent.isValid()
@@ -603,6 +635,14 @@ QVariant QQmlTableModel::data(const QModelIndex &index, int role) const
return QVariant();
const QVariantList rowData = mRows.at(row).toList();
+
+ if (mRoleDataProvider.isCallable()) {
+ const auto args = QJSValueList() << row << column <<
+ QString::fromUtf8(mRoleNames.value(role)) <<
+ qmlEngine(this)->toScriptValue(rowData.at(column));
+ return const_cast<QQmlTableModel*>(this)->mRoleDataProvider.call(args).toVariant();
+ }
+
const QVariantMap columnData = rowData.at(column).toMap();
int effectiveRole = role;
diff --git a/src/qml/types/qqmltablemodel_p.h b/src/qml/types/qqmltablemodel_p.h
index 8da930872d..863c592678 100644
--- a/src/qml/types/qqmltablemodel_p.h
+++ b/src/qml/types/qqmltablemodel_p.h
@@ -65,6 +65,7 @@ class Q_QML_PRIVATE_EXPORT QQmlTableModel : public QAbstractTableModel
Q_PROPERTY(int columnCount READ columnCount NOTIFY columnCountChanged FINAL)
Q_PROPERTY(int rowCount READ rowCount NOTIFY rowCountChanged FINAL)
Q_PROPERTY(QVariant rows READ rows WRITE setRows NOTIFY rowsChanged FINAL)
+ Q_PROPERTY(QJSValue roleDataProvider READ roleDataProvider WRITE setRoleDataProvider NOTIFY roleDataProviderChanged)
public:
QQmlTableModel(QObject *parent = nullptr);
@@ -81,6 +82,9 @@ public:
Q_INVOKABLE void removeRow(int rowIndex, int rows = 1);
Q_INVOKABLE void setRow(int rowIndex, const QVariant &row);
+ QJSValue roleDataProvider() const;
+ void setRoleDataProvider(QJSValue roleDataProvider);
+
QModelIndex index(int row, int column, const QModelIndex &parent) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
@@ -92,6 +96,7 @@ Q_SIGNALS:
void columnCountChanged();
void rowCountChanged();
void rowsChanged();
+ void roleDataProviderChanged();
private:
class ColumnPropertyInfo
@@ -136,6 +141,7 @@ private:
// key = column index
// value = index (key) into mRoleNames
QHash<int, int> mDefaultDisplayRoles;
+ QJSValue mRoleDataProvider;
};
QT_END_NAMESPACE
diff --git a/tests/auto/qml/qqmltablemodel/data/roleDataProvider.qml b/tests/auto/qml/qqmltablemodel/data/roleDataProvider.qml
new file mode 100644
index 0000000000..825a1ad071
--- /dev/null
+++ b/tests/auto/qml/qqmltablemodel/data/roleDataProvider.qml
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** 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 QtQuick 2.12
+import Qt.labs.qmlmodels 1.0
+
+Item {
+ id: root
+ width: 200
+ height: 200
+
+ property alias testModel: testModel
+
+ TableModel {
+ id: testModel
+ objectName: "testModel"
+ rows: [
+ [ { name: "Rex" }, { age: 3 } ],
+ [ { name: "Buster" }, { age: 5 } ]
+ ]
+ roleDataProvider: function(row, column, role, cellData) {
+ if (role === "display") {
+ // Age will now be in dog years
+ if (cellData.hasOwnProperty("age"))
+ return (cellData.age * 7);
+ else if (column === 0)
+ return (cellData.name);
+ }
+ return cellData;
+ }
+ }
+ TableView {
+ anchors.fill: parent
+ model: testModel
+ delegate: Text {
+ id: textItem
+ text: model.display
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp b/tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp
index 825017e811..276f4e2b9f 100644
--- a/tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp
+++ b/tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp
@@ -56,6 +56,7 @@ private slots:
void setRowsImperatively();
void setRowsMultipleTimes();
void defaultDisplayRoles();
+ void roleDataProvider();
};
void tst_QQmlTableModel::appendRemoveRow()
@@ -859,6 +860,24 @@ void tst_QQmlTableModel::defaultDisplayRoles()
QCOMPARE(model->data(model->index(1, 1, QModelIndex()), roleNames.key("display")).toInt(), 33);
}
+void tst_QQmlTableModel::roleDataProvider()
+{
+ QQuickView view(testFileUrl("roleDataProvider.qml"));
+ QCOMPARE(view.status(), QQuickView::Ready);
+ view.show();
+ QVERIFY(QTest::qWaitForWindowActive(&view));
+
+ QQmlTableModel *model = view.rootObject()->property("testModel").value<QQmlTableModel*>();
+ QVERIFY(model);
+
+ const QHash<int, QByteArray> roleNames = model->roleNames();
+ QVERIFY(roleNames.values().contains("display"));
+ QCOMPARE(model->data(model->index(0, 0, QModelIndex()), roleNames.key("display")).toString(), QLatin1String("Rex"));
+ QCOMPARE(model->data(model->index(0, 1, QModelIndex()), roleNames.key("display")).toInt(), 3 * 7);
+ QCOMPARE(model->data(model->index(1, 0, QModelIndex()), roleNames.key("display")).toString(), QLatin1String("Buster"));
+ QCOMPARE(model->data(model->index(1, 1, QModelIndex()), roleNames.key("display")).toInt(), 5 * 7);
+}
+
QTEST_MAIN(tst_QQmlTableModel)
#include "tst_qqmltablemodel.moc"