Important: Please read the Qt Code of Conduct -

QListWidget: setSelectionModel stops emission of itemSelectionChanged signal

  • In my QListWidget subclass, when I replace its QItemSelectionModel using setSelectionModel, the list widget stops emitting its itemSelectionChanged signal. In the real code, I'm doing this to install a subclass of QItemSelectionModel, but the problem appears even if I use just a new QItemSelectionModel.

    MyListWidget::MyListWidget(QWidget* parent)
    	: QListWidget(parent)
    	QItemSelectionModel* oldSelectionModel = selectionModel();
    	QItemSelectionModel* newSelectionModel = new QItemSelectionModel(model(), oldSelectionModel->parent());

    In the debugger, I can see QItemSelectionModel emit its selectionChanged signal, but QListWidget never emits its corresponding itemSelectionChanged signal.

    If I comment out the body of this constructor, things work fine. As before, I can see QItemSelectionModel emit its selectionChanged signal, but now that triggers QListWidget to emit itemSelectionChanged.

    It looks as if my call to setSelectionModel causes the connection between QItemSelectionModel::selectionChanged and QListWidget::itemSelectionChanged to break.

    By the way, I checked to see if I'm passing the wrong arguments to the QItemSelectionModel constructor. After I create it, model() and parent() of newSelectionModel are identical to those of oldSelectionModel. I also tried commenting out the call to deleteLater, but that didn't help.

    Am I doing something wrong, or is this a Qt bug?

  • Moderators

    Almost certainly a bug. The problem is in void QListWidgetPrivate::setup() (called in the widget's constructor) where the list widget subscribes directly to the selection model. Here's the relevant code:

    QObject::connect(q->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
                     q, SLOT(_q_emitCurrentItemChanged(QModelIndex,QModelIndex)));
    QObject::connect(q->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
                     q, SIGNAL(itemSelectionChanged()));

    So when you change the selection model these two connections won't be available anymore. Note that the QListView is behaving correctly in its setSelectionModel() method, and reinitializes its own connections. Also, consider filing a bug report (you should be able to log in with your forum credentials).

    Kind regards.

  • @kshegunov Thank you. That was helpful. I did file a bug, which includes our proposed fix.

  • Moderators

    No problem. If you've edited the Qt sources fixing the bug, and have the time, you could also submit that patch through the gerrit code review, although it requires some work to clone/setup the repository.

    Kind regards.