Reputation: 181
I'm writing an application that has a QTreeWidget that is populated by parsing an XML file containing the tree levels. If I select a top level checkbox, I need all of the sub-level checkboxes to be checked also.
I already have the XML parser working and populating the QTreeWidget with QTreeWidgetItems that have checkboxes but they can only be individually checked.
Upvotes: 3
Views: 6207
Reputation: 382
This appears still quite high in search engines, and is outdated. Just set the flag Qt::ItemIsAutoTristate on your top-level item.
Upvotes: 5
Reputation: 9251
To do this, keep the code you have to generate the tree with your XML. Then connect to the itemChanged() signal and update the check states in a slot. It should look something like:
connect(treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*, int)),
this, SLOT(updateChecks(QTreeWidgetItem*, int)));
void ClassName::updateChecks(QTreewidgetItem* item, int column)
{
// Checkstate is stored on column 0
if(column != 0)
return;
recursiveChecks(item);
}
void ClassName::recursiveChecks(QTreeWidgetItem* parent)
{
Qt::CheckState checkState = parent->checkState(0);
for(int i = 0; i < parent->childCount(); ++i)
{
parent->child(i)->setCheckState(0, checkState);
recursiveChecks(parent->child(i));
}
}
A few notes to consider:
Upvotes: 6
Reputation: 303
I just worked on this a little and got nice results based on Rick's answer. Maybe it can help other out there. It updates the state of parents and children with a tristate status for parents only (checked, unchecked, partially-checked).
void ClassName::updateChecks(QTreeWidgetItem *item, int column)
{
bool diff = false;
if(column != 0 && column!=-1)
return;
if(item->childCount()!=0 && item->checkState(0)!=Qt::PartiallyChecked && column!=-1){
Qt::CheckState checkState = item->checkState(0);
for (int i = 0; i < item->childCount(); ++i) {
item->child(i)->setCheckState(0, checkState);
}
} else if (item->childCount()==0 || column==-1) {
if(item->parent()==0)
return;
for (int j = 0; j < item->parent()->childCount(); ++j) {
if(j != item->parent()->indexOfChild(item) && item->checkState(0)!=item->parent()->child(j)->checkState(0)){
diff = true;
}
}
if(diff)
item->parent()->setCheckState(0,Qt::PartiallyChecked);
else
item->parent()->setCheckState(0,item->checkState(0));
if(item->parent()!=0)
updateChecks(item->parent(),-1);
}
}
Doesn't need recursiveChecks() anymore. Connect between the treeWidget and updateChecks still active.
Upvotes: 4