QListWidget: how to prevent unselect all?
A QListWidget in SingleSelection mode allows unselecting the last selected item in several ways, such as Ctrl-click (the docs suggest that it should not allow this, but see the comments on QTBUG-49217). How can I prevent this? My item list must always have one item selected.
I first tried overriding mousePressEvent and ignoring it if necessary. This works, but there are other ways to unselect (e.g. it can happen on mouseMoveEvent), and it seems clunky to find and override them all.
I next tried setting a custom QItemSelectionModel that refuses to unselect the currently selected item. That leads to what may be a Qt bug: QListWidget never issues its itemSelectionChanged signal, even if my QItemSelectionModel has no custom behavior at all. (Apparently my call to QListWidget::setSelectionModel somehow causes the connection between QItemSelectionModel::selectionChanged and QListWidget::itemSelectionChanged to break. See my related question.)
Ideally, QListWidget would have optional require-at-least-one-selection behavior built in. I can't be the only one who needs this.
See my answer for your related question. I suggest overriding
void QItemSelectionModel::select(const QModelIndex & index, QItemSelectionModel::SelectionFlags command)
for your selection model to discard the unneeded deselections. Additionally, you should want to override
QAbstractItemView::setSelectionModelfor your list widget to restore the appropriate selection model connections before calling the default implementation.
another possible solution can be overriding QAbstractItemView::selectionCommand() and return QItemSelectionModel::NoUpdate in case the selection should not change.
Xicor last edited by
just wondering, did you 'ignore' the event or did you 'accept' the event? in qt, the 'ignore' option means that YOUR CLASS is ignoring the event, not that you want qt to ignore the event. if you want qt to ignore the event, you need to call 'accept'.
@Xicor Properly speaking, I didn't do either. I just overrode mousePressEvent and did not pass the event along to QAbstractItemView::mousePressEvent if I wanted to block the deselect. It did not occur to me to do anything to the event object itself. I'm guessing that was wrong. (I'm new to Qt.)
Yes, the point is valid. If you want to stop the propagation of the event, you are supposed to call
QEvent::acceptand do nothing. However any child widgets you may have are receiving the event before their parent, so it may or may not work.
@raven-worx Thanks. I ended up using this solution, which seems a bit more direct and focused than overriding "select".