Removing rows from a table model
-
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 -
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@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?
-
@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?
@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.
-
@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.
@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?
-
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.
-
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.
@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()
?) byQModelIndex::row()
, you don't care about columns. And given you haveQModelIndexList selectedRows = qsm->selectedRows()
I think you have just one entry, withcolumn() == 0
, for each row, so no duplicate row numbers. -
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.
-
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.
@Perdrix
Umm, isn't this "naughty"?! You do not know what it is sorting by within aQModelIndex
, the fact that it "works" by row number is "fortuitous"? Oh, I see, it will use the in-builtbool 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 :)
-
@Perdrix
Umm, isn't this "naughty"?! You do not know what it is sorting by within aQModelIndex
, the fact that it "works" by row number is "fortuitous"? Oh, I see, it will use the in-builtbool 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 :)
-