Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 1

Qt-interest Archive, April 2008
Qt::ItemIsTristate - No Qt::PartiallyChecked in setData(...)


Message 1 in thread

I'm trying to add Tristate checkbox functionality to an existing  
QTreeView that uses my own model.  The problem is that I don't get  
Qt::PartiallyChecked values from the model's setData(...) method.  The  
only values I get for Qt::CheckStateRole are Qt::Unchecked and  
Qt::Checked.  How do you get Qt::PartiallyChecked values from  
setData(...)?

The flags that are set for my checkable items are as follows:

Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsTristate |  
Qt::ItemIsSelectable

Any ideas as to how I can get Qt::PartiallyChecked values from  
QAbstractItemModel::setData(...)?

Thanks.

Qt 4.4 Snapshot:  4.4.0-snapshot-20080229
Mac OS X 10.5.2
--
 [ signature omitted ] 

Message 2 in thread

On Thursday 03 April 2008 01:56:05 Dave Thorup wrote:
> Any ideas as to how I can get Qt::PartiallyChecked values from
> QAbstractItemModel::setData(...)?
Hi,

In your model you need to return values asscociated with the 
Qt::CheckStateRole. Just return the checkStateof the items in question. This 
does support the partially checked state. e.g.:

if ( index.column() == 0 && role == Qt::CheckStateRole )
{
    StructureModelNode* item = static_cast<StructureModelNode*>(
        index.internalPointer() );
    return item->checkState();
}

HTH,

Sean

--
 [ signature omitted ] 

Message 3 in thread

On Apr 3, 2008, at 4:01 AM, Sean Harmer wrote:
> On Thursday 03 April 2008 01:56:05 Dave Thorup wrote:
>> Any ideas as to how I can get Qt::PartiallyChecked values from
>> QAbstractItemModel::setData(...)?
> Hi,
>
> In your model you need to return values asscociated with the
> Qt::CheckStateRole. Just return the checkStateof the items in  
> question. This
> does support the partially checked state. e.g.:


I'm not having any problems displaying checkboxes using the  
Qt::PartiallyChecked state (which does not require the  
Qt::ItemIsTristate flag).  The problem is that in calls to  
QAbstractItemModel::setData(...) the values that are passed by  
setData(...) are only Qt::Unchecked and Qt::Checked,  
Qt::PartiallyChecked is never passed to setData(...) and thus I can  
never set the data in my model to Qt::PartiallyChecked.

This is in stark contrast to how QCheckBoxes work.  If you set a  
checkbox to be Tristate ( setTristate( true ) ), then the checkbox  
will cycle between the three states when you click on it.  The same  
should also be true for an ItemView when its model returns the  
"Qt::ItemIsUserCheckable | Qt::ItemIsTristate" flags for a given  
item.  Apparently this is not the case, you only get two states in an  
ItemView - Qt::Unchecked and Qt::Checked - even if you use the flag  
Qt::ItemIsTristate.
--
 [ signature omitted ] 

Message 4 in thread

Dave Thorup wrote:
> I'm not having any problems displaying checkboxes using the 
> Qt::PartiallyChecked state (which does not require the 
> Qt::ItemIsTristate flag).  The problem is that in calls to 
> QAbstractItemModel::setData(...) the values that are passed by 
> setData(...) are only Qt::Unchecked and Qt::Checked, 
> Qt::PartiallyChecked is never passed to setData(...) and thus I can 
> never set the data in my model to Qt::PartiallyChecked.
Ah OK sorry I misunderstood the problem. What we have done in the past 
is to only use the partially checked state when a subset of the children 
of a parent item are checked and the rest are unchecked/partially 
checked. To do this you have to recurse up the hierarchy of items when 
setData() is called on a child to change the check state.

We also implemented it in the other direction. That is, when the parent 
is checked or unchecked we recurse down through its children and check 
or uncheck them respectively.
> This is in stark contrast to how QCheckBoxes work.  If you set a 
> checkbox to be Tristate ( setTristate( true ) ), then the checkbox 
> will cycle between the three states when you click on it.  The same 
> should also be true for an ItemView when its model returns the 
> "Qt::ItemIsUserCheckable | Qt::ItemIsTristate" flags for a given 
> item.  Apparently this is not the case, you only get two states in an 
> ItemView - Qt::Unchecked and Qt::Checked - even if you use the flag 
> Qt::ItemIsTristate.
I don't know that what you are after here is possible. But I could well 
be wrong.

