How to add elements to a DelegateModelGroup depend

2020-02-10 10:07发布

I have a ListModel and a DelegateModel, a ListView and 3 Buttons. The DelegateModel has one Group: myGroup With a click on of the first two buttons, I add elements to the ListModel with different properties, that then will be used to add them or not add them to myGroup. The third button is used to toggle the filter.

ListModel {
    id: rootModel
}


DelegateModel {
    id: visualModel
    model: rootModel
    groups: [DelegateModelGroup { name: 'myGroup' }]

    delegate: Rectangle {
        width: model.width
        height: model.height
        color: model.color
        border.width: 1

        Component.onCompleted: DelegateModel.inMyGroup = Qt.binding(function() {return width == 80})
    }
}

ListView {
    width: 300
    height: 480
    model: visualModel
}

Rectangle {
    id: b1
    x: 350
    width: 100
    height: 50
    color: 'lightsteelblue'
    Text {
        anchors.centerIn: parent
        text: 'add 80'
    }

    MouseArea {
        anchors.fill: parent
        onClicked: rootModel.append( { width: 80, height: 30, color: 'steelblue' })
    }
}

Rectangle {
    id: b2
    x: 350
    y: 70
    width: 100
    height: 50
    color: 'violet'
    Text {
        anchors.centerIn: parent
        text: 'add 50'
    }

    MouseArea {
        anchors.fill: parent
        onClicked: rootModel.append( { width: 50, height: 30, color: 'violet' })
    }
}
Rectangle {
    id: b3
    x: 350
    y: 140
    width: 100
    height: 50
    color: 'green'
    Text {
        anchors.centerIn: parent
        text: 'filter'
    }

    MouseArea {
        anchors.fill: parent
        property bool toggle: false
        onClicked: {
            visualModel.filterOnGroup = toggle ? '' : 'myGroup'
            toggle = !toggle
        }
    }
}

So far so good, as long as not filter is set, I can add elements of both types to the model, and then I can filter. However I can't add elements to the model (Group) as long as I have set the filter. This is obvious, as per default the element is not added, so the component is not completed, and nothing is added to the group, until I unset the filter again, and all pending elements are instanciated, completed, and finally added.

Therefore I look for another way to automatically add the elements depending on a property to the group, or to exclude them.

I know, I could set includeByDefault: true and then throw them out after they have been instanciated once. While this solves this particular issue, it does not solve the next, where I would change the property, therefore throw it out of the group, and then change it back. It won't reappear until the component is reinstanciated again.

Oh, and I know, I could solve this with C++, but I don't want to, unless necessary.

标签: qml qtquick2
2条回答
看我几分像从前
2楼-- · 2020-02-10 10:11

The problem is that DelegateModel.inMyGroup = Qt.binding(function() {return width == 80}) is evaluated only once the object is displayed. But when filter is on, if an element is added it does not belongs to myGroup group, so it is not displayed and never has a chance to evaluate the condition.

Here is a quick fix, I added a function that executes every time an element is added. The default group seems to be 'items' and not ''.

Window {
    visible: true
    width: 640
    height: 480
    property bool toggle: true


    ListModel{
        id: rootModel
        onCountChanged: visualModel.setGroups()
    }

    DelegateModel {
        id: visualModel
        model: rootModel
        filterOnGroup: toggle ? 'items' : 'myGroup'
        groups: [DelegateModelGroup { id: myGroup; name: 'myGroup' }]

        function setGroups() {
            var newItem = rootModel.get(rootModel.count - 1)
            var groups;
            if (newItem.width == 80){
                groups = ['items', 'myGroup'];
            }else{
                groups = ['items'];
            }
            items.setGroups(rootModel.count - 1, 1, groups)
        }

        delegate: Rectangle {
            width: model.width
            height: model.height
            color: model.color
            border.width: 1
        }
    }

    ListView {
        width: 300
        height: 480
        model: visualModel
    }

    Rectangle {
        id: b1
        x: 350
        width: 100
        height: 50
        color: 'lightsteelblue'
        Text {
            anchors.centerIn: parent
            text: 'add 80'
        }

        MouseArea {
            anchors.fill: parent
            onClicked: rootModel.append( { width: 80, height: 30, color: 'steelblue' })
        }
    }

    Rectangle {
        id: b2
        x: 350
        y: 70
        width: 100
        height: 50
        color: 'violet'
        Text {
            anchors.centerIn: parent
            text: 'add 50'
        }

        MouseArea {
            anchors.fill: parent
            onClicked: rootModel.append( { width: 50, height: 30, color: 'violet' })
        }
    }
    Rectangle {
        id: b3
        x: 350
        y: 140
        width: 100
        height: 50
        color: 'green'
        Text {
            anchors.centerIn: parent
            text: 'filter'
        }

        MouseArea {
            anchors.fill: parent
            onClicked: {
                toggle = !toggle
            }
        }
    }
}
查看更多
▲ chillily
3楼-- · 2020-02-10 10:22

For those who are interested in it, with the hint of user2436719 I was able to hack together this model. It is a ListModel, and examplewise two DelegateModels, with groups to which the elements are added depending on a role of the listmodel.

ListModel{
    id: rootModel
    onCountChanged: setGroups(count - 1)
    onDataChanged: setGroups(arguments[0].row)
    property DelegateModel sub1:
        DelegateModel {
            id: subModel1
            model: rootModel
            groups: [
                DelegateModelGroup { name: 'myGroup' },
                DelegateModelGroup { name: 'notMyGroup' }
            ]
            delegate: Rectangle {
                width: model.width
                height: model.height
                color: model.color
                border.width: 1
            }
            filterOnGroup: (root.toggle ? 'myGroup' : 'notMyGroup')
        }
    property DelegateModel sub2:
        DelegateModel {
            id: subModel2
            model: rootModel
            groups: [
                DelegateModelGroup { name: 'myGroup' },
                DelegateModelGroup { name: 'notMyGroup' }
            ]
            delegate: Rectangle {
                radius: 5
                width: model.width
                height: model.height
                color: model.color
                border.width: 1

                Text {
                    anchors.centerIn: parent
                    text: DelegateModel.groups.toString()
                }
            }
            filterOnGroup: (root.toggle ? 'myGroup' : 'notMyGroup')
        }

    function setGroups(index) {
        console.log('set Groups for', index)
        var i = get(index)
        subModel1.items.setGroups(index, 1, ['items', (i.width === 80 ? 'myGroup' : 'notMyGroup')])
        subModel2.items.setGroups(index, 1, ['items', (i.width !== 80 ? 'myGroup' : 'notMyGroup')])
    }
}
查看更多
登录 后发表回答