Chief
Chief

Reputation: 191

How to get the Index from an Item in the QTreeView

My Qt-Application was built based on the EditableTreeModel example from Qt. In the TreeModel class there is a function called getItem() which takes the QModelIndex as a parameter and returns a TreeItem.

For my Application I need the reverse function: getting the QModelIndex from an TreeItem. This should be independent from the View. This means that I can't use the function QTreeView::currentIndex().

Is there any good solution for my problem?

Upvotes: 7

Views: 11756

Answers (2)

tunglt
tunglt

Reputation: 1072

You can build a map from TreeItem to QModelIndex as following :

    void buildMap(const QModelIndex &index, const QAbstractItemModel *model, QMap<TreeItem *, QModelIndex> &itemMap)
    {
            if( !index.isValid() )
                    return;

            TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
            itemMap.insert( item, index );

            int rows = model->rowCount(index);
            int cols = model->columnCount(index);

            for (int i = 0; i < rows; ++i)
                    for (int j = 0; j < cols; ++j){
                            QModelIndex idChild = model->index(i, j, index);
                            buildMap( idChild , model, itemMap );
                    }
    }

The function buildMap should be used as :

        QMap<TreeItem *, QModelIndex> itemMap;
        TreeModel *model = static_cast<TreeModel *>(view->model());

        for (int row = 0; row < model->rowCount(); ++row){
            buildMap( model->index(row,0), model, itemMap );
        }

        qDebug() << "Item map count : " << itemMap.count();

        foreach( TreeItem * item, itemMap.keys( )){
                qDebug() << "item " << item << " -> " << itemMap[ item ];
        }

Output:

    Item map count :  35
    item  0xbe1fe8  ->  QModelIndex(1,1,0xbe1fe8,TreeModel(0x4421390))
    item  0xbe2020  ->  QModelIndex(2,1,0xbe2020,TreeModel(0x4421390))
    item  0xbe22f8  ->  QModelIndex(3,1,0xbe22f8,TreeModel(0x4421390))
    item  0xbe2330  ->  QModelIndex(2,0,0xbe2330,TreeModel(0x4421390))
    ...

Upvotes: 0

Steve Lorimer
Steve Lorimer

Reputation: 28659

You need to call QAbstractItemModel::createIndex passing in the correct row, column and the item iteself.

The following should work:

QModelIndex TreeModel::indexForTreeItem(TreeItem* item)
{
    return createIndex(item->childNumber(), 0, item);
}

An explanation of how I came to this:

createIndex also takes a void* data pointer, which in the EditableTreeModel TreeModel example code, is a pointer to the TreeItem. You can see this is the case in the TreeModel::index member function:

QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) const
{
    if (parent.isValid() && parent.column() != 0)
        return QModelIndex();

    TreeItem *parentItem = getItem(parent);

    TreeItem *childItem = parentItem->child(row);
    if (childItem)
        return createIndex(row, column, childItem); // <-- here childItem is the TreeItem*
    else
        return QModelIndex();
}

Note that QAbstractItemModel::createIndex is a protected function, so you have to add a new member function to your TreeModel which creates the QModelIndex for you.

In order to calculate the row for a given TreeItem there is a member function childNumber which returns its index in its parent's list of children (ie: its row)

Unfortunately it is not possible to calculate the column for a given TreeItem, as a TreeItem contains all the data for its columns, so encompasses all columns. As such, a reasonable default would be to use 0 (the left-most column)

Upvotes: 5

Related Questions