Have QItemSelectionModel react on resetModel()
-
Hello Qt Community,
in my current project I gave the model/view concept with Table and List another go after rather frustrating failures of the past and this time it appears to work out just fine. I have views with derived models behind it which fetch data and such. I also can connect to QItemSelectionModel's selectionChanged() or currentChanged() to react on selection. So far so good.
Now my models usually contain only a few items (<20) per data set and fetch them remotely. They have no natural order but an Id which serves as ModelIndex (internalId). For this reason, when I detect remote change I call (in my models)
beginResetModel(); // delete my internal data or restructure it accordingly endResetModel();
so far so good. Now my question is:
How am I supposed to deal with existing an selection when this happens?
When the model is reset like this the selection model appears to clear the selection but doesn't emit signals. Which is documented behavior. e.g. in http://doc.qt.io/qt-5/qitemselectionmodel.html#currentRowChanged it says:
"Note that this signal will not be emitted when the item model is reset."
Which appears to be the case for all relevant signals. It has the effect that I get a signal when the user selects something but when the selection is cleared for some reason (data reset) I don't get the signal. Now before I start ugly hacks again I would like to ask you if there's something obvious I'm missing here. Is there some way I can still get a signal like this?
tl;dr
How can I make a stock QItemSelectionModel send me a signal when the underlying QAbstractItemModel has undergone model reset, causing the selection to clear?Best regards...
Moose
-
Hi,
You could try something like connecting the QAbstractItemModel::modelReset signal to QItemSelectionModel::clear
Hope it helps
-
That connection can't work, it seems. In qitemselectionmodel.cpp it looks like the wanted signals will only be emitted if there is a previous selection (which at the point of calling clear() will already have been reset due to some internal connection that will certainly fire before your custom one).
Have you tried connecting signals (I am not sure which one you actually rely on):
QAbstractItemModel *m; QItemSelectionModel *s; connect(m, &QAbstractItemModel::modelReset, [s](){ emit(s->selectionChanged(QItemSelection(), QItemSelection())); });
Or maybe directly connecting QAbstractItemModel::modelReset to whatever it is you want to be called in case the selection changes? Alternatively you might use QAbstractItemModel::rowsInserted, if that is possible in your case (I don't know if the model is dynamic in that items come and go at all times). That way you might even be able to set up a new selection in reaction to the model being reset.
-
@thEClaw
Indeed, it would seem that way. I have tried different ties to those signals but finally caved in and found a solution in having the selection model and the tablemodel interact. I wanted to avoid this as it appears unclean to me but now I hand the instance of QItemSelectionModel being used by the view into my own table model implementation. Now when the table model notices data change that would have to result in the selection being cleared I clear() it manually.
Seems to work, though I would have preferred the models not depend on each other but hey, sometimes a man just gotta do what a man's gotta do. Or some such excuse.Thanks for all your input!
Moose
-
Are you calling reset on the selection model when you reset your own model ?
-
@SGaist
Well yes, now I do. Which is what I wanted to avoid as this requires tighter coupling (both code and semantically) between the two. My initial expectation was that the selection model is cleared automatically when the model changes. Why wouldn't it, risking to point to invalid or no longer existing data? -
What surprises me is that it sounds like you manually do what the modelReset/clear combo should do.