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 Updated to NodeBB v4.3 + New Features

Removing multiple rows from TableView

Scheduled Pinned Locked Moved Solved QML and Qt Quick
7 Posts 3 Posters 4.0k Views 1 Watching
  • 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.
  • deleted71D Offline
    deleted71D Offline
    deleted71
    wrote on 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
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on 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
      • deleted71D Offline
        deleted71D Offline
        deleted71
        wrote on 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
        • deleted71D Offline
          deleted71D Offline
          deleted71
          wrote on 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 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.

            deleted71D 1 Reply Last reply
            0
            • L levelxxl
              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.

              deleted71D Offline
              deleted71D Offline
              deleted71
              wrote on 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
              • deleted71D Offline
                deleted71D Offline
                deleted71
                wrote on 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

                • Login

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