Search code examples
c++qtqtreeviewqcomboboxqstandarditemmodel

How to select item in QComboBox with QTreeView


I was trying to select item "leaf2" from QComboBox with QTreeView in the below code.

I just want to select items with no child from text by code. (if there is a child, it won't be selectable)

How can I select item or index with no child item?

Can anyone help me with this problem?

Thank you.

void Main::initView()
{
    QStandardItemModel *model = new QStandardItemModel;
    QStandardItem *root_item = model->invisibleRootItem();

    // Build Model Items
    QStandardItem *node_item = NULL;
    node_item = new QStandardItem("Node");
    node_item->setFlags(Qt::ItemIsEnabled);
    root_item->appendRow(node_item);

    QStandardItem *leaf_item = new QStandardItem("leaf1");
    leaf_item ->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
    node_item->appendRow(leaf_item );

    leaf_item = new QStandardItem("leaf2");
    leaf_item ->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
    node_item->appendRow(leaf_item );

    // Set Model to TreeViewComboBox
    ui.cb_treevew->setModel(model);

    ui.cb_treeview->setCurrentIndex(0); // "Node" is selected.
    ui.cb_treeview->setCurrentIndex(1); // Nothing is selected.
    ui.cb_treeview->setCurrentIndex(2); // Nothing is selected.
    ui.cb_treeview->setCurrentIndex(3); // Nothing is selected.
}

Here is my code for CTreeViewComboBox.

CTreeViewComboBox::CTreeViewComboBox(QWidget *parent) : QComboBox(parent)
{
    QTreeView* treeView = new QTreeView(this);
    treeView->setEditTriggers(QTreeView::NoEditTriggers);
    treeView->setSelectionBehavior(QTreeView::SelectRows);
    treeView->setSelectionMode(QTreeView::SingleSelection);
    treeView->setItemsExpandable(true);
    treeView->header()->setVisible(false);
    treeView->setWordWrap(true);
    setView(treeView);
}

PS: I tried to select items as following, but not working. :(

ui.cb_treeview->treeView()->setCurrentIndex(getModelIndexFromText("leaf2"));

Solution

  • If the nodes with children will never have the same text with the nodes without children then the following method is appropriate.

    QModelIndexList modelIndexes = model->match(
                model->index(0, 0),
                Qt::DisplayRole,
                "leaf2",
                -1,
                Qt::MatchRecursive);
    QModelIndex index = modelIndexes.first();
    ui.cb_treeview.setRootModelIndex(index.parent());
    ui.cb_treeview.setCurrentIndex(index.row());
    

    On the other hand, if the nodes with children can have the same text as the nodes without children, you should use the following method.

    QModelIndexList modelIndexes = model->match(
                model->index(0, 0),
                Qt::DisplayRole,
                "leaf2",
                -1,
                Qt::MatchRecursive);
    
    QModelIndexList::iterator tstIt = std::find_if(modelIndexes.begin(),
                                             modelIndexes.end(),
                                             [] (const QModelIndex & index) {
        return !index.model()->hasChildren(index);
    });
    
    ui.cb_treeview.setRootModelIndex(tstIt->parent());
    ui.cb_treeview.setCurrentIndex(tstIt->row());
    

    In both cases I am assuming that nodes without children always have different texts. If nodes without children match the name, choose one of them.