I'm working in Qt 5.6.1. There are several QTableWidget tables, in theory they represent one table - they are located closely, and the data on the rows is interconnected, but they should be presented as separate widgets. Their selection flag is SelectRows, and the ExtendedSelection mod. How can I make a general selection for them? Let's say you selected several rows of the first table and selected the same rows in others. The selection should be removed accordingly. Tables have different numbers of columns.
I tried to handle the selectionChanged signal from the selectionModel tables in this way:
void wSpisokActive::selectionChangedMain(const QItemSelection &selected, const QItemSelection &deselected)
{
permission_to_changed_main_ = false; // flag to exit a similar slot in another table
if (permission_to_changed_monitoring_) { // select row
QModelIndexList selected_list = selected.indexes();
for (QModelIndex model_index: selected_list) {
ui->tbMonitoring->selectRow(model_index.row());
}
QModelIndexList deselected_list = deselected.indexes();
int last_row = -1;
for (QModelIndex model_index: deselected_list) { // deselect row
if (last_row == model_index.row()) continue;
last_row = model_index.row();
for (int i = 0; i < ui->tbMonitoring->columnCount(); ++i) {
ui->tbMonitoring->selectionModel()->select(ui->tbMonitoring->model()->index(last_row, i), QItemSelectionModel::Deselect);
}
}
}
permission_to_changed_main_ = true;
}
But this way selection via Ctrl is processed incorrectly. Also, when selecting several rows, only the last one is highlighted - I tried setting ui->tbMonitoring->setSelectionMode(QAbstractItemView::MultiSelection); before selecting rows, and after ui->tbMonitoring->setSelectionMode(QAbstractItemView::ExtendedSelection);. But it didn't help.
As explained in this help page (my emphasis):
The methods you are interested in come in pairs:
model/setModel(QAbstractItemModel*)selectionModel()/setSelectionModel(QItemSelectionModel*)For that last one, spare a minute to carefully read what the documentation says, that is:
The resulting code looks like (assuming this is on your main thread):
Edit: About QTBUG-49966, pointed out by @musicamante in comments.
To cut the chase: YES, 1 selection model per view (rather, 1 selection model for the header view of the view) will remain in memory until the view is deleted, along with its header.
However, if you do nothing more than what I presented above, you will only have 1 selection model "leaked" per view (which should be a very small number) which get deleted when you delete the view.
If you are implementing a window where
setModelgets called any number of time (e.g. see the scenario described by @musicamante in comments), there are several things you can do as a mitigation measure:To limit the lifetime of the memory leak:
If you make sure widgets are deleted (the easiest way to ensure everything gets cleared when you close a window is by calling
myWindow->setAttribute(Qt::WA_DeleteOnClose);), these unused selection models will not outlive your views.mySelectionModel->setParent(nullptr);either.As long as all selection models have a view as their parent, they will get deleted with the view.
To limit the size of the memory leak:
You must make sure not to call
setModel()more than once per view:Example with
QSqlTableModel: changing the SQL table loaded should not be done by creating a new model to substitute it to the existing one. Instead, do:QIdentityProxyModel.The purpose of a proxy model is not supposed to be this but it comes in handy here. The model can be changed on a view (at least, this is what it visually looks like) without calling
setModel.It is intialized by doing:
Then, attaching a new model to your view can be done:
And voilà! no more calling
setModelseveral time on the same view.On a related note, if I can make a quick (optional) recommendation:
QListView,QTableView,QTreeViewover theirQxxxxxWidgetcounterparts.While
QTableWidgetis a class of choice for beginners, simplifying a lot of the required work, it sets such limitations on flexibility that the downsides far outweigh the advantages.QStandardItemModel(noteQxxxxxWidgetclasses all use their own internal standalone model) if they can.If your application already has some internal structure to store the data shown on screen, it is usually more efficient to map it to a custom subclass of
QAbstractItemModelrather than copy it into a standalone model such asQStandardItemModel.The sooner you get used to creating your own model classes, the easier your life will become down the line.
In your case, you are working with tables, you can start your learning journey with
QAbstractTableModel. It should be accessible enough as a starting point and generally speaking easier to subclass compared toQAbstractItemModel.The above will work with your current code so feel free to ignore this advice.