I want to have a simple column header with a checkbox that selects/ deselects all rows in a QTableView. Clicking the check box in the header causes either to select or desel
I am surprised such a hacky solution is recommend and used.
First: The check state should be stored in the model. All the tools are already there.
bool MyModel::setHeaderData(int index, Qt::Orientation orient, const QVariant& val, int role)
{
if(Qt::Vertical != orient)
return Base::setHeaderData(index, orient, val, role);
storeCheckState(index, val);
emit headerDataChanged(orient, index, index);
return true;
}
QVariant MyModel::headerData(int index, Qt::Orientation o, int role) const
{
if(Qt::Vertical != orient)
return Base::headerData(index, o, role);
switch(role)
{
...
case Qt::CheckStateRole:
return fetchCheckState(index);
}
return Base::headerData(index, o, role);
}
Second: We toggle checked state simply by handling the click signal on the header.
connect(header, &QHeaderView::sectionClicked, receiver
, [receiver](int sec)
{
const auto index = logicalIndex(sec);
model()->setHeaderData(index
, Qt::Vertical
, Qt::CheckState(model()->headerData(index, Qt::Vertical, Qt::CheckStateRole).toUInt()) != Qt::Checked ? Qt::Checked : Qt::Unchecked
, Qt::CheckStateRole);
});
Third:
At this point we have fully functional checking behavior, only part missing is the visualization. The smartest way to go is to again use the model, taking advantage of the Qt::DecorationRole
. Here is a dummy implementation:
QVariant MyModel::headerData(int index, Qt::Orientation o, int role) const
{
if(Qt::Vertical != orient)
return Base::headerData(index, o, role);
switch(role)
{
case Qt::DecorationRole:
{
QPixmap p{12,12};
p.fill(Qt::CheckState(headerData(index, o, Qt::CheckStateRole).toUInt()) ? Qt::green : Qt::red);
return p;
}
break;
...
}
return Base::headerData(index, o, role);
}
Of course, one can draw a real checkbox there using the styled drawing.
Notice, this solution does not require sub-classing and custom widgets.
Also, the check state is decoupled from the view/UI. The only downside is fact the visuals are handled by the model, but this is optional - any way can be used to draw the check state, the one from the alternative answers included.