Denis Rouzaud
Denis Rouzaud

Reputation: 2630

programmatically check items in a QAbstractItemModel / QTreeView

I am trying to use a selection (QModelIndexList) to check all the selected items of a QTreeView.

I use setData with the Qt::CheckStateRole on the indexes and the data seems updated. I am emitting dataChanged signal but the tree is not redrawn (with and without the role given as argument). Is this an issue of the selection model?

It works if I do beginResetModel but my tree gets collapsed which a deal breaker.

How can I manage to get my item repainted?

Here is the method I added in my model

void MyModel::checkSelectedItems( const QModelIndexList &checkedIndexes, bool check )
{
    QVector<int> roles = QVector<int>() << Qt::CheckStateRole;
  for ( const QModelIndex &index : checkedIndexes)
  {
      setData(index, check ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole);
      emit dataChanged(index, index); //), roles);
  }
}

and the call to it:

myModel->checkSelectedItems( myTree->selectionModel()->selectedIndexes(), true );

After the call, the selection is grey (and not blue anymore) but still "selected". Clicking anywhere refresh the tree and correctly shows the checked items.

Upvotes: 1

Views: 816

Answers (1)

The code you show works mostly fine in spite of being incorrect. Please amend the question to include a reproduction case. But yes, the code does have problems.

It is in setData's contract to emit the dataChanged signal; any code where dataChanged is emitted outside of setData indicates a broken implementation of the model. You should move the signal emission to MyModel::setData. The only other place where it'd be valid to emit dataChanged is in a slot/functor in a proxy model, but only when the slot/functor is connected to the sourceModel's dataChanged signal.

myTree->repaint() solved the issue

Invoking repaint() or update() outside of a widget's implementation is almost always an error, and indicates that the widget is either not used properly or is not implemented properly. In your case, it's the former: the model's setData is broken and doesn't emit dataChanged.

For inspiration on how such a test case might look like, see e.g. this answer. In a nutshell: aim for 100 lines or less, single file, #include <QtWidgets> at the beginning, no unnecessary code nor boilerplate. Make it sweet and simple :)

Upvotes: 0

Related Questions