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. Removing multiple rows from TableView
Forum Update on Monday, May 27th 2025

Removing multiple rows from TableView

Scheduled Pinned Locked Moved Solved QML and Qt Quick
7 Posts 3 Posters 4.0k 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.
  • D Offline
    D Offline
    deleted71
    wrote on 17 Aug 2016, 13:00 last edited by
    #1

    Hi,

    I am trying to remove multiple rows from a TableView. I have a selection and on deletion action traverse the selected rows with

    tableView.selection.forEach(function(rowIndex) {myModel.deleteRow(rowIndex)})
    

    Now what happens is that the first selected row is deleted and the view is updated. Then the next row is deleted but since one line has already been deleted, all the row indexes below are now shifted by 1.

    How is the approach here in general?

    • Find a way to not update the view between the deletions?
    • Recalculate the index after every deletion?

    Thanks for any hints.

    1 Reply Last reply
    0
    • S Offline
      S Offline
      SGaist
      Lifetime Qt Champion
      wrote on 17 Aug 2016, 22:42 last edited by
      #2

      Hi,

      There are usually three ways:

      1. Do it in reverse order
      2. Keep deleting the starting row for the number of rows to remove.
      3. If your model is base on QAbstractItemModel, call removeRows on it with the start index and the count

      Hope it helps

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • D Offline
        D Offline
        deleted71
        wrote on 18 Aug 2016, 07:59 last edited by
        #3

        Thank you for your answer.

        I forgot to mention that the selection is not contiguous.
        So I guess it's 1. then. I will try that out later today.

        1 Reply Last reply
        0
        • D Offline
          D Offline
          deleted71
          wrote on 18 Aug 2016, 13:05 last edited by
          #4

          OK, so far so bad. :)
          Since I am using a QSortFilterProxyModel, I cannot make any assumptions about the "real" rowIndex position. So I cannot tell which row is the "last" one that should be removed first.

          I have now added a unique ID to my data source and will try to identify the rows to remove that way. Will post my solution soon'ish. :)

          1 Reply Last reply
          0
          • L Offline
            L Offline
            levelxxl
            wrote on 18 Aug 2016, 18:13 last edited by
            #5
            function removeSelectedRows() {
                for (var i = selection.__ranges.length - 1 ; i >= 0 ; -- i) {
                    var index = selection.__ranges[i][0];
                    var count = 1 + selection.__ranges[i][1] - selection.__ranges[i][0];
                    model.remove(index, count)
                }
                
                selection.clear()
            }
            

            This worked for me, but I'm not using a QSortFilterProxyModel.

            D 1 Reply Last reply 22 Aug 2016, 08:35
            0
            • L levelxxl
              18 Aug 2016, 18:13
              function removeSelectedRows() {
                  for (var i = selection.__ranges.length - 1 ; i >= 0 ; -- i) {
                      var index = selection.__ranges[i][0];
                      var count = 1 + selection.__ranges[i][1] - selection.__ranges[i][0];
                      model.remove(index, count)
                  }
                  
                  selection.clear()
              }
              

              This worked for me, but I'm not using a QSortFilterProxyModel.

              D Offline
              D Offline
              deleted71
              wrote on 22 Aug 2016, 08:35 last edited by
              #6

              Hi,

              looks tempting (though not with QSqortFilterProxyModel) but for my understanding breaks with two "best practices" of the QML world.

              1. limit the use of JavaScript to UI logic and put your business logic into the C++ backend
              2. avoid double-underscore __methods because they are private and can change with any minor version of Qt

              My approach will be to fill an array with all the selected rows on the QML side, hand that to my ProxyModel (C++), remap the rowIndexes there to the ones of my SqlTableModel, hand that new list to that model and then try to remove all rows in one transaction with QSqlQuery::execBatch. Not sure if I succeed (still a beginner) but this feels like a good approach.

              Regards

              1 Reply Last reply
              0
              • D Offline
                D Offline
                deleted71
                wrote on 22 Aug 2016, 11:37 last edited by
                #7

                So here is what works for me.
                Please comment if you think there are things to improve. :)
                What I do is:

                • View: create a list of selected rows and give that list to the ProxyModel
                • ProxyModel: map the proxy row indexes to the table row indexes and give the new list to the SqlTableModel
                • SqlTableModel: remove the rows in reverse order to not shift the remaining row indexes in the list

                The QML...

                Menu {
                    id: contextMenu
                    MenuItem {
                        text: qsTr("Delete")
                        shortcut: "Del"
                        onTriggered: {
                            var selectedRows = []
                            tableView.selection.forEach(function(rowIndex) {selectedRows.push(rowIndex)})
                            myModel.deleteRows(selectedRows)
                            tableView.selection.clear()
                            tableView.selection.select(tableView.currentRow)
                        }
                    }
                }
                

                ...the ProxyModel...

                void ProxyModel::deleteRows(QVariantList selectedRows)
                {
                    QVector<int> rowsToDelete;
                    for (QVariant row : selectedRows) {
                        QModelIndex proxyIdx = index(row.toInt(), 0);
                        QModelIndex sourceIdx = mapToSource(proxyIdx);
                        rowsToDelete.append(sourceIdx.row());
                    }
                    qobject_cast<SqlTableModel*>(sourceModel())->deleteRows(rowsToDelete);
                }
                

                ...and the ugly ... err, the SqlTableModel

                void SqlTableModel::deleteRows(QVector<int> rows)
                {
                    bool success;
                    for (auto it = rows.crbegin(); it != rows.crend(); ++it) {
                        int row = *it;
                        beginRemoveRows(QModelIndex(), row, row);
                        success = removeRow(row);
                        if (success == true) {
                            endRemoveRows();
                        }
                    }
                }
                
                1 Reply Last reply
                0

                1/7

                17 Aug 2016, 13:00

                • Login

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