Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. [solved] TableView with a rowDelegate should select newly added item

[solved] TableView with a rowDelegate should select newly added item

Scheduled Pinned Locked Moved QML and Qt Quick
tableviewqmlrowdelegateonrowsinsertedqabstractlistmo
6 Posts 2 Posters 5.9k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • K Offline
    K Offline
    KiNgFrUiT
    wrote on 22 Sept 2015, 10:09 last edited by KiNgFrUiT
    #1

    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

    P 1 Reply Last reply 22 Sept 2015, 11:57
    1
    • K KiNgFrUiT
      22 Sept 2015, 10:09

      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

      P Offline
      P Offline
      p3c0
      Moderators
      wrote on 22 Sept 2015, 11:57 last edited by p3c0
      #2

      @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)
           }
      }
      

      157

      K 1 Reply Last reply 22 Sept 2015, 13:04
      0
      • P p3c0
        22 Sept 2015, 11:57

        @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)
             }
        }
        
        K Offline
        K Offline
        KiNgFrUiT
        wrote on 22 Sept 2015, 13:04 last edited by
        #3

        @p3c0 Thanks for the suggestion. Using your method how can I know which is the new row? The new item can be added anywhere in the model.

        P 1 Reply Last reply 23 Sept 2015, 05:04
        0
        • K KiNgFrUiT
          22 Sept 2015, 13:04

          @p3c0 Thanks for the suggestion. Using your method how can I know which is the new row? The new item can be added anywhere in the model.

          P Offline
          P Offline
          p3c0
          Moderators
          wrote on 23 Sept 2015, 05:04 last edited by
          #4

          @KiNgFrUiT The last one is the new one. rowCount-1 will give its index.

          157

          K 1 Reply Last reply 25 Sept 2015, 08:26
          0
          • P p3c0
            23 Sept 2015, 05:04

            @KiNgFrUiT The last one is the new one. rowCount-1 will give its index.

            K Offline
            K Offline
            KiNgFrUiT
            wrote on 25 Sept 2015, 08:26 last edited by KiNgFrUiT
            #5

            @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
                     }
                  }      
               }
            }
            
            P 1 Reply Last reply 25 Sept 2015, 08:34
            1
            • K KiNgFrUiT
              25 Sept 2015, 08:26

              @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
                       }
                    }      
                 }
              }
              
              P Offline
              P Offline
              p3c0
              Moderators
              wrote on 25 Sept 2015, 08:34 last edited by
              #6

              @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.

              157

              1 Reply Last reply
              0

              3/6

              22 Sept 2015, 13:04

              • Login

              • Login or register to search.
              3 out of 6
              • First post
                3/6
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved