Home > database >  how to implement nested listmodels in qml
how to implement nested listmodels in qml

Time:10-12

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 ?

CodePudding user response:

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

  • Related