[Qt-interest] Qt::CheckStateRole
Willy P
willy.lists at gmail.com
Fri Sep 18 07:58:01 CEST 2009
Thanks all! I ended up doing it myself and it wasn't that bad,
similar to your approach Sean. Appreciate the help.
-Willy
On Thu, Sep 17, 2009 at 1:22 AM, Sean Harmer
<sean.harmer at maps-technology.com> wrote:
> 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
> _______________________________________________
> Qt-interest mailing list
> Qt-interest at trolltech.com
> http://lists.trolltech.com/mailman/listinfo/qt-interest
>
More information about the Qt-interest-old
mailing list