Presetting a combobox to one of its tree view popup entry
-
Finally I found a way to make it work.
First I have created a subclass for QCombobox called TreeBox.TreeBox::TreeBox(QWidget *parent) : QComboBox(parent) { m_tree = new QTreeView; this->setView(m_tree); m_tree->setHeaderHidden(true); m_tree->viewport()->installEventFilter(this); }
Then in the class which is using the TreeBox I have declared a private property to keep track of the items added to the list view.
QVector<QStandardItem*> m_itemList; QStandardItemModel m_modelForTree;
In the ui I have added a ComboBox and promoted it to TreeBox.
Then I populate the tree model as follows and set the model to the ComboBox.QStandardItem *root = m_modelForTree.invisibleRootItem(); QStandardItem *item; for (int i=0; i<10; i++){ item = new QStandardItem(QString("item %0").arg(i)); m_itemList.append(item); root->appendRow(item); for(int j=0; j<5; j++){ item->setChild(j, 0, new QStandardItem(QString("item %0%1").arg(i).arg(j))); } } ui->comboBox->setModel(&m_modelForTree);
As an example I choose "item 43" to be set at the startup of this test program.
QString text = "item 43";
Then I loop through the QStandardListItems in m_itemList to find the QModelIndex of the item I want to preset.
bool textFound=false; QModelIndex modelIndex; for (int i=0; i<m_itemList.count(); i++){ for (int j=0; j<m_itemList[i]->rowCount(); j++){ modelIndex = m_modelForTree.indexFromItem(m_itemList[i]->child(j)); if (modelIndex.data(Qt::DisplayRole).toString()==text){ textFound = true; break; } } if (textFound) break; }
Now I can set the item as follows
ui->comboBox->setRootModelIndex(modelIndex.parent()); ui->comboBox->setCurrentIndex(modelIndex.row());
Unfortunately this restricts also the items displayed in the popup of the combobox to those of the current parent item.
To avoid this behavior I have to reset to the first QStandardItem in the list
modelIndex = m_modelForTree.indexFromItem(m_itemList[0]); ui->comboBox->setRootModelIndex(modelIndex.parent());
Now I get the behaviour I was looking for
Maybe there are simpler ways to do it and I would be glad if someone could come up with one.
But for the time being I just wanted to share this solution. -
Hi,
I have a combobox with a popup treeview as shown below.
I would like to set the combobox current item programmaticaly to one of the child items.How can I achieve that ?
-
But how do I get the index of an item? If I just now the name, for example "item 24", how can I get the index for it?
@Bert59
You must search the tree view items for the one matchingitem 24
. You could tryQComboBox::findText()
to do that, I don't know if it works for you but worth a try.If you say all you want to do is set the current item, have you tried simply
yourComboBox->setCurrentText("item 24")
? I don't know whether that will work with a tree view, and selecting a sub-item, but again worth a try? -
@Bert59
You must search the tree view items for the one matchingitem 24
. You could tryQComboBox::findText()
to do that, I don't know if it works for you but worth a try.If you say all you want to do is set the current item, have you tried simply
yourComboBox->setCurrentText("item 24")
? I don't know whether that will work with a tree view, and selecting a sub-item, but again worth a try? -
Thank you for the feedback.
Unfortunately both methods only work for the root items (item 2 for example) but not for the child items like "item 24".@Bert59
Yes I did wonder if that might be the case.That only means you cannot use the two quick
...text()
methods. Revert to what I said first (which is what...text()
methods would have to do internally anyway): search the tree view/model for the item you want. I assume you have tested thatsetCurrentIndex(7)
does indeed selectitem 24
correctly, so you know all you have to do is correctly find thatitem 24
is at item #7
and it will then select correctly? (If it does not do that, and actually selectsitem 7
which is presumably scrolled down at the bottom, then you have a problem....) -
setCurrentIndex(7) selects in fact "item 7".
I think I should use ui->comboBox->view()->setCurrentIndex(index);
But in this method index is a QModelIndex and so far I couldn't find a way to get the QModelIndex from the items name.
@Bert59 said in Presetting a combobox to one of its tree view popup entry:
setCurrentIndex(7) selects in fact "item 7".
Then you should stop and realise this is telling you your whole idea is flawed/does not work.
A
QComboBox
works from a single, integer index, not aQModelIndex
. Your finding shows that no value forQComboBox::setCurrentIndex()
is going to select a non-top-level item/node such asitem 24
. Rather, it only works on the top-level items, and that's all it will allow you to select/return as selected. Even if you finditem 24
'sQModelIndex
in the model, how will that help you select/return it in a combo box?QCombBox
only works for a "flat" list of items. Not some tree view hierarchy. Where did you get the idea from that you could make it work with a tree view? Have you found any code example anywhere which says that can be done? -
Finally I found a way to make it work.
First I have created a subclass for QCombobox called TreeBox.TreeBox::TreeBox(QWidget *parent) : QComboBox(parent) { m_tree = new QTreeView; this->setView(m_tree); m_tree->setHeaderHidden(true); m_tree->viewport()->installEventFilter(this); }
Then in the class which is using the TreeBox I have declared a private property to keep track of the items added to the list view.
QVector<QStandardItem*> m_itemList; QStandardItemModel m_modelForTree;
In the ui I have added a ComboBox and promoted it to TreeBox.
Then I populate the tree model as follows and set the model to the ComboBox.QStandardItem *root = m_modelForTree.invisibleRootItem(); QStandardItem *item; for (int i=0; i<10; i++){ item = new QStandardItem(QString("item %0").arg(i)); m_itemList.append(item); root->appendRow(item); for(int j=0; j<5; j++){ item->setChild(j, 0, new QStandardItem(QString("item %0%1").arg(i).arg(j))); } } ui->comboBox->setModel(&m_modelForTree);
As an example I choose "item 43" to be set at the startup of this test program.
QString text = "item 43";
Then I loop through the QStandardListItems in m_itemList to find the QModelIndex of the item I want to preset.
bool textFound=false; QModelIndex modelIndex; for (int i=0; i<m_itemList.count(); i++){ for (int j=0; j<m_itemList[i]->rowCount(); j++){ modelIndex = m_modelForTree.indexFromItem(m_itemList[i]->child(j)); if (modelIndex.data(Qt::DisplayRole).toString()==text){ textFound = true; break; } } if (textFound) break; }
Now I can set the item as follows
ui->comboBox->setRootModelIndex(modelIndex.parent()); ui->comboBox->setCurrentIndex(modelIndex.row());
Unfortunately this restricts also the items displayed in the popup of the combobox to those of the current parent item.
To avoid this behavior I have to reset to the first QStandardItem in the list
modelIndex = m_modelForTree.indexFromItem(m_itemList[0]); ui->comboBox->setRootModelIndex(modelIndex.parent());
Now I get the behaviour I was looking for
Maybe there are simpler ways to do it and I would be glad if someone could come up with one.
But for the time being I just wanted to share this solution. -
Finally I found a way to make it work.
First I have created a subclass for QCombobox called TreeBox.TreeBox::TreeBox(QWidget *parent) : QComboBox(parent) { m_tree = new QTreeView; this->setView(m_tree); m_tree->setHeaderHidden(true); m_tree->viewport()->installEventFilter(this); }
Then in the class which is using the TreeBox I have declared a private property to keep track of the items added to the list view.
QVector<QStandardItem*> m_itemList; QStandardItemModel m_modelForTree;
In the ui I have added a ComboBox and promoted it to TreeBox.
Then I populate the tree model as follows and set the model to the ComboBox.QStandardItem *root = m_modelForTree.invisibleRootItem(); QStandardItem *item; for (int i=0; i<10; i++){ item = new QStandardItem(QString("item %0").arg(i)); m_itemList.append(item); root->appendRow(item); for(int j=0; j<5; j++){ item->setChild(j, 0, new QStandardItem(QString("item %0%1").arg(i).arg(j))); } } ui->comboBox->setModel(&m_modelForTree);
As an example I choose "item 43" to be set at the startup of this test program.
QString text = "item 43";
Then I loop through the QStandardListItems in m_itemList to find the QModelIndex of the item I want to preset.
bool textFound=false; QModelIndex modelIndex; for (int i=0; i<m_itemList.count(); i++){ for (int j=0; j<m_itemList[i]->rowCount(); j++){ modelIndex = m_modelForTree.indexFromItem(m_itemList[i]->child(j)); if (modelIndex.data(Qt::DisplayRole).toString()==text){ textFound = true; break; } } if (textFound) break; }
Now I can set the item as follows
ui->comboBox->setRootModelIndex(modelIndex.parent()); ui->comboBox->setCurrentIndex(modelIndex.row());
Unfortunately this restricts also the items displayed in the popup of the combobox to those of the current parent item.
To avoid this behavior I have to reset to the first QStandardItem in the list
modelIndex = m_modelForTree.indexFromItem(m_itemList[0]); ui->comboBox->setRootModelIndex(modelIndex.parent());
Now I get the behaviour I was looking for
Maybe there are simpler ways to do it and I would be glad if someone could come up with one.
But for the time being I just wanted to share this solution. -
I know this is old but I just wanted to thank you for posting this solution. A QComboBox will absolutely accept a tree model and it is NOT a sign of incorrect design or usage. It is strange that QComboBox will accept a model as the source but not return a model index when queried, but swapping root model indices and setting the current row index worked perfectly!