Cheers,

Sean

--
 [ signature omitted ] 

Message 5 in thread

On Apr 3, 2008, at 3:01 PM, Sean Harmer wrote:

> Dave Thorup wrote:
>> I'm not having any problems displaying checkboxes using the  
>> Qt::PartiallyChecked state (which does not require the  
>> Qt::ItemIsTristate flag).  The problem is that in calls to  
>> QAbstractItemModel::setData(...) the values that are passed by  
>> setData(...) are only Qt::Unchecked and Qt::Checked,  
>> Qt::PartiallyChecked is never passed to setData(...) and thus I can  
>> never set the data in my model to Qt::PartiallyChecked.
> Ah OK sorry I misunderstood the problem. What we have done in the  
> past is to only use the partially checked state when a subset of the  
> children of a parent item are checked and the rest are unchecked/ 
> partially checked. To do this you have to recurse up the hierarchy  
> of items when setData() is called on a child to change the check  
> state.
>
> We also implemented it in the other direction. That is, when the  
> parent is checked or unchecked we recurse down through its children  
> and check or uncheck them respectively.

This is what I've been doing as well and it's been working well.   
However, I wanted to add the ability for the user to cycle between  
Checked, Unchecked & Partially Checked when the default state of a  
parent has some of its children checked.  i.e.  Only when clicking on  
a parent item that has children would the user be allowed to set the  
Partially Checked state.  In that case when going from all children  
unchecked to the partially checked state, the children's check state  
would be set to their default state and the parent item would display  
Partially Checked (if some of the children's default states are  
unchecked).

>
>> This is in stark contrast to how QCheckBoxes work.  If you set a  
>> checkbox to be Tristate ( setTristate( true ) ), then the checkbox  
>> will cycle between the three states when you click on it.  The same  
>> should also be true for an ItemView when its model returns the  
>> "Qt::ItemIsUserCheckable | Qt::ItemIsTristate" flags for a given  
>> item.  Apparently this is not the case, you only get two states in  
>> an ItemView - Qt::Unchecked and Qt::Checked - even if you use the  
>> flag Qt::ItemIsTristate.
> I don't know that what you are after here is possible. But I could  
> well be wrong.


I found the solution and apparently this is a bug that for whatever  
reason won't be fixed:

http://trolltech.com/developer/task-tracker/index_html?method=entry&id=108755

Apparently you have to create your own QItemDelegate for your item  
view in order to get the correct behavior.  I don't understand how  
they can dismiss this as something that they won't fix since it  
doesn't even work in the way they describe in the bug report:

After returning the Qt::ItemIsTristate flag from  
QAbstractTableModel::flags(....) , the supplied checkboxs do not  
possess tristate functionality.

Won't fix:
The intended usage of Qt::ItemIsTristate is to signify that the  
checked state of an item should be computed as a function of the  
checked states of its child items; e.g. no child items checked =>  
parent becomes unchecked; some child items checked => parent is  
partially checked; all child items checked => parent item checked.  
Therefore, the default item delegate does not have provisions for  
interactive partial checking of items. However, you can reimplement  
QItemDelegate::editorEvent() and change the behavior to what you want,  
for example like this:

The "intended usage" that they describe is not how Item Views actually  
work.  If you have an Item View and your own Model then it's up to you  
to return the proper check state regardless of whether you set the  
Qt::ItemIsTristate flag.  For example, if you have a parent where some  
of it's children are checked and some are not and you use the  
Qt::ItemIsTristate flag then the parent's check state will not  
magically be set to partially checked, it will be set to whatever your  
model returns - checked, unchecked or partially check - which is as it  
should be.  The Qt::ItemIsTristate shouldn't magically override how  
your model works, it should allow the default QItemDelegate to send  
the 3 check states to your model's setData(...) method just as  
QCheckBox::setTristate( true) works.  I don't understand how this  
can't be seen as a bug.
--
 [ signature omitted ]