1
votes

I had asked a similar question here. But this solution worked only for one-paged QML file. I build a QML app that contains many pages, so I made a favorite tab that contains Add/Remove action. There is a list model in favorite tab page. In my opinion, in order to add any page to the favorite list, it is necessary to call the favorite list model from the sample page, so when a user clicked the action, the page should be added to the favorite page as a list item. I have two examples. First example is one-paged QML and it adds/removes list item. But second example doesn't adds/removes the sample page to favorite list page. How can I access, save and restore the content of the list model using QML or Java Script? Thanks.

First example:

enter image description here

main.qml

import QtQuick 2.6
import QtQuick.Controls 2.3
import QtQuick.Controls.Material 2.0
import Qt.labs.settings 1.0
ApplicationWindow{
    id:main
    width: 640
    height: 480
    visible:true
    title: "Menu"
    property string datastore: ""
    property int countt2: 0
    Settings{
        property alias datastore: main.datastore
        property alias mycount: main.countt2
    }
    menuBar:MenuBar {
        Menu{
        title: main.title
            Action {
                id:action2
                text: qsTr("On/Off")
                onTriggered:{
                    countt2++
                    console.log("triggered works.Count/2: "+ countt2%2)
                    if(countt2%2==1){
                        console.log("it must be added")
                        dataModel.append({ "title": "Application Tools" })
                    }
                    else if(countt2%2==0){
                        console.log("list must be removed. count/2: "+countt2%2)
                        return dataModel.remove(dataModel.index)
                    }
                }
            }
        }
    }
    Component.onCompleted: {
        if(datastore){
            dataModel.clear()
            var datamodel=JSON.parse(datastore)
            for (var i=0; i<datamodel.length; ++i) dataModel.append(datamodel[i])
        }
        console.log("onCompleted works right now.")
    }
    onClosing: {
        var datamodel = []
        for (var i=0;i<dataModel.count; ++i) datamodel.push(dataModel.get(i))
        datastore=JSON.stringify(datamodel)
        console.log("datastore: "+datastore)
    }
        ListView {
            id:malist
            width: parent.width
            height: parent.height
            focus: true
            interactive: true
            clip: true
            model:FavModel{
            id:dataModel
            }
            delegate: ItemDelegate {
                width: parent.width
                text: model.title
            }
        }
}

FavModel.qml:

import QtQuick 2.0
ListModel {
    id:dataModel
    }

Second Example:

enter image description here

enter image description here

main.qml:

import QtQuick 2.6
import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.0
import QtQuick.Layouts 1.3
import Fluid.Controls 1.0
import QtQuick.Window 2.3
ApplicationWindow{
    id:main
    width: 640
    height: 480
    visible:true
    title: "Example App"
    initialPage:TabbedPage {
        title: main.title
        Tab{
            title:"APPS"
        ListView {
            id:malist
            width: parent.width
            height: parent.height
            focus: true
            interactive: true
            clip: true
            model:ListModel {
            id:appModel
            ListElement { title: qsTr("Page1"); source: "qrc:/SampePage.qml" }
            }
            delegate: ListItem {
                text: model.title
                onClicked: pageStack.push(model.source)
            }
        }
        }
        Favourites{}
    }
}

Favourites.qml:

import QtQuick 2.6
import QtQuick.Controls 2.0
import QtQuick.Controls.Material 2.0
import Fluid.Controls 1.0
Tab{
    title:"FAVORITES"
ListView {
    id:favorites
    width: parent.width
    height: parent.height
    focus: true
    interactive: true
    clip: true
    model:FavModel {
    id:favModel
    }
    delegate: ListItem {
        text: model.title
        onClicked: pageStack.push(model.source)
    }
}
}

FavModel.qml:

import QtQuick 2.0

ListModel {
    id:dataModel
    }

SamplePage.qml:

import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.2
import Fluid.Controls 1.0
import Qt.labs.settings 1.0
Page{
    title:qsTr("Page1")
    appBar.maxActionCount: 2
    id:sampleapp
    property string datastore: ""
    property int countt2: 0
    Settings{
        id:mysetting4
        property alias datastore: sampleapp.datastore
        property alias mycount: sampleapp.countt2
    }
    FavModel{
        id:dataModel
    }
    Component.onCompleted: {
        console.log("onCompleted works right now.")
        if(datastore){
            dataModel.clear()
            var datamodel = JSON.parse(datastore)
            for (var i=0; i<datamodel.length; ++i) dataModel.append(datamodel[i])
        }
    }
    onCanGoBackChanged: {
        var datamodel=[]
        for (var i=0; i<dataModel.count; ++i) datamodel.push(dataModel.get(i))
        datamodel = JSON.stringify(datamodel)
        console.log("datastore: "+datastore)
    }
    actions: [
        Action {
          id:favourite2
            onTriggered:{
                countt2++
                console.log("Count/2: "+ countt2%2)
                if(countt2%2==1){
                    console.log("List must be added")
                    dataModel.append({ "title": "Application Tools", "source": "qrc:/SampePage.qml" })
                }
                else if(countt2%2==0){
                    console.log("List must be removed.")
                    return dataModel.remove(dataModel.index)
                }
            }
            icon.name: "toggle/star"
            toolTip: qsTr("Add/Remove")
        }
    ]
}

