This can be done if you're willing to accept a shameless hack :-)
Assuming the following code...
QFileDialog fd;
Inspecting fd
using fd.findChildren<QListView *>()
reveals that it has two children that either are or inherit from QListView
...
- QListView named listView
- QSidebar named sidebar
(where QSidebar is private to Qt).
Working on the assumption that the QListView
named listView
is the widget of interest you can connect a callback to its selection model...
QFileDialog fd;
for (const auto &i: fd.findChildren<QListView *>("listView")) {
auto *sm = i->selectionModel();
QObject::connect(sm, &QItemSelectionModel::selectionChanged,
[sm](const QItemSelection &selected, const QItemSelection &deselected)
{
/*
* Here we pass a hard-coded max selected items
* value of 5 to the real callback/slot.
*/
handle_selection_updated(5, sm, selected, deselected);
});
}
Here handle_selection_updated
has the following definition...
void handle_selection_updated (int selection_max, QItemSelectionModel *sm,
const QItemSelection &selected,
const QItemSelection &deselected)
{
/*
* We need to remember the last valid selection. The following
* is declared static in this simple case but would generally be
* a class member in `real' code.
*/
static QItemSelection last_selected;
/*
* Because we update the selection model `sm' from within this
* slot this function will recurse which will cause problems if
* we don't detect it and take appropriate action.
*/
static bool recursing = false;
if (recursing)
return;
/*
* If the number of rows selected is greater than the value
* specified by `selection_max' then revert to the last valid
* selection as specified by `last_selected'.
*/
if (sm->selectedRows().size() > selection_max) {
/*
* The following call to QItemSelectionModel::clearSelection
* will result in a recursive call to this function. Set
* `recursing' to true to catch this and avoid associated
* problems.
*/
recursing = true;
/*
* Now clear the selection and reset it to the items from
* `last_selected'.
*/
sm->clearSelection();
for (const auto &i: last_selected.indexes()) {
sm->select(i, QItemSelectionModel::Select);
}
recursing = false;
}
/*
* Update `last_selected'.
*/
last_selected = sm->selection();
}
I've only tested the above code briefly but it appears to behave in the manner required.