如何从 QML 访问嵌套的 QStandardItemModel 的项目?

How to access nested QStandardItemModel's items from QML?

背景

我有一个树状 QStandardItemModel,我想从 QML 访问它的项目。

以下是模型在 C++ 端的定义方式:

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;
}

模型在 main.cpp 中导出为 QML,如下所示:

Backend backend;
QQmlApplicationEngine engine;

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

main.qml 中使用 QtQuick.Controls 1.4 中的 TreeView 像这样:

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

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

我得到了想要的结果,即所有项目都正确嵌套:

问题

当我尝试使用 RepeaterDelegateModel 手动遍历嵌套项时,如下所示:

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
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

主要分支(蓝色标记)和第一个嵌套级别(绿色标记)上的项目是正确的,但我在第二个嵌套级别(红色标记)上得到错误的项目:

如何修复代码以在每个嵌套级别正确迭代 QStandardItemModel 的项目?

问题出在这两行:rootIndex: modelIndex(index)

index是'parent'模型的索引,但是modelIndex(...)是当前模型的方法


我已经用这段(稍微修改过的)代码试过了,它成功了:

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
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}