QML: Multi-level Menu from ListModel

只愿长相守 提交于 2021-02-08 09:50:55

问题


I have an example multi-level ListModel:

ListModel{
    id: myModel
    ListElement{
        name: "File"
        subItems:[
            ListElement{
                name: "Open"
            },
            ListElement{
                name: "Open Recent"
                subItems:[
                    ListElement{
                        name: "Bla.txt"
                    }
                ]
            },
            ListElement{
                name: "Save"
            },
            ListElement{
                name: "Save as"
            },
            ListElement{
                name: "Exit"
            }
        ]
    }
    ListElement{
        name: "Edit"
        subItems:[
            ListElement{
                name: "Undo"
            },
            ListElement{
                name: "Redo"
            },
            ListElement{
                name: "Select All"
            }
        ]
    }
    ListElement{
        name: "Help"
        subItems:[
            ListElement{
                name: "About"
            }
        ]
    }
}

Which I want to display as Menu. From here I know how to iterate model inside of Menu component. But because I have multi-level structure I should check either second level is Menu or MenuItem. Therefore I use Loader and choose which component to load(check if subItems of the element is undefined):

    MenuBar{
    id: menuBar
    Instantiator{
        id: menuBarRepeater
        model: myModel
        onObjectRemoved: menuBar.removeItem( object )
        delegate: Loader{
            sourceComponent: myModel.get(index)["subItems"]? subMenuLoader : menuItemLoader
            onLoaded: {
                item.name = model.name;
                if(myModel.get(index)["subItems"]){
                    item.parentIndex = index;
                    item.model = model
                    menuBar.insertMenu( index, item )
                }else{
                    menuBar.insertItem( index, item )
                }
            }
        }
    }
}

Finally I need to add one more Instantiator for third level of menu. I could do it recursively, but for example purpose I'll assume that I have max. 3 levels. So the components that will be loaded in code above are:

    Component{
    id: menuItemLoader
    MenuItem{
        property var name
        text: name
    }
}

Component{
    id: subMenuLoader
    Menu{
        id: subMenu
        property var name
        property var parentIndex: index
        property var model
        title: name
        Instantiator{
            model: model
            onObjectRemoved: menuBar.removeItem( object )
            delegate: Loader{
                sourceComponent: myModel.get(parentIndex)["subItems"].get(index)["subItems"] ? subMenuLoader : menuItemLoader
                onLoaded: {
                    item.name = model.name;
                    if(myModel.get(parentIndex)["subItems"].get(index)["subItems"]){
                        subMenu.insertMenu( index, item )
                    }else{
                        subMenu.insertItem( index, item )
                    }
                }
            }
        }
    }
}

My problem is that the model that will be passed to the second level is QQmlDMListAccessorData and is not iterable. Is there any way to get children of the Intantiator model item?


回答1:


So, the workaround I have found is: instead of passing the model (which has type QQmlDMListAccessorData) to subMenu, as a second-level Instantiator model I used myModel.get(parentIndex)["subItems"].get(index), which addresses to ListElement, which for QML has type QQmlListModel(%index%) and can be used exactly as its parent (myModel itself)



来源:https://stackoverflow.com/questions/63794990/qml-multi-level-menu-from-listmodel

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!