How to access childWidgets in a QTreeView using QModelIndex?

1.6k views Asked by At

I'm working on an application using the Qt library (version 4.8).

I have a QTreeView with a QStandardItemModel. My widget looks like that:

Item1

subitem11

subitem12

Item2

subitem21

subitem22

Item3

subitem31

subitem32

Here is how I add the items to my QTreeView:

 model->setItem(0, 0, item1); 
 item1->setChild(0, 0, subitem12);

I want to take an action only when the user double cliked an item (and do nothing when he clicked a subitem). So I use the doubleClicked(const QModelIndex & index) signal.

I want to process the information about the item/subitem which was double cliked by the user. So I get the row of my item/subitem:

index.row();

But every time I try to reference to the item/subitem to display its name or check if it has children, I can only access the items:

index.model()->item(row)->text();

My question is: how can I acces the subitems (vbetween items abd subitems) in my slot? Or how can I prevent them from emitting the signal? I can't disable them - it would be too confusing for the user.

Edit: The problem is that every time I click on an item or subitem and execute:

index.model()->item(row)->hasChildren();

or:

index.model()->item(row)->parent() == 0;

I get true as result. So I can reference only the items.

My question is: What is the correct way to reference to subitems?

3

There are 3 answers

1
JvO On

You can't disable the signal for the subitems. However, you can check if an item has a parent. It it doesn't, it is an item and if it does, it's a subitem.

if (item->parent() != 0)
   .. //subitem
else
   .. //item

An alternative would be to use the data() function to set some special value to distinguish between the two.

item1->setData(QVariant("item"));
subitem1->setData(QVariant("subitem"));

Then query the value in your doubleclick handler:

QVariant var = item->data();
if (var.toString() == "item")
  ...
else if (var.toString() == "subitem")
  ...
2
Georgy Pashkov On

When you are trying to access model items by row index, the model returns top-level item at that row. Use itemFromIndex instead:

auto item = index.model()->itemFromIndex(index);
if (item && item->hasChildren()){
    // item is not a leaf
}

EDIT index.model() returns QAbstractItemModel*, so a cast is also necessary here (or, better, storing a pointer to the standard model somehwere in the code).

0
Tomas On

I would do it like this:

// Define your custom role to store item type.
enum MyRoles
{
    ItemTypeRole = Qt::UserRole + 1
};

// Define item types.
enum ItemType
{
    Primary,
    Secondary
};

Than set the proper item type for all your items:

QStandardItem* item = new QStandardItem("Item1");
item->setData(Primary, ItemTypeRole);

QStandardItem* subItem = new QStandardItem("SubItem1");
subItem->setData(Secondary, ItemTypeRole);

And in your slot connected to the doubleClicked signal acces the type like this:

ItemType type = static_cast<ItemType>(index.data(ItemTypeRole).toInt());
if (type == Primary)
    std::cout << "It's a Primary item!" << std::endl;
else if (type == Secondary)
    std::cout << "It's a Secondary item!" << std::endl;