TableModel: Difference between revisions
Jump to navigation
Jump to search
No edit summary |
No edit summary |
||
Line 98: | Line 98: | ||
import QtQuick.Window 2.12 | import QtQuick.Window 2.12 | ||
import Qt.labs.qmlmodels 1.0 | import Qt.labs.qmlmodels 1.0 | ||
Window { | Window { | ||
width: 400 | width: 400 | ||
height: 400 | height: 400 | ||
visible: true | visible: true | ||
// pretend we got data from some web API... | // pretend we got data from some web API... | ||
property var tableData: [ | property var tableData: [ | ||
Line 130: | Line 130: | ||
] | ] | ||
] | ] | ||
TableView { | TableView { | ||
anchors.fill: parent | anchors.fill: parent | ||
Line 136: | Line 136: | ||
rowSpacing: 1 | rowSpacing: 1 | ||
boundsBehavior: Flickable.StopAtBounds | boundsBehavior: Flickable.StopAtBounds | ||
model: TableModel { | model: TableModel { | ||
rowCount: tableData.length | rowCount: tableData.length | ||
Line 144: | Line 144: | ||
// return tableData[index.row][role] | // return tableData[index.row][role] | ||
// } | // } | ||
// Otherwise: | // Otherwise, handle those with more than one: | ||
roleDataProvider: function(index, role) { | roleDataProvider: function(index, role) { | ||
var rowData = tableData[index.row] | var rowData = tableData[index.row] | ||
Line 151: | Line 151: | ||
case 0: | case 0: | ||
return role === "checked" ? rowData.checked : rowData.checkable | return role === "checked" ? rowData.checked : rowData.checkable | ||
default: | |||
return | return tableData[index.row][role] | ||
} | } | ||
} | } | ||
Line 170: | Line 164: | ||
// delegate: ... | // delegate: ... | ||
} | } | ||
/* | /* | ||
To append a row: | To append a row: | ||
model.beginAppendRow() | model.beginAppendRow() | ||
// user code to append row to tableData | // user code to append row to tableData |
Revision as of 13:20, 27 February 2019
TableModel provides a QAbstractTableModel that can be used in QML with TableView.
Requirements
#1
Allow different data format/structure for rows; need to be flexible. For example, it should be possible to specify several roles per column, as QAbstractTableModel supports this:
model: TableModel { // Each row is one type of fruit that can be ordered rows: [ [ // Each object (line) is one cell/column, // and each property in that object is a role. { checked: false, checkable: true }, { amount: 1 }, { fruitType: "Apple" }, { fruitName: "Granny Smith" }, { fruitPrice: 1.50 } ], [ { checked: true, checkable: true }, { amount: 4 }, { fruitType: "Orange" }, { fruitName: "Navel" }, { fruitPrice: 2.50 } ] ] }
In addition, it should be possible to use a simple object for a row, as this seems to be common with web APIs:
[ { "driverId":"fisichella", "code":"FIS", "url":"http://en.wikipedia.org/wiki/Giancarlo_Fisichella", "givenName":"Giancarlo", "familyName":"Fisichella", "dateOfBirth":"1973-01-14", "nationality":"Italian" }, { "driverId":"barrichello", "code":"BAR", "url":"http://en.wikipedia.org/wiki/Rubens_Barrichello", "givenName":"Rubens", "familyName":"Barrichello", "dateOfBirth":"1972-05-23", "nationality":"Brazilian" } ]
#2
We know we want settable rowCount + columnCount for prototyping and allowing use cases such as e.g. spreadsheets.
Solutions
#1 "rows"
Current (unfinished) state as of writing can be seen here: http://code.qt.io/cgit/qt/qtdeclarative.git/tree/src/qml/types/qqmltablemodel.cpp?h=dev&id=b4ee855eb10cf9bfa44ce8e5de8f9ee6c5917764
In addition, there are some follow-up patches:
- https://codereview.qt-project.org/#/c/253255/
- https://codereview.qt-project.org/#/c/253234/
- https://codereview.qt-project.org/#/c/253509/
#2 No "rows"
- We know we can't expect one data format/structure for rows; need to be flexible.
- We know we want settable rowCount + columnCount.
- roleDataLookPolicy (https://codereview.qt-project.org/#/c/253509/) is making things quite complex.
So:
- Remove "rows" altogether. How the actual source JS data is stored and formatted is up to the user,
- rowCount and columnCount would then have to always be specified so that we know how many there are.
- "roles" allows the user to use their custom roles without us having parsed the rows data (currently we parse it up front using an expected format so that we know which roles are available):
roles: [ ["driverId"], ["code"], ["url"], ["givenName"], ["familyName"], ["dateOfBirth"], ["nationality"] ]
- Then we call roleDataProvider() unconditionally each time data() is called for a "new" index, and store that in our own well-formatted map/hash, so we don't need to call roleDataProvider() again for that index.
- As appendRow(), moveRow(), etc. would no longer take the row as an argument, they would need to be replaced with beginAppendRow()/endAppendRow(), etc.
An example:
import QtQuick 2.12 import QtQuick.Window 2.12 import Qt.labs.qmlmodels 1.0
Window { width: 400 height: 400 visible: true
// pretend we got data from some web API... property var tableData: [ [ // Each object (line) is one cell/column, // and each property in that object is a role. { checked: false, checkable: true }, { amount: 1 }, { fruitType: "Apple" }, { fruitName: "Granny Smith" }, { fruitPrice: 1.50 } ], [ { checked: true, checkable: true }, { amount: 4 }, { fruitType: "Orange" }, { fruitName: "Navel" }, { fruitPrice: 2.50 } ], [ { checked: false, checkable: true }, { amount: 1 }, { fruitType: "Banana" }, { fruitName: "Cavendish" }, { fruitPrice: 3.50 } ] ]
TableView { anchors.fill: parent columnSpacing: 1 rowSpacing: 1 boundsBehavior: Flickable.StopAtBounds
model: TableModel { rowCount: tableData.length columnCount: roles.length // If there is only one role per column: // roleDataProvider: function(index, role) { // return tableData[index.row][role] // }
// Otherwise, handle those with more than one: roleDataProvider: function(index, role) { var rowData = tableData[index.row] switch (index.column) { case 0: return role === "checked" ? rowData.checked : rowData.checkable default: return tableData[index.row][role] } } roles: [ ["checked", "checkable"], ["fruitType"], ["fruitName"], ["fruitPrice"] ] } // delegate: ... }
/* To append a row:
model.beginAppendRow() // user code to append row to tableData model.endAppendRow() */ }