[Qt-interest] Qt::CheckStateRole
Sean Harmer
sean.harmer at maps-technology.com
Thu Sep 17 10:22:47 CEST 2009
Hi,
On Thursday 17 Sep 2009 02:06:56 Willy P wrote:
> I've implemented my own model by inheriting from QAbstractItemModel
> and my own view by inheriting from QTreeView. I've got all the
> parents and children showing up and I've got checkboxes showing up
> next to them in their proper state. Checking and unchecking items is
> properly setting the values in the model, but they're not cascading up
> the chain to the parents. In other words, in the view, a parent's
> check state is not Qt::PartiallyChecked when only some of it's
> children are checked. How do I get the automatic updating of parent's
> and children's checkboxes? Or do I have to do that myself?
>
> Thanks in advance...
I think you have to do this yourself. Here is some snippets of how I did it a
couple of years ago. (Bear in mind I was still learning the model/view API
then so there may be a better way of doing this).
In your model's setData function have a section like this:
bool MyModel::setData( const QModelIndex& index, const QVariant& value, int
role )
{
if ( role == Qt::CheckStateRole )
{
Node* item = static_cast<Node*>( index.internalPointer() );
Qt::CheckState state = Qt::Checked;
if ( item->checkState() == Qt::Checked )
state = Qt::Unchecked;
item->setCheckState( state );
if ( item->itemType() == Node::File )
{
QModelIndex highestChanged = propagateCheckStateToRoot( index,
state );
emit dataChanged( highestChanged, index );
emit layoutChanged();
}
else
{
// For (un)checking a group we must recurse down and apply the
// change to all children too
QModelIndex lowestChanged;
QModelIndex highestChanged =
propagateCheckStateToLeaves( index, lowestChanged,
state,true);
emit dataChanged( highestChanged, lowestChanged );
emit layoutChanged();
}
return true;
}
return false;
}
This assumes that we have two types of node in our model leaf nodes and
grouping nodes and takes care of calling either propagateCheckStateToLeaves or
propagateCheckStateToRoot as needed. The implementation of these functions
are:
QModelIndex MyModel::propagateCheckStateToRoot( const QModelIndex& index,
Qt::CheckState state )
{
QModelIndex parent = index.parent();
if ( parent.isValid() )
{
Node* parentItem = static_cast<Node*>( parent.internalPointer() );
Qt::CheckState parentState = parentItem->checkState();
if ( !childrenAllSameSelectionState( parent ) )
state = Qt::PartiallyChecked;
if ( parentState != state )
{
setCheckState( parent, state );
return propagateCheckStateToRoot( parent, state );
}
return index;
}
return parent;
}
QModelIndex MyModel::propagateCheckStateToLeaves( const QModelIndex& index,
QModelIndex& lowest, Qt::CheckState state, bool initiator )
{
if ( hasChildren( index ) )
{
// Recurse this call into the children
for ( int i = 0; i < rowCount( index ); i++ )
{
QModelIndex child = MyModel::index( i, 0, index );
propagateCheckStateToLeaves( child, lowest, state );
}
}
else
{
// The item referenced by index has no children.
// Set the state and record the index
setCheckState( index, state );
lowest = index;
}
if ( initiator )
return propagateCheckStateToRoot( index, state );
return index;
}
And finally these function use a couple of small helpers:
bool MyModel::childrenAllSameSelectionState( const QModelIndex& parent ) const
{
if ( !parent.isValid() )
return false;
Node* parentItem = static_cast<Node*>( parent.internalPointer() );
if ( parentItem->itemType() != Node::Group )
return false;
GroupItem* group = static_cast<GroupItem*>( parentItem );
if ( group->childCount() == 0 || group->childCount() == 1 )
return true;
Qt::CheckState state = group->child( 0 )->checkState();
for ( int i = 1; i < group->childCount(); i++ )
{
if ( group->child( i )->checkState() != state )
return false;
}
return true;
}
void MyModel::setCheckState( const QModelIndex& index, Qt::CheckState state )
{
if ( !index.isValid() )
return;
Node* item = static_cast<Node*>( index.internalPointer() );
item->setCheckState( state );
}
Anyway, you should be able to get the idea from this and port it to your
specific case.
HTH,
Sean
More information about the Qt-interest-old
mailing list