8

I want to fire QAbstractItemView::doubleClicked slot programaticaly for an item that has specific text. I want to do this using QAbstractItemView class and not it's implementations if possible.

This task boils down to looping over items and comparing strings. But I cannot find any method that would give me all QModelIndexes. The only method that gives any QModelIndex without parameters is QAbstractItemView::rootIndex. But when I look into QModelIndex docs, I again cannot see a way to access it's children and siblings.

So how to access all QModelIndexes in QAbstractItemView?

Tomáš Zato
  • 50,171
  • 52
  • 268
  • 778

1 Answers1

17

The indexes are provided by the model, not by the view. The view provides the rootIndex() to indicate what node in the model it considers as root; it might be an invalid index. Otherwise it has nothing to do with the data. You have to traverse the model itself - you can get it from view->model().

Here's a depth-first walk through a model:

void iterate(const QModelIndex & index, const QAbstractItemModel * model,
             const std::function<void(const QModelIndex&, int)> & fun,
             int depth = 0)
{
    if (index.isValid())
        fun(index, depth);
    if ((index.flags() & Qt::ItemNeverHasChildren) || !model->hasChildren(index)) return;
    auto rows = model->rowCount(index);
    auto cols = model->columnCount(index);
    for (int i = 0; i < rows; ++i)
        for (int j = 0; j < cols; ++j)
            iterate(model->index(i, j, index), model, fun, depth+1);
}

The functor fun gets invoked for every item in the model, starting at root and going in depth-row-column order.

E.g.

void dumpData(QAbstractItemView * view) {
    iterate(view->rootIndex(), view->model(), [](const QModelIndex & idx, int depth){
        qDebug() << depth << ":" << idx.row() << "," << idx.column() << "=" << idx.data();
    });
}
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
  • 1
    Much C++11. Very recursive. Wow. Thanks. I have one question though. I am trying to adopt your code in less modern way (eg. no C++11), but I have no clue what `auto model = index();` is. `QModelIndex` doesn't seem to have `operator()`... Could you explain the code please? – Tomáš Zato Aug 25 '16 at 20:57
  • I fixed the typos. You'd have probably deduced what it was if you have read [this informative page](http://doc.qt.io/qt-5/qmodelindex-members.html) while keeping in mind what you're looking for: how to get a model from an index. – Kuba hasn't forgotten Monica Aug 25 '16 at 21:00
  • I would probably have deduced if I wasn't tired. I read through the page - I said so in the OP... – Tomáš Zato Aug 25 '16 at 21:04
  • I'm sorry, this came out harsher than I meant. Take care and get rest when you can. – Kuba hasn't forgotten Monica Aug 25 '16 at 21:23
  • I'm not so sure if it's even in the scope of the question, but for `QTreeWidget` I get invalid index when I call `rootIndex`. Docs state that it can be invalid, but my widget has two items. Is that normal behavior? – Tomáš Zato Aug 25 '16 at 22:51
  • 1
    You're right that I didn't take care of an invalid index. See the edit. An invalid index is the root of a hierarchy. Unfortunately, there's no `QModelIndex(QAbstractItemModel*)` constructor. So it won't have its `model` set, and you can't depend on the `child` member to work. Thus `iterate` must be passed a model explicitly, because the one in index won't be valid at the base of the tree. – Kuba hasn't forgotten Monica Aug 26 '16 at 13:12