Search code examples
listviewqml

appending item into a listmodel which is in another file


My question is how can you append item coming from another listmodel.qml to another ListModel that is in another qml file.
There is a button in ItemDelegate from the NameDeleget.qml. when I click that button I want to append the name to the ListModel in favorite.qml.
When I push that favorite.qml into a StackView I want it to show the appended item.
Anyone with idea how to do that.

Home.qml

import QtQuick 2.0
import QtQuick.Controls 2.12

ApplicationWIndow {
    id: root
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")
    
    ListView {
        anchors.fill: parent
        model: NameModel{}
        delegate: NameDeleget{}
    }
}

NameModel.qml

import QtQuick 2.0

ListModel {
    listElement {name:""; value:}
    listElement {name:""; value:}
    listElement {name:""; value:}
}

NameDeleget.qml

import QtQuick 2.0
import QtQuick.Controls 2.12

ItemDelegate {
    width: parent.width
    text: model.name
    RoundButton {
        id: btn
        anchos.right: parent.right
        onclicked: {
        // When the button is clciked I want to append the clciked name to the "favorite.qml"
    }
}

Favorite.qml

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import Qt.labs.settings 1.1
import Qt.labs.settings 1.0

Item {
    ListView {
        id: listView
        anchors.fill: parent

        model: ListModel {
            id: dataModel
            ListElement {name: "test1"; value: 1}
        }

        delegate: ItemDelegate {
            id: itemDelegete
            width: parent.width
            text: name +":"+ value
        }
    }
}

Solution

  • I interpret your requirements as:

    • On HomePage.qml view ListModel containing names and pick your favourites
    • On FavouritePage.qml view the same ListModel but only show the selected favourites
    • Navigate between the two pages using StackView

    So, to do this:

    • I ignored the requirement of two ListModel since only one ListModel is needed
    • Declare the ListModel in a parent scope so both pages can see it
    • Use DelegateModel on the second page to filter the records
    import QtQuick 2.15
    import QtQuick.Controls 2.15
    import QtQuick.Layouts 1.15
    
    Page {
        property var fav: ([])
        StackView {
            id: stackView
            anchors.fill: parent
            initialItem: "HomePage.qml"
        }
        ListModel {
            id: nameModel
            ListElement { name: "Steve Jobs" }
            ListElement { name: "Bill Gates" }
            ListElement { name: "Jeff Bezos" }
        }
    }
    
    //HomePage.qml
    import QtQuick 2.15
    import QtQuick.Controls 2.15
    import QtQuick.Layouts 1.15
    Page {
        header: Frame {
            background: Rectangle { color: "lightgrey" }
            Text {
                text: "HomePage.qml (%1 total)".arg(nameModel.count)
            }
        }
        ColumnLayout {
            anchors.fill: parent
            ListView {
                Layout.fillWidth: true
                Layout.fillHeight: true
                model: nameModel
                delegate: Frame {
                    background: Rectangle {
                        color: (index & 1) ? "#f0f0f0" : "#e0e0e0"
                    }
                    width: ListView.view.width
                    RowLayout {
                        width: parent.width
                        CheckBox {
                            checked: fav.indexOf(model.index) !== -1
                            onToggled: {
                                let obj = fav;
                                let idx = obj.indexOf(model.index);
                                if (idx === -1) {
                                    obj.push(model.index);
                                } else {
                                    obj = obj.filter(e => e !== model.index);
                                }
                                fav = obj;
                            }
                        }
                        Text {
                            Layout.fillWidth: true
                            text: model.name
                        }
                    }
                }
            }
            Text {
                text: JSON.stringify(fav)
            }
        }
        footer: Button {
            text: "Goto Favourites"
            onClicked: stackView.push("FavouritePage.qml")
        }
    }
    
    //FavouritePage.qml
    import QtQuick 2.15
    import QtQuick.Controls 2.15
    import QtQuick.Layouts 1.15
    import QtQml.Models 2.15
    Page {
        header: Frame {
            background: Rectangle { color: "lightgrey" }
            Text {
                text: "FavouritePage.qml (%1 total)".arg(favourites.count)
            }
        }
        ListView {
            anchors.fill: parent
            model: FilterDelegateModel {
                id: favourites
                model: nameModel
                filter: model => fav.indexOf(model.index) !== -1
                delegate: Frame {
                    background: Rectangle {
                        color: (index & 1) ? "#f0f0f0" : "#e0e0e0"
                    }
                    width: ListView.view.width
                    RowLayout {
                        width: parent.width
                        Text {
                            Layout.fillWidth: true
                            text: model.name
                        }
                    }
                }
            }
        }
        footer: Button {
            text: "Back to HomePage"
            onClicked: stackView.pop()
        }
    }
    
    //FilterDelegateModel.qml
    import QtQuick 2.15
    import QtQml.Models 2.15
    
    DelegateModel {
        property var filter: null
        groups: [
            DelegateModelGroup {
                id: allItems
                name: "all"
                includeByDefault: true
                onCountChanged: Qt.callLater(update)
            },
            DelegateModelGroup {
                id: visibleItems
                name: "visible"
            }
        ]
        filterOnGroup: "visible"
        function update() {
            allItems.setGroups(0, allItems.count, [ "all" ] );
            for (let index = 0; index < allItems.count; index++) {
                let item = allItems.get(index).model;
                let visible = !filter || filter(item);
                if (!visible) continue;
                allItems.setGroups(index, 1, [ "all", "visible" ]);
            }
        }
        Component.onCompleted: Qt.callLater(update)
    }
    

    You can Try it Online!