1

Is it possible to implement 3 ListModels (one inside the other) and if yes how could I do it? The 3 ListModels are for hour day and month accordingly.In other words I want one model for hour inside the model for day inside the model for month and I am going to use them in nested ListView s (3 of them ) to display the hour the day and the month in a calendar. I have made a try below :

   ListModel{
      id:monthlistModel
      ListElement {
                  monthName:0
                  daylistModel:[
                      ListElement  {
                          day:0
                          hourlistModel: [
                            ListElement{ hour:0;notes:"" }
                          ]
                      }
                  ]
       }
        ListElement {
                  monthName:1
                  daylistModel:[
                      ListElement  {
                          day:1
                          hourlistModel: [
                            ListElement{ hour:1;notes:"" }
                          ]
                      }
                  ]
       }

but I could not finish it . Moreover I have some typeerror issues when I am running my code.The hourlistModel insists to be undefined for my nested listview and I dont no why. Anyway back to my question , how can I go on with the above listmodel to display 24 hours , 31 days and 12 months ?

1 Answer 1

2

I suggest doing this imperatively with javascript rather than declaratively in QML, as it can be more dynamic and brief. One downside is that this is not well documented in my experience.

If you append an array to a ListModel, all of the array elements are converted into ListElements. Further than this, if an array is appended, and that array has nested arrays inside of it, the nested arrays are automatically converted to nested ListModels inside.

Here is a full example:

import QtQuick 2.15
import QtQuick.Window 2.0
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.12

Window {
    visible: true
    width: 1000
    height: 600

    ListModel {
        id: monthsModel

        Component.onCompleted: {
            let months = [
                    {
                        name: "January",
                        days: createDays(31) // returns an array, nested arrays become nested ListModels when appended
                    },
                    {
                        name: "February",
                        days: createDays(28)
                    },
                    // add more months etc.
                ]
            append(months) // appending a whole array makes each index into a ListElement at the top level
        }

        function createDays(dayCount) {
            let days = []

            for (let i = 0; i < dayCount; i++) {
                days.push({
                              day: i + 1,
                              hours: createHours()
                          }
                          )
            }
            return days
        }

        function createHours() {
            let hours = []
            for (let i = 0; i < 24; i++) {
                hours.push({
                               hour: i,
                               notes: ""
                           }
                           )
            }
            return hours
        }
    }

    // Visual example code starts here ///////////////

    ColumnLayout {
        id: monthsColumn

        Repeater {
            model: monthsModel

            delegate: Rectangle {
                id: month
                color: "pink"
                implicitWidth: daysRow.implicitWidth + 10
                implicitHeight: daysRow.implicitHeight + 10

                RowLayout {
                    id: daysRow
                    anchors {
                        centerIn: parent
                    }

                    Text {
                        text: model.name
                    }

                    Repeater {
                        model: days // refers to the "days" entry in monthsModel.get(<monthIndex>)

                        delegate: Rectangle {
                            id: day
                            color: "orange"
                            implicitWidth: hoursColumn.implicitWidth + 10
                            implicitHeight: hoursColumn.implicitHeight + 10

                            ColumnLayout {
                                id: hoursColumn
                                anchors {
                                    centerIn: parent
                                }

                                Text {
                                    text: model.day
                                }

                                Repeater {
                                    model: hours // refers to the "hours" entry in monthsModel.get(<monthIndex>).get(<dayIndex>)

                                    delegate: Rectangle {
                                        id: hour
                                        color: "yellow"
                                        implicitHeight: 5
                                        implicitWidth: 5

                                        // do something here with model.notes for each hour
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

The output of this shows months in pink, days in orange, and hours in yellow:

months in pink, days in orange, and hours in yellow

Sign up to request clarification or add additional context in comments.

10 Comments

@fallerdThis is an amazing answer.Thank you very much.Just a question about days model.How can I use this model days to another ListView outside repeaters ?What is the syntax to refer to this model in another outside this code listview as a model?
@cgiannakidis After creating/filling the base monthsModel, you can reach into this model to get and use any of the nested days models (there is 1 days model per month) by doing something like monthsModel.get(<your month index here>).days. So to get the days model for the first month: monthsModel.get(0).days.
@fallerdOK.And if I want to access notes in hours model for updating the text of notes how I must express it , what is the syntax for that.Thanks in advance.
@cgiannakidis Since these are also nested, they are accessible in the same manner, just deeper. For example, the first day of the first month's hours model is accessible with monthsModel.get(0).days.get(0).hours. And similarly, the notes for the first hour of that day is: monthsModel.get(0).days.get(0).hours.get(0).notes. In my example, though, notes is a string and not a model, but it could be made into a model by making it an array instead of empty string in createHours()
@cgiannakidis Depends. Your code frag is re-using the same currentIndex rather than the currentIndex of the appropriate ListViews. I would think you would need something more like monthsModel.get(monthListView.currentIndex).days.get(dayListView.currentIndex).hours.get(hourListView.currentIndex).notes. As with everything, this sort of depends on the scope you want to call this from, there may be a simpler answer. If you are inside my yellow "hour" delegate, as commented there, you can just refer to notes there with model.notes
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.