[solved] TableView with a rowDelegate should select newly added item
-
Ive got a TableView which displays a model derived from QAbstractListModel. Im using an item and row delegates to heavily customize the appearance. To show the user the currently selected row I am drawing a rectangle around the row. My understanding of "selected" is the last row the user clicked or I set using the code
tableView.selection.select(rowIndex)
When an item is added to the model it is shown correctly in the table. However, I would like this row to become the selected row.
I have tried to achieve this using the model's onRowsInserted signal which works in most situations. If the new new row is at the end on the model then I have a problem. Inside the onRowsInserted handler, the TableView does not yet have the new item at the end and therefore I cannot select it.
Here is my onRowsInserted code:
Connections { target: tableView.model onRowsInserted: { console.log("sessionUsers rows inserted") // row has been added to model but is not yet shown in the tableView // so this does NOT work when the new row is the last item in the table tableView.selection.clear() tableView.currentRow = last tableView.selection.select(last) tableView.activated(last) // doesnt seem to do anything } }
My "selected indicator" inside the rowDelegate is set visible using
visible: styleData.selected ? true : false
-
@KiNgFrUiT Use
onRowCountChanged
handler instead. In this way there will be a guarantee that new row is added. For eg:TableView { ... rowDelegate: Rectangle { color: styleData.selected ? "skyblue" : "white" Text { anchors.fill: parent text: styleData.value } } ... onRowCountChanged: { tableview.selection.clear() tableview.selection.select(rowCount-1) } }
-
@KiNgFrUiT The last one is the new one.
rowCount-1
will give its index. -
@p3c0 Thanks again. Your help got me thinking along the right lines and I now have a solution I am happy with. I am including it below to help others who may come across this page. The code has some omissions to keep it brief but everything needed to solve this problem is included. Ive also shown how I sort the items using a proxy model.
When a row is clicked by the user, it becomes selected.
When a row is added to the table via the model, it becomes selected.
When a row is removed from the table via the model, the next row is selected. If this row was at the end of the table, then the previous row is selected. If the table is empty, nothing is selected.import org.qtproject.example 1.0 // SortFilterProxyModel TableView { id: tableView ... selectionMode: SelectionMode.SingleSelection model: SortFilterProxyModel { id: proxyModel source: userModel sortOrder: Qt.AscendingOrder sortCaseSensitivity: Qt.CaseInsensitive sortRole: tableView.getColumn(1).role } property int last:0 // index of the last inserted or deleted item onRowCountChanged: { tableView.selection.clear() if(tableView.rowCount > 0) { var index = tableView.last if(index + 1 >= tableView.rowCount) { index = tableView.rowCount - 1 } tableView.currentRow = index tableView.selection.select(index) tableView.activated(index) } } Connections { target: tableView.model onModelReset: tableView.last = 0 } Connections { target: tableView.model onRowsRemoved: tableView.last = last } Connections { target: tableView.model onRowsInserted: tableView.last = last } rowDelegate: Rectangle { ... MouseArea { anchors.fill: parent onClicked: { // clear any other selected row tableView.selection.clear() // select this row tableView.currentRow = styleData.row tableView.selection.select(styleData.row) // convert mouse position from delegate to tableview coordinates var coordinates = rowDelegate.mapToItem(tableView, mouse.x, mouse.y) // active and click the appropriate items (internal) var clickIndex = tableView.__listView.indexAt(0, coordinates.y + tableView.__listView.contentY) if (clickIndex > -1) { if (tableView.__activateItemOnSingleClick) tableView.activated(clickIndex) tableView.clicked(clickIndex) } // consume the mouse event mouse.accepted = true } } } }
-
@KiNgFrUiT You're Welcome :) Thanks for sharing the complete solution. Also it would be better if you mark the post as solved so that others may know that the post has a solution.