*I couldn't make Qt Quick Controls 2.0 only example in second example, I had to use fluid qml library because it is simple to make list menu.

1

1 Answers

2
votes

In your code you have 2 problems:

  • The first is that you are not saving the list in datastorage

[...]
datamodel = JSON.stringify(datamodel)
[...]

Must be:

datastore = JSON.stringify(datamodel)
  • The second is that you are saving the data at the wrong time, the onCanGoBackChanged event occurs after the page is loaded. In general the approach must be that the data is loaded when the item is finished loading, and the data is saved before the item is destroyed, so it is appropriate to use the Component.onCompleted and Component.onDestruction events.

Component.onCompleted: {
    console.log("onCompleted works right now.")
    if(datastore){
        dataModel.clear()
        var datamodel = JSON.parse(datastore)
        for (var i=0; i<datamodel.length; ++i) dataModel.append(datamodel[i])
    }
}
Component.onDestruction: {
    console.log("onDestruction works right now.")
    var datamodel=[]
    for (var i=0; i<dataModel.count; ++i) datamodel.push(dataModel.get(i))
    datastore = JSON.stringify(datamodel)
    console.log("datastore: "+datastore)
}

Another minor error, because I think it's a test code. let's say there is no data in dataModel and that countt2 is even, so you're going to want to delete a non-existent data from the dataModel.

Update:

Settings is used to store the data and be able to restore after closing the application, but if you want to share data between several files a possible solution is to implement a singleton, as this is a single element that exists in the whole application. It will be easy to modify it anywhere.

To build a singleton we create an .qml file with the following structure:

Shared.qml

pragma Singleton
import QtQuick 2.0

QtObject {
    property var favModel: FavModel{}
}

Then we add another file called qmldir:

qmldir

singleton Shared 1.0 Shared.qml

Then I import it and we use it in the following way:

import "."

[...]

Shared.favModel.some_function()

for example in your specific case:

main.qml

import QtQuick 2.6
import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.0
import QtQuick.Layouts 1.3
import Fluid.Controls 1.0
import QtQuick.Window 2.3
import Qt.labs.settings 1.0
import "."

ApplicationWindow{
    id:main
    width: 640
    height: 480
    visible:true
    title: "Example App"

    property string datastore: ""
    Settings{
        property alias datastore: main.datastore
    }

    Component.onCompleted: {
        console.log("onCompleted works right now.")
        if(datastore){
            Shared.favModel.clear()
            var datamodel = JSON.parse(datastore)
            for (var i=0; i<datamodel.length; ++i) Shared.favModel.append(datamodel[i])
        }
    }

    Component.onDestruction: {
        console.log("onDestruction works right now.")
        var datamodel=[]
        for (var i=0; i<Shared.favModel.count; ++i) datamodel.push(Shared.favModel.get(i))
        datastore = JSON.stringify(datamodel)
        console.log("datastore: "+datastore)
    }
    [...]
}

SamplePage.qml

import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.2
import Fluid.Controls 1.0
import "."

Page{
    title:qsTr("Page1")
    appBar.maxActionCount: 2
    id:sampleapp

    actions: [
        Action {
            id:favourite2
            onTriggered:{
                Shared.favModel.append({ "title": "Application Tools", "source": "qrc:/SamplePage.qml" })
            }
            icon.name: "toggle/star"
            toolTip: qsTr("Add/Remove")
        }
    ]
}

Favourites.qml

import QtQuick 2.6
import QtQuick.Controls 2.0
import QtQuick.Controls.Material 2.0
import Fluid.Controls 1.0

import "."

Tab{
    title:"FAVORITES"
    id:favtab

    ListView {
        id:favorites
        width: parent.width
        height: parent.height
        focus: true
        interactive: true
        clip: true
        model: Shared.favModel
        delegate: ListItem {
            text: model.title
            onClicked: pageStack.push(model.source)
        }
    }
}

The complete and updated example can be found in the following link