QTreeView::scrollTo not working

Qt 4.8

I have a QTreeView based class with an asociated QAbstractItemModel based class. If I reload the model with new information I want to expand/scroll the tree to a previous selected item.

Both clases, tree view and model are correctly created and connected using QTreeView::setSelectionModel(...) working everything properly.

After reloading the model, I get a valid index to the previous selected item and I scrollTo it:

myTreeView->scrollTo(index);

but the tree is not expanded. However, if I expand the tree manually, the item is really selected.

Tree view is initialized in contruct with:

header()->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
header()->setStretchLastSection(false);
header()->setResizeMode(0, QHeaderView::ResizeToContents);

Any idea about expanding the tree to the selection?

Answers


Even QTreeView::scrollTo documentation says:

Scroll the contents of the tree view until the given model item index is 
visible. The hint parameter specifies more precisely where the item should 
be located after the operation. If any of the parents of the model item 
are collapsed, they will be expanded to ensure that the model item is visible.

That is not really true (I think)

If solved the problem expanding all previous tree levels manually:

// This slot is invoqued from model using last selected item
void MyTreeWidget::ItemSelectedManually(const QModelIndex & ar_index)
{
    std::vector<std::pair<int, int> > indexes;

    // first of all, I save all item "offsets" relative to its parent

    QModelIndex indexAbobe = ar_index.parent();
    while (indexAbobe.isValid())
    {
        indexes.push_back(std::make_pair(indexAbobe.row(), indexAbobe.column()));
        indexAbobe = indexAbobe.parent();
    }

    // now, select actual selection model

    auto model = _viewer.selectionModel()->model();

    // get root item

    QModelIndex index = model->index(0, 0, QModelIndex());
    if (index.isValid())
    {
        // now, expand all items below

        for (auto it = indexes.rbegin(); it != indexes.rend() && index.isValid(); ++it)
        {
            auto row = (*it).first;
            auto colum = (*it).second;

            _viewer.setExpanded(index, true);

            // and get a new item relative to parent
            index = model->index(row, colum, index);
        }
    }

    // finally, scroll to real item, after expanding everything above.
    _viewer.scrollTo(ar_index);
}

I just dealt with similar situation, setting model index via setModelIndex (which internally ends up with scrollTo) worked OK for one of my models, but badly for the other one.

When I forcefully expanded all level 1 items, the scrollTo worked just as described above (calling expandAll suffices).

The reason was a bug in my model class in:

QModelIndex MyBadModel::parent(const QModelIndex& index) const

and as I fixed that, things got normal there too. The bug was such that internalId of parent model index was not the same as when this same model index (for parent) is calculated "from other direction", therefore in this model index (returned by parent method) could not be found in the list of visual indices.


QTreeView::scrollTo should expand the hierarchy appropriately.

It's likely that your QModelIndex object is being invalidated when the model is updated (and perhaps still selecting the correct row because the row information is still valid though the parentage is not, don't ask me how those internals work). From the QModelIndex documentation:

Note: Model indexes should be used immediately and then discarded. You should not rely on indexes to remain valid after calling model functions that change the structure of the model or delete items. If you need to keep a model index over time use a QPersistentModelIndex.

You can certainly look into the QPersistentModelIndex object, but like it says in its documentation:

It is good practice to check that persistent model indexes are valid before using them.

Otherwise, you can always query for that item again after the model refresh.


Everything was simple. Just change autoExpandDelay property from -1 to 0(for example).

ui->treeView->setAutoExpandDelay(0);

Need Your Help

Conditional try catch statement in matlab

matlab debugging try-catch

I am looking for an elegant way to use a conditional try catch statement.

Estimate color distribution with Gaussian mixture model

c++ opencv background-color video-capture gaussian

I am trying to use two Gaussian mixtures with EM algorithm to estimate color distribution of a video frame. For that, I want to use two separate peaks in the color distribution as the two Gaussian ...