summaryrefslogtreecommitdiffstats
path: root/src/controls/TableView.qml
diff options
context:
space:
mode:
authorJens Bache-Wiig <jens.bache-wiig@digia.com>2013-12-09 14:16:39 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-02-20 11:01:45 +0100
commit73ac28cba6d9344b866788443a5ff753d15f6606 (patch)
tree2ff2409cb7c44ee73a8321152e5555a1cc9b2496 /src/controls/TableView.qml
parent38bce6ada7f0660c39929fcab19d5c10b8550d3c (diff)
Improve TableView performance by caching row-delegates
This gives a much better scrolling performance in TableView since we do not have to instantiate the rows or re-establish bindings to header columns for each created table row. [ChangeLog][QtQuickControls] Significantly optimized TableView scrolling by recycling rowDelegate instances. Change-Id: I301e5e476c78f241be1282332905b714fbc5b37d Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@digia.com> Reviewed-by: J-P Nurmi <jpnurmi@digia.com>
Diffstat (limited to 'src/controls/TableView.qml')
-rw-r--r--src/controls/TableView.qml183
1 files changed, 114 insertions, 69 deletions
diff --git a/src/controls/TableView.qml b/src/controls/TableView.qml
index 6a773aa6d..f72b429ad 100644
--- a/src/controls/TableView.qml
+++ b/src/controls/TableView.qml
@@ -542,6 +542,7 @@ ScrollView {
currentIndex: -1
visible: columnCount > 0
interactive: Settings.hasTouchScreen
+ property var rowItemStack: [] // Used as a cache for rowDelegates
SystemPalette {
id: palette
@@ -770,82 +771,126 @@ ScrollView {
root.activated(currentRow);
}
- delegate: FocusScope {
- id: rowitem
- width: itemrow.width
- height: rowstyle.height
+ delegate: Item {
+ id: rowItemContainer
- function selected() {
- if (mousearea.dragRow > -1 && (rowIndex >= mousearea.clickedRow && rowIndex <= mousearea.dragRow
- || rowIndex <= mousearea.clickedRow && rowIndex >=mousearea.dragRow))
- return selection.contains(mousearea.clickedRow)
+ property Item rowItem
+ // We recycle instantiated row items to speed up list scrolling
- return selection.count && selection.contains(rowIndex)
+ Component.onDestruction: {
+ // move the rowItem back in cache
+ if (rowItem) {
+ rowItem.visible = false;
+ rowItem.parent = null;
+ listView.rowItemStack.push(rowItem); // return rowItem to cache
+ }
}
- readonly property int rowIndex: model.index
- readonly property bool alternate: alternatingRowColors && rowIndex % 2 == 1
- readonly property var itemModelData: typeof modelData == "undefined" ? null : modelData
- readonly property var itemModel: model
- readonly property bool itemSelected: selected()
- readonly property color itemTextColor: itemSelected ? __style.highlightedTextColor : __style.textColor
-
- onActiveFocusChanged: {
- if (activeFocus)
- listView.currentIndex = rowIndex
+
+ Component.onCompleted: {
+ // retrieve row item from cache
+ if (listView.rowItemStack.length > 0)
+ rowItem = listView.rowItemStack.pop();
+ else
+ rowItem = rowComponent.createObject(listView);
+
+ // Bind container to item size
+ rowItemContainer.width = Qt.binding( function() { return rowItem.width });
+ rowItemContainer.height = Qt.binding( function() { return rowItem.height });
+
+ // Reassign row-specific bindings
+ rowItem.rowIndex = model.index;
+ rowItem.alternate = Qt.binding( function() { return alternatingRowColors && model.index % 2 == 1 });
+ rowItem.itemModelData = Qt.binding( function() { return typeof modelData == "undefined" ? null : modelData });
+ rowItem.itemModel = Qt.binding( function() { return model });
+ rowItem.parent = rowItemContainer;
+ rowItem.visible = true;
}
+ }
- Loader {
- id: rowstyle
- // row delegate
- sourceComponent: root.rowDelegate
- // Row fills the view width regardless of item size
- // But scrollbar should not adjust to it
- height: item ? item.height : 16
- width: parent.width + __horizontalScrollBar.width
- x: listView.contentX
-
- // these properties are exposed to the row delegate
- // Note: these properties should be mirrored in the row filler as well
- property QtObject styleData: QtObject {
- readonly property int row: rowitem.rowIndex
- readonly property bool alternate: rowitem.alternate
- readonly property bool selected: rowitem.itemSelected
- readonly property bool hasActiveFocus: root.activeFocus
+ Component {
+ id: rowComponent
+
+ FocusScope {
+ id: rowitem
+ visible: false
+
+ property int rowIndex
+ property bool alternate
+ property var itemModelData
+ property var itemModel
+ property bool itemSelected: selected()
+ readonly property color itemTextColor: itemSelected ? __style.highlightedTextColor : __style.textColor
+
+ function selected() {
+ if (mousearea.dragRow > -1 && (rowIndex >= mousearea.clickedRow && rowIndex <= mousearea.dragRow
+ || rowIndex <= mousearea.clickedRow && rowIndex >=mousearea.dragRow))
+ return selection.contains(mousearea.clickedRow)
+
+ return selection.count && selection.contains(rowIndex)
}
- readonly property var model: listView.model
- readonly property var modelData: rowitem.itemModelData
- }
- Row {
- id: itemrow
- height: parent.height
- Repeater {
- id: repeater
- model: columnModel
- Loader {
- id: itemDelegateLoader
- width: columnItem.width
- height: parent ? parent.height : 0
- visible: columnItem.visible
- sourceComponent: columnItem.delegate ? columnItem.delegate : itemDelegate
-
- // these properties are exposed to the item delegate
- readonly property var model: listView.model
- readonly property var modelData: itemModelData
-
- property QtObject styleData: QtObject {
- readonly property int row: rowitem.rowIndex
- readonly property int column: index
- readonly property int elideMode: columnItem.elideMode
- readonly property int textAlignment: columnItem.horizontalAlignment
- readonly property bool selected: rowitem.itemSelected
- readonly property color textColor: rowitem.itemTextColor
- readonly property string role: columnItem.role
- readonly property var value: itemModel.hasOwnProperty(role)
- ? itemModel[role] // Qml ListModel and QAbstractItemModel
- : modelData && modelData.hasOwnProperty(role)
- ? modelData[role] // QObjectList / QObject
- : modelData != undefined ? modelData : "" // Models without role
+
+ width: itemrow.width
+ height: rowstyle.height
+
+ onActiveFocusChanged: {
+ if (activeFocus)
+ listView.currentIndex = rowIndex
+ }
+
+ Loader {
+ id: rowstyle
+ // row delegate
+ sourceComponent: root.rowDelegate
+ // Row fills the view width regardless of item size
+ // But scrollbar should not adjust to it
+ height: item ? item.height : 16
+ width: parent.width + __horizontalScrollBar.width
+ x: listView.contentX
+
+ // these properties are exposed to the row delegate
+ // Note: these properties should be mirrored in the row filler as well
+ property QtObject styleData: QtObject {
+ readonly property int row: rowitem.rowIndex
+ readonly property bool alternate: rowitem.alternate
+ readonly property bool selected: rowitem.itemSelected
+ readonly property bool hasActiveFocus: root.activeFocus
+ }
+ readonly property var model: listView.model
+ readonly property var modelData: rowitem.itemModelData
+ }
+ Row {
+ id: itemrow
+ height: parent.height
+ Repeater {
+ id: repeater
+ model: columnModel
+
+ Loader {
+ id: itemDelegateLoader
+ width: columnItem.width
+ height: parent ? parent.height : 0
+ visible: columnItem.visible
+ sourceComponent: columnItem.delegate ? columnItem.delegate : itemDelegate
+
+ // these properties are exposed to the item delegate
+ readonly property var model: listView.model
+ readonly property var modelData: itemModelData
+
+ property QtObject styleData: QtObject {
+ readonly property int row: rowitem.rowIndex
+ readonly property int column: index
+ readonly property int elideMode: columnItem.elideMode
+ readonly property int textAlignment: columnItem.horizontalAlignment
+ readonly property bool selected: rowitem.itemSelected
+ readonly property color textColor: rowitem.itemTextColor
+ readonly property string role: columnItem.role
+ readonly property var value: (itemModel && itemModel.hasOwnProperty(role))
+ ? itemModel[role] // Qml ListModel and QAbstractItemModel
+ : modelData && modelData.hasOwnProperty(role)
+ ? modelData[role] // QObjectList / QObject
+ : modelData != undefined ? modelData : "" // Models without role
+ }
}
}
}