Expand all QTreeWidget items and hide all expansion indicators



  • I have a sample application which displays a QTreeWidget with a number of levels, and sets them all expanded.

    Basic setup:

    The following works as expected:

    1. Create the QTreeWidget and set as central widget:

    QMainWindow* main_window = new QMainWindow();
    QTreeWidget* tree = new QTreeWidget();
    
    main_window->setCentralWidget(tree);
    

    2. Create some sample data which will be used to create the items in the tree:

    std::vector<std::vector<std::string>> fields = {
    	{ "foo" },
    	{ "bar", "baz", "fizz", "buzz" },
    	{ "apples", "oranges" }
    };
    

    3. Loop over the sample data, creating QTreeWidgetItems:

    QTreeWidgetItem* parent = nullptr;
    QTreeWidgetItem* item   = nullptr;
    
    for (auto& level : fields)
    {
    	for (auto& field : level)
    	{
    		if (!parent)
    			item = new QTreeWidgetItem(tree, { QString::fromStdString(field) });
    		else
    			item = new QTreeWidgetItem(parent, { QString::fromStdString(field) });
    
    	}
    	parent = item;
    }
    

    4. Set the header and expand all the nodes:

    tree->setHeaderLabels({ "fields" });
    tree->expandAll();
    

    This correctly populates the tree, and the resulting window looks like this:

    tree expanded

    Hide the expansion indicators

    I don't want the user to be able to collapse the nodes, so I use setchildIndicatorPolicy:

    QTreeWidgetItem* last = tree->topLevelItem(tree->topLevelItemCount() - 1);
    while(last)
    {
    	last->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicator);
    	last = last->child(last->childCount() - 1);
    }
    

    However, doing this hides all the children below the first level

    DontShowIndicator

    The documentation for QTreeWidgetItem::DontShowIndicator says

    The controls for expanding and collapsing will never be shown even if there are children. If the node is forced open the user will not be able to expand or collapse the item.

    Force the node open

    So I update the code to set the item expanded

    QTreeWidgetItem* last = tree->topLevelItem(tree->topLevelItemCount() - 1);
    while(last)
    {
    	last->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicator);
    	last->setExpanded(true);
    
    	last = last->child(last->childCount() - 1);
    }
    

    That makes no difference

    ForcedOpen

    Expanding the node before I set the ChildIndicatorPolicy doesn't work either

    QTreeWidgetItem* last = tree->topLevelItem(tree->topLevelItemCount() - 1);
    while(last)
    {
    	last->setExpanded(true);
    	last->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicator);
    
    	last = last->child(last->childCount() - 1);
    }
    

    ForcedOpenBefore

    Question:

    How can I set all my nodes expanded, and show no expansion indicators?


  • Lifetime Qt Champion

    Hi,

    That kinda looks like a bug... Did you check the bug report system ?



  • I found the following in the source, which definitely doesn't look correct.

    bool QTreeModel::hasChildren(const QModelIndex &parent) const
    {
        if (!parent.isValid())
            return (rootItem->childCount() > 0);
    
        QTreeWidgetItem *itm = item(parent);
        if (!itm)
            return false;
        switch (itm->d->policy) {
        case QTreeWidgetItem::ShowIndicator:
            return true;
        case QTreeWidgetItem::DontShowIndicator:
            return false;
        case QTreeWidgetItem::DontShowIndicatorWhenChildless:
            return (itm->childCount() > 0);
        }
        return false;
    }
    

    I haven't found everything which calls hasChildren, but the name of the function does stand out as making this look like it could be a bug.

    I'll report a bug


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.