Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Removing rows from a table model
Forum Updated to NodeBB v4.3 + New Features

Removing rows from a table model

Scheduled Pinned Locked Moved Unsolved General and Desktop
10 Posts 2 Posters 1.8k 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.
  • PerdrixP Offline
    PerdrixP Offline
    Perdrix
    wrote on last edited by Perdrix
    #1

    If I have a table view that is set for extended selection, I can select disjunct ranges of rows.

    If I want to delete them do I have to delete each row individually like this:

    QItemSelectionModel* qsm = ui->tableView->selectionModel();
    QModelIndexList selectedRows = qsm->selectedRows();
    
    	for (int i = 0; i < selectedRows.size(); i++)
    	{
    		int row = selectedRows[i].row();
    		imageModel->beginRemoveRows(QModelIndex(), row, row);
    		imageModel->removeRows(row, 1);
    		imageModel->endRemoveRows();
    	}
    

    Where my overridden removeRows mf looks like:

        bool ImageListModel::removeRows(int row, int count, const QModelIndex& parent)
            {
                //
                // Remove the rows from our backing data and then call
                // base class removeRows()
                //
                auto first{ std::next(mydata.begin(), row) };
                auto last{ first + (count - 1) };
                mydata.erase(first, last);
                return Inherited::removeRows(row, count, parent);
            }
    

    or is there a better way to do it?

    Thanks
    David

    JonBJ 1 Reply Last reply
    0
    • PerdrixP Perdrix

      If I have a table view that is set for extended selection, I can select disjunct ranges of rows.

      If I want to delete them do I have to delete each row individually like this:

      QItemSelectionModel* qsm = ui->tableView->selectionModel();
      QModelIndexList selectedRows = qsm->selectedRows();
      
      	for (int i = 0; i < selectedRows.size(); i++)
      	{
      		int row = selectedRows[i].row();
      		imageModel->beginRemoveRows(QModelIndex(), row, row);
      		imageModel->removeRows(row, 1);
      		imageModel->endRemoveRows();
      	}
      

      Where my overridden removeRows mf looks like:

          bool ImageListModel::removeRows(int row, int count, const QModelIndex& parent)
              {
                  //
                  // Remove the rows from our backing data and then call
                  // base class removeRows()
                  //
                  auto first{ std::next(mydata.begin(), row) };
                  auto last{ first + (count - 1) };
                  mydata.erase(first, last);
                  return Inherited::removeRows(row, count, parent);
              }
      

      or is there a better way to do it?

      Thanks
      David

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #2

      @Perdrix said in Removing rows from a table model:

      I can select disjunct ranges of rows.

      "Disjunct" is a big word :) If your range of rows is not contiguous you can only remove them one a time.

      And while I think of it: presumably you must be careful for removals after the first one? I am thinking that once one row has been removed it may affect the row numbers of the others to be removed, bear that in mind in your code?

      PerdrixP 1 Reply Last reply
      0
      • PerdrixP Offline
        PerdrixP Offline
        Perdrix
        wrote on last edited by
        #3

        Really? I thought disjunct was a much smaller word that dis-contiguous :)

        1 Reply Last reply
        0
        • JonBJ JonB

          @Perdrix said in Removing rows from a table model:

          I can select disjunct ranges of rows.

          "Disjunct" is a big word :) If your range of rows is not contiguous you can only remove them one a time.

          And while I think of it: presumably you must be careful for removals after the first one? I am thinking that once one row has been removed it may affect the row numbers of the others to be removed, bear that in mind in your code?

          PerdrixP Offline
          PerdrixP Offline
          Perdrix
          wrote on last edited by Perdrix
          #4

          @JonB said in Removing rows from a table model:

          once one row has been removed it may affect the row numbers of the others to be removed

          Oh grief - that's a pain! So clearly I need to revise...

          Is this correct - I think it is:

          if (Menuitem::remove == item || Menuitem::erase == item)
          {
          	for (int i = 0; i < selectedRows.size(); i++)
          	{
          		int row = selectedRows[i].row() - i;
          		imageModel->beginRemoveRows(QModelIndex(), row, row);
          		imageModel->removeRows(row, 1);
          		imageModel->endRemoveRows();
          	}
          }
          

          If not does anyone have the correct code to do this - my head is starting to hurt!!!

          D.

          JonBJ 1 Reply Last reply
          0
          • PerdrixP Perdrix

            @JonB said in Removing rows from a table model:

            once one row has been removed it may affect the row numbers of the others to be removed

            Oh grief - that's a pain! So clearly I need to revise...

            Is this correct - I think it is:

            if (Menuitem::remove == item || Menuitem::erase == item)
            {
            	for (int i = 0; i < selectedRows.size(); i++)
            	{
            		int row = selectedRows[i].row() - i;
            		imageModel->beginRemoveRows(QModelIndex(), row, row);
            		imageModel->removeRows(row, 1);
            		imageModel->endRemoveRows();
            	}
            }
            

            If not does anyone have the correct code to do this - my head is starting to hurt!!!

            D.

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by
            #5

            @Perdrix
            First, check my logic on this. My thought:

            • You start with some selection model containing the indexes/row numbers in the source you want to delete.
            • I do not know what order the selection/source row numbers are returned to you in. Suppose it is "random".
            • If you delete a low row number first, one at a time, that would cause higher row numbers to move down.
            • This would make the row numbers from the remaining selections "wrong". Unless the selection indexes are "live", so that they get decremented for you when a lower numbered row is deleted? You need to check.

            The easiest way with deleting numbered rows in anything is to delete downwards in row number order. Then deleting a higher numbered row first does not affect the lower numbered rows. I (think I) would get a list of the source row numbers to delete sorted by row number. Then I would delete those in descending row number order, so I wouldn't have to worry about renumbering?

            1 Reply Last reply
            1
            • PerdrixP Offline
              PerdrixP Offline
              Perdrix
              wrote on last edited by
              #6

              My thoughts are much along the same line as yours

              the list of items to remove is in a QModelIndexList which is just a QList<QModelIndex>

              I actually came here to ask how to sort one of those in descending order (always assuming the QModelIndex has operator<(), so that I can delete the higher numbered rows first.

              I'm a bit concerned by the comment:

              bool QModelIndex::operator<(const QModelIndex &other) const
              Returns true if this model index is smaller than the other model index; otherwise returns false.
              The less than calculation is not directly useful to developers - the way that indexes with different parents compare is not defined. This operator only exists so that the class can be used with QMap.

              which sort of suggests I can't do that :(

              I'll open a separate question for that.

              D.

              JonBJ 1 Reply Last reply
              0
              • PerdrixP Perdrix

                My thoughts are much along the same line as yours

                the list of items to remove is in a QModelIndexList which is just a QList<QModelIndex>

                I actually came here to ask how to sort one of those in descending order (always assuming the QModelIndex has operator<(), so that I can delete the higher numbered rows first.

                I'm a bit concerned by the comment:

                bool QModelIndex::operator<(const QModelIndex &other) const
                Returns true if this model index is smaller than the other model index; otherwise returns false.
                The less than calculation is not directly useful to developers - the way that indexes with different parents compare is not defined. This operator only exists so that the class can be used with QMap.

                which sort of suggests I can't do that :(

                I'll open a separate question for that.

                D.

                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by
                #7

                @Perdrix
                You don't need to compare "full indexes". You are only interested in row numbers for your deletions. So you can just sort (e.g. std::sort()?) by QModelIndex::row(), you don't care about columns. And given you have QModelIndexList selectedRows = qsm->selectedRows() I think you have just one entry, with column() == 0, for each row, so no duplicate row numbers.

                1 Reply Last reply
                2
                • PerdrixP Offline
                  PerdrixP Offline
                  Perdrix
                  wrote on last edited by Perdrix
                  #8

                  Well, I tried to see what would happen if I ignored the warning, and simply did this:

                  //
                  // Sort the list of QModelIndex in descending order so that 
                  // when we iterate over the list we will delete the rows 
                  // with higher row numbers first.
                  //
                  std::sort(selectedRows.rbegin(), selectedRows.rend());
                  
                  

                  and it worked perfectly to sort the QModelIndex entries in the list by row number in descending order.

                  D.

                  JonBJ 1 Reply Last reply
                  0
                  • PerdrixP Perdrix

                    Well, I tried to see what would happen if I ignored the warning, and simply did this:

                    //
                    // Sort the list of QModelIndex in descending order so that 
                    // when we iterate over the list we will delete the rows 
                    // with higher row numbers first.
                    //
                    std::sort(selectedRows.rbegin(), selectedRows.rend());
                    
                    

                    and it worked perfectly to sort the QModelIndex entries in the list by row number in descending order.

                    D.

                    JonBJ Offline
                    JonBJ Offline
                    JonB
                    wrote on last edited by JonB
                    #9

                    @Perdrix
                    Umm, isn't this "naughty"?! You do not know what it is sorting by within a QModelIndex, the fact that it "works" by row number is "fortuitous"? Oh, I see, it will use the in-built bool QModelIndex::operator<.

                    Looking at https://codebrowser.dev/qt5/qtbase/src/corelib/itemmodels/qabstractitemmodel.h.html#83

                        Q_DECL_CONSTEXPR inline bool operator<(const QModelIndex &other) const noexcept
                        {
                               return  r <  other.r
                                    || ...
                    

                    you will be OK, but don't tell anyone else :)

                    PerdrixP 1 Reply Last reply
                    0
                    • JonBJ JonB

                      @Perdrix
                      Umm, isn't this "naughty"?! You do not know what it is sorting by within a QModelIndex, the fact that it "works" by row number is "fortuitous"? Oh, I see, it will use the in-built bool QModelIndex::operator<.

                      Looking at https://codebrowser.dev/qt5/qtbase/src/corelib/itemmodels/qabstractitemmodel.h.html#83

                          Q_DECL_CONSTEXPR inline bool operator<(const QModelIndex &other) const noexcept
                          {
                                 return  r <  other.r
                                      || ...
                      

                      you will be OK, but don't tell anyone else :)

                      PerdrixP Offline
                      PerdrixP Offline
                      Perdrix
                      wrote on last edited by
                      #10

                      @JonB I admit I cheated and looked at the code!

                      D.

                      1 Reply Last reply
                      1
                      • A aperfectcirclefan referenced this topic on

                      • Login

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