qmlkde-plasma

How to filter a delegatemodel with more than one different filter groups qml


I have a ListView with model, number 6 and horizontal scrolling .Inside ListView there is a GridView with model a ListModel.The ListElement's of the ListModel in GridView are about 200.Right now I have managed to display the first 35 items in GridView scrolling horizontally the ListView.What i want to do is to display in each "page" of ListView, groups of 35 ListElements untill all of them displayed.Which means, in first "page" of ListView display the first 35 items of GridView, after that , in second "page" the other 35 items etc. while scrolling horizontally.I tryied with the below code to make groups of DelegateModel and filter it conditionally in two pages at first, following the answer in this question Working with delegate model and delegate model group dynamically QML? :

DelegateModel {

        id: visualModel

        delegate: myButton

        model:appsModel

       property var visualIndex: pageList.currentIndex

            groups: [
            DelegateModelGroup {
                id:firstpage
                includeByDefault: true
                name: "firstpage"
            },
            DelegateModelGroup {
                id:secondpage
                includeByDefault: true
                name: "secondpage"
            }
        ]

      onVisualIndexChanged:{

        if(visualIndex===0){
               filterOnGroup: "firstpage";page="first"
        }else if(visualIndex===1){
               filterOnGroup: "secondpage";page="second"
        }else{}
        console.log(visualIndex, page);
    }
      Component.onCompleted:{
                    for( var i = 0;i < items.count;i++ ) {
                    var element = items.get(i).model;
                    if(element.appId > 35) {
                        items.removeGroups(i, 1, "firstpage");
                    }else if(element.appId <= 35 && element.appId > 70) {
                        items.removeGroups(i, 1, "secondpage");
                    }else{}
                }
            }
         }

but it does not work.pageList is the ListView. Any suggestion will be appreciated. Thank you.


Solution

  • Your DelegateModel is problematic, because, for 6 pages, you would need to create 6 DelegateModelGroups, and, to generalize for n pages, you would need to generalize further.

    I highly recommend you engineer a reusable DelegateModelGroup that has a from and to that will help choose different elements from the underlying model to be visible, e.g.

        ListView {
            model: colorModel.count / 35
            delegate: GridView {
                model: DelegateModel {
                    property from: index * 35
                    property to: from + 35
                    model: colorModel
                    filterOnGroup: "visible"
                    // ... heavy lifting needed here
                }
            }
        }
    

    That way, for 200 items, it would assign 6 items to the parent ListView, and, for the inner GridView the visual model will choose 35 records from the underlying model to be visible.

    Here's a complete working example:

    import QtQuick
    import QtQuick.Controls
    import QtQuick.Layouts
    Page {
        id: page
        ListView {
            width: 640
            height: 480
            anchors.centerIn: parent
            model: Math.floor((colorModel.count + 34) / 35)
            orientation: ListView.Horizontal
            clip: true
            snapMode: ListView.SnapOneItem
            delegate: GridView {
                width: ListView.view.width
                height: ListView.view.height
                cellWidth: 70
                cellHeight: 70
                header: Label {
                    width: GridView.view.width
                    text: `page ${index + 1}`
                    horizontalAlignment: Qt.AlignHCenter
                }
                model: MyDelegateModel {
                    from: index * 35
                    to: Math.min(from + 35, colorModel.count)
                    model: colorModel
                    delegate: MyDelegate { }
                }
            }
        }
        ColorModel {
            id: colorModel
        }
    }
    
    // MyDelegateModel.qml
    import QtQuick
    import QtQuick.Controls
    DelegateModel {
        property int from: 0
        property int to: 10
        groups: [
            DelegateModelGroup {
                id: newItems
                name: "new"
                includeByDefault: true
                onCountChanged: {
                    newItems.setGroups(from, to - from, ["new","visible"]);
                }
            },
            DelegateModelGroup { name: "visible" }
        ]
        filterOnGroup: "visible"
    }
    
    // MyDelegate.qml
    import QtQuick
    import QtQuick.Controls
    Label {
        width: 70
        height: 70
        text: txt
        verticalAlignment: Qt.AlignVCenter
        horizontalAlignment: Qt.AlignHCenter
        color: Qt.color(col).hslLightness > 0.5 ? "black" : "white"
        wrapMode: Text.Wrap
        background: Rectangle { color: col }
    }
    
    // ColorModel.qml
    import QtQuick
    import QtQuick.Controls
    ListModel {
        Component.onCompleted: {
            for (let i = 0; i < 200; i++) {
                let txt = i;
                let col = Qt.rgba(Math.random(),Math.random(),Math.random()).toString();
                append({txt,col});
            }
        }
    }
    

    You can Try it Online!