Search code examples
c++qtqmlqt5qstandarditemmodel

QML Treeview: How to get QModelIndex of childs


I have a QML TreeView with a QStandardItemModel and use a ItemSelectionModel to manage the selection. The ItemSelectionModel wants a QModelIndex for its select function. How can I obtain the QModelIndex of children in my view?

The tree looks like this:

  • file 1
    • task 1
    • task 2
  • file 2
    • task 1

I want to select task2 when I click on it (I can have a MouseArea in the delegate) (so that the TreeView highlights it), and in order to do this, I must call ItemSelectionModel.select with the QModelIndex of task 2. But I don' t know how I can get the QModelIndex of task2.

QStandardItemModel is derived from QAbstractItemModel and therefore provides an index function:

 virtual QModelIndex    index(int row, int column, const QModelIndex & parent = QModelIndex()) const

but to use this function I need to know the index of the parent. How can I get it from the view?


Solution

  • To obtain the child you must first have the parent, so in the case of your scheme you must obtain "file1" and for this you must obtain his parent, and this parent is the rootIndex of the TreeView, so the sequence is: rootIndex -> file1 -> task1.

    main.cpp

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlContext>
    #include <QStandardItemModel>
    
    int main(int argc, char *argv[])
    {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    
        QGuiApplication app(argc, argv);
    
        QStandardItemModel model;
    
        QStandardItem *item1 = new QStandardItem("file1");
        item1->appendRows({new QStandardItem("task1"), new QStandardItem("task2")});
    
        QStandardItem *item2 = new QStandardItem("file2");
        item2->appendRows({new QStandardItem("task1")});
    
        model.appendRow(item1);
        model.appendRow(item2);
    
        QQmlApplicationEngine engine;
        engine.rootContext()->setContextProperty("tree_model", &model);
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
        if (engine.rootObjects().isEmpty())
            return -1;
    
        return app.exec();
    }
    

    main.qml

    import QtQuick 2.9
    import QtQuick.Window 2.2
    import QtQuick.Controls 1.4
    import QtQml.Models 2.11
    
    Window {
        visible: true
        width: 640
        height: 480
        TreeView {
            id: treeView
            anchors.fill: parent
            model: tree_model
            selectionMode: SelectionMode.MultiSelection
            selection: ItemSelectionModel {
                id: ism
                model: tree_model
            }
            TableViewColumn {
                title: "Name"
                role: "display"
                width: 300
            }
            Component.onCompleted: {
                expandAll()
    
                var ix1 = tree_model.index(0, 0, treeView.rootIndex)
                var ix = tree_model.index(0, 0, ix1)
                ism.select(ix, ItemSelectionModel.Select)
            }
        }
    
        // https://forum.qt.io/topic/75395/qml-treeview-expand-method-not-working
        function expandAll() {
            for(var i=0; i < tree_model.rowCount(); i++) {
                var index = tree_model.index(i,0)
                if(!treeView.isExpanded(index)) {
                    treeView.expand(index)
                }
            }
        }
    }
    

    enter image description here

    Update:

    To get the index of the item pressed you must use styleData.index:

    import QtQuick 2.9
    import QtQuick.Window 2.2
    import QtQuick.Controls 1.4
    import QtQml.Models 2.11
    
    Window {
        visible: true
        width: 640
        height: 480
        TreeView {
            id: treeView
            anchors.fill: parent
            model: tree_model
            selectionMode: SelectionMode.MultiSelection
            selection: ItemSelectionModel {
                id: ism
                model: tree_model
            }
            TableViewColumn {
                title: "Name"
                role: "display"
                width: 300
            }
            itemDelegate: Item {
                Text {
                    anchors.verticalCenter: parent.verticalCenter
                    color: styleData.textColor
                    elide: styleData.elideMode
                    text: styleData.value
    
                }
                MouseArea{
                    anchors.fill: parent
                    onClicked: {
                        var ix = tree_model.index(0, 0, styleData.index)
                        ism.select(ix, ItemSelectionModel.Select)
                    }
                }
            }
        }
    }