diff options
| author | Jens Bache-Wiig <jens.bache-wiig@digia.com> | 2013-12-09 14:16:39 +0100 |
|---|---|---|
| committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-02-20 11:01:45 +0100 |
| commit | 73ac28cba6d9344b866788443a5ff753d15f6606 (patch) | |
| tree | 2ff2409cb7c44ee73a8321152e5555a1cc9b2496 /src/controls/TableView.qml | |
| parent | 38bce6ada7f0660c39929fcab19d5c10b8550d3c (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.qml | 183 |
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 + } } } } |
