3

I have a tree model derived from a QAbstractItemModel. And I can display the data in a tree like way.

enter image description here

What I want is to display teh data by the layers. To display only one level of a layer at a time AND put each layer on a stack and navigate backwards by poping the layer from the stack. enter image description here

I guess I have to implement a custom delegate? Any advice would be highly appreciated. Thank you.

Bob
  • 1,433
  • 1
  • 16
  • 36

2 Answers2

3

I recently implemented something similar, based on a QFileSystemModel, set as a qml contextProperty, named treeModel in the example below.

The idea was to keep track of the current QModelIndex, and to use the data() & rowCount() functions of the QAbstractItemModel to get the actual model data, and to use a recursive stack view for the navigation

General layout

ApplicationWindow {
    id: main
    visible: true
    width: 640
    height: 480

    ColumnLayout
    {
        anchors.fill: parent

        // Breadcrumb
        SEE BELOW

        // View
        StackView
        {
            id: stackView
            Layout.fillHeight: true
            Layout.fillWidth: true
            initialItem: TreeSlide {}
        }

    }
}

TreeSlide

The view itself is pretty simple. I didn't used anything fancy here, and it displays only one role, but you could extend it without trouble. Note that the view's model is NOT your treeModel, but instead just the rowCount for the rootIndex.

ListView
{
    Layout.fillHeight: true
    Layout.fillWidth: true
    model: treeModel.rowCount(rootIndex)
    clip: true
    snapMode: ListView.SnapToItem

    property var rootIndex

    // I used a QFileSytemModel in my example, so I had to manually 
    // fetch data when the rootIndex changed. You may not need this though.
    onRootIndexChanged: {
        if(treeModel.canFetchMore(rootIndex))
            treeModel.fetchMore(rootIndex)
    }
    Connections {
        target: treeModel
        onRowsInserted: {
            rootIndexChanged()
        }
    }

    delegate: ItemDelegate {
        property var modelIndex: treeModel.index(index,0, rootIndex)
        property bool hasChildren: treeModel.hasChildren(modelIndex)
        width: parent.width
        text: treeModel.data(modelIndex)
        onClicked: {
            if(hasChildren)
            {
                // Recursively add another TreeSlide, with a new rootIndex
                stackView.push("TreeSlide.qml", {rootIndex: modelIndex})
            }
        }
    }
}

Breadcrumb

To navigate the model, instead of a simple back button, I used a kind of dynamic breadcrumb

// Breadcrumb
RowLayout
{
    Repeater
    {
        id: repeat
        model: {
            var res = []
            var temp = stackView.currentItem.rootIndex
            while(treeModel.data(temp) != undefined)
            {
                res.unshift(treeModel.data(temp))
                temp = temp.parent
            }
            res.unshift('.')
            return res
        }
        ItemDelegate
        {
            text : modelData
            onClicked: {
                goUp(repeat.count - index-1)
            }
        }

    }
}

the goUp function simply goes up the stack by poping items

function goUp(n)
{
    for(var i=0; i<n; i++)
        stackView.pop()
}
1

To to do it completely by guides we should use DelegateModel and DelegateModel.rootIndex

   DelegateModel {
        id: delegateSupportPropConfigModel

        model: supportModel

        delegate: SupportPropConfigListItem {
            id: currentItem
            width: scrollRect2.width - 60
            fieldName: model.fieldName
            fieldValue: model.value 

            onClick:{
              delegateSupportPropConfigModel.rootIndex = supportPropConfigModel.index(0, 0, supportPropConfigModel)
            }
        }
    }

    Column {
        id: columnSettings
        spacing: 2

        Repeater {
            model: delegateSupportPropConfigModel
        }
    }
Bob
  • 1,433
  • 1
  • 16
  • 36