Strange behavior QTreeView

  • Hello everyone

    I have some difficult to understanding how the QTreeView work with QAbstractItemModel and what functions it calls.
    To test, I created a simple class that inherits from QAbstractItemModel and contains a tree (using QStandardItemModel). My class simply calls the function of QStandardItemModel. For example, for data ():
    @QVariant TableToTreeProxyModel::data(const QModelIndex &index, int role) const
    return sourceModel()->data(index, role);

    I have overloaded functions that normally should be:
    @QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
    QModelIndex parent(const QModelIndex &child) const;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
    int rowCount(const QModelIndex &parent) const;
    int columnCount(const QModelIndex &parent) const;
    Qt::ItemFlags flags(const QModelIndex &index) const;@

    I also draw my tree with a simple recursive function that uses data(), hasChildren(), rowCoun () and index() functions:
    @void drawTree(QAbstractItemModel* tree, QModelIndex const& parent, int level)
    QString s = "";
    QString t = s.rightJustified(level*2, ' ');
    qDebug() << t + tree->data(parent).toString();
    if (tree->hasChildren(parent))
    for (int row = 0; row < tree->rowCount(parent); ++row )
    drawTree(tree, tree->index(row, 0, parent), level+1);

    Unfortunately, when I try to view my tree in a QTreeView, nothing is displayed (while the QStandardItemModel displayed properly).

    An idea of ​​what I forgot?

    thank you

    PS: I also tried using a QAbstractProxyModel unsuccessfully while a QSortFilterProxyModel works.

  • The QModelIndex you pass as argument to sourceModel()->data() must come from sourceModel(), not from your proxy model.
    So you have somehow to map your indexes to the sourceModel() indexes (that's what mapFromSource and mapToSource are for in QAbstractProxyModel).

  • Thanks for the answer

    All QModelIndex was created using sourceModel() in index() function et QModelIndex::model() return the internal QStandardItemModel. I have shown only data() function but I have wrote all listed functions (index, parent, data, rowCount, columnCount and flags) with similar implementation.

    I think the problem is not there (or so I did not understand)

  • I think, you didn't want to implement a proxy model, right?
    have a look at "the Qt docs": or, if you understand German, at "the German wiki":

  • Thanks

    I have read the doc.

    yes, it's a proxy that I want to implement. My ultimate goal is to convert a TableModel in TreeModel using two columns of the table (one for id and one for the id of the parent). I have implemented this class, starting from QAbstractProxyModel but it didn't work. Yet when I was testing my tree generated, it was correct. So I tried starting from QAbstractItemModel. But it did not work either. So I tried too a QAbstractItemModel which is supposed to be a simple warper of model. But this doesn't work (this is the code that I gave).
    So I guess I missed something but I can not find anything.

    (I have write a class to create a new tree model from table model ans that work. But here, I want to map table and tree items)

  • QTreeView uses some QModelIndex functions, like row()/column() or parent() and they return the index position and parent index in the source model which is flat (if I understood correctly), and not its position in your proxy model.

    Can you show your implementation of rowCount ?

  • Sorry, my English is not perfect and I was not necessarily clear.
    My model is supposed to do anything, just call the functions of the model. And when I call the function drawTree(), the tree displays correctly. There is no position in my model proxy.

    @QModelIndex TableToTreeProxyModel::index(int row, int column, const QModelIndex &parent) const
    return sourceModel()->index(row, column, parent);

    QModelIndex TableToTreeProxyModel::parent(const QModelIndex &child) const
    return sourceModel()->parent(child);

    QVariant TableToTreeProxyModel::data(const QModelIndex &index, int role) const
    return sourceModel()->data(index, role);

    int TableToTreeProxyModel::rowCount(const QModelIndex &parent) const
    return sourceModel()->rowCount(parent);

    int TableToTreeProxyModel::columnCount(const QModelIndex &parent) const
    return sourceModel()->columnCount(parent);

    Qt::ItemFlags TableToTreeProxyModel::flags(const QModelIndex &index) const
    return sourceModel()->flags(index);

    To create tree & proxy:
    @// tree
    QStandardItemModel* tree = new QStandardItemModel(this);
    QStandardItem* root = tree->invisibleRootItem();
    QStandardItem* toto = new QStandardItem("toto");
    QStandardItem* titi = new QStandardItem("titi");
    QStandardItem* tata = new QStandardItem("tata");
    QStandardItem* pokemon = new QStandardItem("tutu");
    QStandardItem* tyty = new QStandardItem("tyty");

    // proxy
    proxy = new TableToTreeProxyModel;

    To draw :
    @drawTree(tree); // ok
    drawTree(proxy); // ok

    QTreeView* treeView1 = new QTreeView;
    treeView1->setModel(tree); // ok

    QTreeView* treeView2 = new QTreeView;
    treeView2->setModel(proxy); // not ok@

  • Moderators

    [quote author="Guillaume Belz" date="1312386299"]Thanks

    (I have write a class to create a new tree model from table model ans that work. But here, I want to map table and tree items)[/quote]

    Can you show your code for that. It should be possible to map the table and tree items through a proxy. I suppose you used a proxy for that?

  • I use... nothing in particular. I take a QStandardItem table for source and QStandardItem tree for destination. Conversion was performed with this :

    @QModelIndex idRow(QAbstractItemModel* src, int row) { return src->index(row, 0); }
    QModelIndex parentIdRow(QAbstractItemModel* src, int row) { return src->index(row, 1); }
    QModelIndex titleRow(QAbstractItemModel* src, int row) { return src->index(row, 2); }

    QList<int> rowByParentID(QAbstractItemModel* src, const QModelIndex &parent)
    QString id = parent.isValid() ? src->data(parent).toString() : QString("-1");
    QList<int> rows;
    for (int row = 0; row < src->rowCount(); ++row)
    //qDebug() << " row" << id << src->data(src->index(row, 1));
    if (src->data(parentIdRow(src, row)) == id)
    return rows;

    void toTree(QAbstractItemModel* src, QStandardItem* dst, QModelIndex const& parent = QModelIndex())
    QList<int> rows = rowByParentID(src, parent);
    for (int row = 0; row < rows.size(); ++row)
    QStandardItem* child = new QStandardItem(src->data(titleRow(src, rows[row])).toString());
    toTree(src, child, idRow(src, rows[row]));

    table = new QStandardItemModel(5, 3, this);
    tree2 = new QStandardItemModel(this);
    toTree(table, tree2->invisibleRootItem());@
    (I don't use free functions in fact, but it's not important here)

    Problems with this approach is : data was duplicated and I must to create symetric functions to convert tree to table (if tree was modified, for update data in table)

  • What I want to do has been added to Qt 4.8 (QIdentityProxyModel :
    However, this class uses the createIndex() function, which is protected (
    @return d->model->createIndex(proxyIndex.row(), proxyIndex.column(), proxyIndex.internalPointer());@
    I implementing this class using the index() function, it's work for tables but not for trees.
    @return sourceModel()->index(proxyIndex.row(), proxyIndex.column());@
    I think this will work for table to tree proxy but not for symetric proxy (tree to table proxy).
    If someone was ideas.

  • Hi,

    I don't know QIdentityProxyModel.
    But as you only have a standard proxy model in 4.7, you have to have an index, that is created on this model and do your own mapping.
    You index function may never return an index from the source model directly.

    The function you mention can be called inside methods of the proxy model, e.g. for mapToSource, where it also works in 4.7.

Log in to reply

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.