Removing rows from a table model
-
wrote on 27 Sept 2022, 09:21 last edited by 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 -
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
Davidwrote on 27 Sept 2022, 09:49 last edited by@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?
-
wrote on 27 Sept 2022, 10:10 last edited by
Really? I thought disjunct was a much smaller word that dis-contiguous :)
-
@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?
wrote on 27 Sept 2022, 10:12 last edited by 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.
-
@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.
wrote on 27 Sept 2022, 10:20 last edited by@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?
-
wrote on 27 Sept 2022, 14:01 last edited by
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.
wrote on 27 Sept 2022, 14:10 last edited by@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. -
wrote on 27 Sept 2022, 14:27 last edited by 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.
-
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.
wrote on 27 Sept 2022, 15:01 last edited by JonB@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 :)
-
1/10