1

Background

I have a tree-like QStandardItemModel, whose items I would like to access from QML.

Here is how the model is defined on the C++ side:

backend.h

class Backend : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QStandardItemModel *model READ model CONSTANT)
public:
    explicit Backend(QObject *parent = nullptr);

    QStandardItemModel *model() const;

private:
    QStandardItemModel *m_model;
};

backend.cpp

Backend::Backend(QObject *parent) :
    QObject(parent),
    m_model(new QStandardItemModel(this))
{
    auto *itemFirst = new QStandardItem(tr("First"));
    auto *itemSecond = new QStandardItem(tr("Second"));
    auto *subItem = new QStandardItem(tr("First_02"));

    subItem->appendRow(new QStandardItem("First_02_01"));

    itemFirst->appendRow(new QStandardItem(tr("First_01")));
    itemFirst->appendRow(subItem);
    itemFirst->appendRow(new QStandardItem(tr("First_03")));

    itemSecond->appendRow(new QStandardItem(tr("Second_00")));
    itemSecond->appendRow(new QStandardItem(tr("Second_01")));

    m_model->appendRow(itemFirst);
    m_model->appendRow(itemSecond);
}

QStandardItemModel *Backend::model() const
{
    return m_model;
}

The model is exported to QML in main.cpp like this:

Backend backend;
QQmlApplicationEngine engine;

engine.rootContext()->setContextProperty("backend", &backend);
qmlRegisterUncreatableType<QStandardItemModel>("QStandardItemModel", 1, 0, "QStandardItemModel", "The model should be created in C++");

Using TreeView from QtQuick.Controls 1.4 in main.qml like this:

TreeView {
    anchors.fill: parent
    model: backend.model

    TableViewColumn {
        title: "Name"
        role: "display"
    }
}

I get the desired results, i.e. all items nested correctly:

Output of TreeView

Problem

When I try to manually iterate over the nested items using Repeater and DelegateModel like this:

ColumnLayout {
    anchors.fill: parent

    Repeater {
        model: backend.model

        Item {
            Layout.fillWidth: true
            Layout.fillHeight: true

            ColumnLayout {
                anchors.fill: parent

                Text {
                    color: "blue"
                    text: model.display
                }

                Repeater {
                    model: DelegateModel {
                        model: backend.model
                        rootIndex: modelIndex(index)

                        Item {
                            Layout.fillWidth: true
                            Layout.fillHeight: true

                            ColumnLayout {
                                anchors.fill: parent

                                Text {
                                    color: "green"
                                    text: model.display
                                }

                                Repeater {
                                    model: DelegateModel {
                                        model: backend.model
                                        rootIndex: modelIndex(index)

                                        Text {
                                            color: "red"
                                            text: model.display
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

the main branches (marked with blue) and the items on the first nesting level (marked with green) are the right ones, but I get the wrong items on the second nesting level (marked with red):

Output of the manual iteration

How to fix the code to correctly iterate over the QStandardItemModel's items on each nesting level?

scopchanov
  • 7,966
  • 10
  • 40
  • 68
  • what should this code do? what a sense in `Repeater` inside `Repeater` with the same model? – folibis Aug 18 '21 at 07:52
  • 1
    @folibis the model is not the same, OP is using `DelegateModel`'s `rootIndex` property to get a nested "submodel" by changing the reference parent QModelIndex. – GrecKo Aug 18 '21 at 08:24
  • @folibis, I try to state my questions generic enough to avoid shifting the focus from the concept to the specific task at hand. So, I see the nested repeaters as the only possibility in QML to get down a certain path and visually depict whathever data the tree-like model is holding (let's say a list of customers and for each customer the bought products). With one repeater QML would give me only the customers, assuming the bought products are sub-items of each customer and not in its data. – scopchanov Aug 18 '21 at 11:08

1 Answers1

3

The problem is in these two lines: rootIndex: modelIndex(index).

index is the index of the 'parent' model, but modelIndex(...) is the method of the current model.


I've tried it with this (slightly modified) piece of code and it worked:

Repeater {
    model: DelegateModel {
        id: model1

        model: backend.model

        delegate: ColumnLayout{
            Text {
                text: "Data: " + display
            }
            Repeater {
                model: DelegateModel {
                    id: model2

                    model: backend.model
                    // 'index' comes from 'model1', so use the 'modelIndex' method from 'model1'
                    rootIndex: model1.modelIndex(index)

                    delegate: ColumnLayout{
                        Text {
                            text: "- Data: " + display
                        }
                        Repeater {
                            model: DelegateModel {
                                id: model3

                                model: backend.model
                                // 'index' comes from 'model2', so use the 'modelIndex' method from 'model2'
                                rootIndex: model2.modelIndex(index)

                                delegate: Text {
                                    text: "--  Data: " + display
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
ParkerHalo
  • 4,341
  • 9
  • 29
  • 51