Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. How to group items?
Forum Updated to NodeBB v4.3 + New Features

How to group items?

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
17 Posts 2 Posters 2.1k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • rrlopezR rrlopez

    @fbg13 Hello, have you checked out QSortFilterProxyModel? With it you can sort and filter any model:
    https://doc.qt.io/qt-5/qsortfilterproxymodel.html
    You will have to add the songs to a model and access them from it:
    https://doc.qt.io/qt-5/qtquick-modelviewsdata-modelview.html

    fbg13F Offline
    fbg13F Offline
    fbg13
    wrote on last edited by
    #3

    @rrlopez What I need help with is how to display the groups in qml.

    I managed to do it by changing my model to hold the groups only and each group will have the songs.
    And in qml I have a repeater for the groups and for each group a repeater for the songs.

    Here's a repo https://gitlab.com/g-fb/music-player-layout-example with what I managed so far.

    Don't know how good this approach is and I can't think of another way.

    rrlopezR 1 Reply Last reply
    0
    • fbg13F fbg13

      @rrlopez What I need help with is how to display the groups in qml.

      I managed to do it by changing my model to hold the groups only and each group will have the songs.
      And in qml I have a repeater for the groups and for each group a repeater for the songs.

      Here's a repo https://gitlab.com/g-fb/music-player-layout-example with what I managed so far.

      Don't know how good this approach is and I can't think of another way.

      rrlopezR Offline
      rrlopezR Offline
      rrlopez
      wrote on last edited by
      #4

      @fbg13 I would use a QAbstractProxyModel to act as a model of your table view and change the way you define stuff in your QML.
      Basically add a row on the model for each song you want to display (artist, songname, artist, etc) and then access these roles on QML as model.artist, model.songname, etc.
      As you'll be using a QAbstractProxyModel you will have access to its sorting and filtering methods, so you will be able to filter out songs on artist. You basically will have N items where N is the number of artists, and each item from N will have a different filter to show only songs related to the corresponding artist.

      Lic-Ing. Rodrigo Lopez Gonzalez
      Embedded Software Engineer
      RidgeRun Engineering Ltd.
      www.ridgerun.com
      Email: rodrigo.lopez@ridgerun.com

      fbg13F 1 Reply Last reply
      0
      • rrlopezR rrlopez

        @fbg13 I would use a QAbstractProxyModel to act as a model of your table view and change the way you define stuff in your QML.
        Basically add a row on the model for each song you want to display (artist, songname, artist, etc) and then access these roles on QML as model.artist, model.songname, etc.
        As you'll be using a QAbstractProxyModel you will have access to its sorting and filtering methods, so you will be able to filter out songs on artist. You basically will have N items where N is the number of artists, and each item from N will have a different filter to show only songs related to the corresponding artist.

        fbg13F Offline
        fbg13F Offline
        fbg13
        wrote on last edited by
        #5

        @rrlopez said in How to group items?:

        @fbg13 I would use a QAbstractProxyModel to act as a model of your table view and change the way you define stuff in your QML.
        Basically add a row on the model for each song you want to display (artist, songname, artist, etc) and then access these roles on QML as model.artist, model.songname, etc.

        You mean the data for the model should be:
        data {song1, song2, .... } instead of data {album1 {song1, song2 ...}, album2 {song1, song2 ...}, album3 {song1, song2 ...}}

        As you'll be using a QAbstractProxyModel you will have access to its sorting and filtering methods, so you will be able to filter out songs on artist. You basically will have N items where N is the number of artists, and each item from N will have a different filter to show only songs related to the corresponding artist.

        But I don't want to filter the results. I want to show all songs, but they should be grouped and all groups should be visible at the same time.
        Like in the screenshot, the red rectangles are the groups (image on left and songs on the right).

        I guess my problem is how to add the image, since it should be added only when the value on which the songs are grouped changes, and have the layout I want, image on left and songs on the right.

        rrlopezR 1 Reply Last reply
        0
        • fbg13F fbg13

          @rrlopez said in How to group items?:

          @fbg13 I would use a QAbstractProxyModel to act as a model of your table view and change the way you define stuff in your QML.
          Basically add a row on the model for each song you want to display (artist, songname, artist, etc) and then access these roles on QML as model.artist, model.songname, etc.

          You mean the data for the model should be:
          data {song1, song2, .... } instead of data {album1 {song1, song2 ...}, album2 {song1, song2 ...}, album3 {song1, song2 ...}}

          As you'll be using a QAbstractProxyModel you will have access to its sorting and filtering methods, so you will be able to filter out songs on artist. You basically will have N items where N is the number of artists, and each item from N will have a different filter to show only songs related to the corresponding artist.

          But I don't want to filter the results. I want to show all songs, but they should be grouped and all groups should be visible at the same time.
          Like in the screenshot, the red rectangles are the groups (image on left and songs on the right).

          I guess my problem is how to add the image, since it should be added only when the value on which the songs are grouped changes, and have the layout I want, image on left and songs on the right.

          rrlopezR Offline
          rrlopezR Offline
          rrlopez
          wrote on last edited by
          #6

          @fbg13 said in How to group items?:

          You mean the data for the model should be:
          data {song1, song2, .... } instead of data {album1 {song1, song2 ...}, album2 {song1, song2 ...}, album3 {song1, song2 ...}}

          No, data should be {{song1, album1, etc},{song2,album2,etc}}. So that each row of the model contains everything that fully describes a song.

          I want to show all songs, but they should be grouped and all groups should be visible at the same time.

          QAbstractProxyModel also has ordering capabilities, so you should be able to sort them on any role of your model, in this case you want to use the album role.

          But I don't want to filter the results.

          I was talking about filtering because a way to show the information as the screenshot you sent is to have some sort of item for each album, so you would filter on album and show only the songs from that specific album in each item, but having a single item and sorting it out also works.

          Lic-Ing. Rodrigo Lopez Gonzalez
          Embedded Software Engineer
          RidgeRun Engineering Ltd.
          www.ridgerun.com
          Email: rodrigo.lopez@ridgerun.com

          fbg13F 1 Reply Last reply
          0
          • rrlopezR rrlopez

            @fbg13 said in How to group items?:

            You mean the data for the model should be:
            data {song1, song2, .... } instead of data {album1 {song1, song2 ...}, album2 {song1, song2 ...}, album3 {song1, song2 ...}}

            No, data should be {{song1, album1, etc},{song2,album2,etc}}. So that each row of the model contains everything that fully describes a song.

            I want to show all songs, but they should be grouped and all groups should be visible at the same time.

            QAbstractProxyModel also has ordering capabilities, so you should be able to sort them on any role of your model, in this case you want to use the album role.

            But I don't want to filter the results.

            I was talking about filtering because a way to show the information as the screenshot you sent is to have some sort of item for each album, so you would filter on album and show only the songs from that specific album in each item, but having a single item and sorting it out also works.

            fbg13F Offline
            fbg13F Offline
            fbg13
            wrote on last edited by
            #7

            @rrlopez said in How to group items?:

            I was talking about filtering because a way to show the information as the screenshot you sent is to have some sort of item for each album, so you would filter on album and show only the songs from that specific album in each item, but having a single item and sorting it out also works.

            How would that look in qml though?
            Do I give my item's (TableView, Repeater etc) model the filtered-by-album model, and in the delegate I get the songs for the respective album?

            rrlopezR 1 Reply Last reply
            0
            • fbg13F fbg13

              @rrlopez said in How to group items?:

              I was talking about filtering because a way to show the information as the screenshot you sent is to have some sort of item for each album, so you would filter on album and show only the songs from that specific album in each item, but having a single item and sorting it out also works.

              How would that look in qml though?
              Do I give my item's (TableView, Repeater etc) model the filtered-by-album model, and in the delegate I get the songs for the respective album?

              rrlopezR Offline
              rrlopezR Offline
              rrlopez
              wrote on last edited by
              #8

              @fbg13 said in How to group items?:

              Do I give my item's (TableView, Repeater etc) model the filtered-by-album model, and in the delegate I get the songs for the respective album?

              Yes, your delegate will just get all songs the model has since results will be filtered on the model, so QML will not view the filtered out items.

              Lic-Ing. Rodrigo Lopez Gonzalez
              Embedded Software Engineer
              RidgeRun Engineering Ltd.
              www.ridgerun.com
              Email: rodrigo.lopez@ridgerun.com

              fbg13F 1 Reply Last reply
              0
              • rrlopezR rrlopez

                @fbg13 said in How to group items?:

                Do I give my item's (TableView, Repeater etc) model the filtered-by-album model, and in the delegate I get the songs for the respective album?

                Yes, your delegate will just get all songs the model has since results will be filtered on the model, so QML will not view the filtered out items.

                fbg13F Offline
                fbg13F Offline
                fbg13
                wrote on last edited by
                #9

                @rrlopez said in How to group items?:

                Yes, your delegate will just get all songs the model has since results will be filtered on the model, so QML will not view the filtered out items.

                But if I give the filtered model to a TableView I will get only songs from 1 album in the TableView.
                How do I get the other songs?

                Or should this TableView be a delegate for another item?

                    Repeater {
                        // model with each album
                        model: albumsModel
                        delegate: TableView {
                            // model with songs of the current album in the repeater
                            model: songsModel
                            delegate: Song {}
                        }
                    }
                
                1 Reply Last reply
                0
                • rrlopezR Offline
                  rrlopezR Offline
                  rrlopez
                  wrote on last edited by
                  #10

                  @fbg13 said in How to group items?:

                  Or should this TableView be a delegate for another item?

                  Yeah, that's what I meant.

                  Lic-Ing. Rodrigo Lopez Gonzalez
                  Embedded Software Engineer
                  RidgeRun Engineering Ltd.
                  www.ridgerun.com
                  Email: rodrigo.lopez@ridgerun.com

                  fbg13F 1 Reply Last reply
                  0
                  • rrlopezR rrlopez

                    @fbg13 said in How to group items?:

                    Or should this TableView be a delegate for another item?

                    Yeah, that's what I meant.

                    fbg13F Offline
                    fbg13F Offline
                    fbg13
                    wrote on last edited by fbg13
                    #11

                    @rrlopez I tried what you suggested, or what I understood at least, but it's not working.

                    At the core what I have done is:

                    Repeater {
                        id: group
                        model: ["album1", "album2"]
                        delegate: Repeater {
                            model: songsProxyModel
                            Component.onCompleted: songsProxyModel.setFilterFixedString(modelData)
                            delegate: Label {
                                text: model.artist + " - " + model.title
                            }
                        }
                    }
                    

                    But all groups have the same songs, from the last filtering.
                    Updated the repo too.

                    1 Reply Last reply
                    0
                    • rrlopezR Offline
                      rrlopezR Offline
                      rrlopez
                      wrote on last edited by
                      #12

                      Hi, your model should be something like:
                      {{song1, album1, etc},{song2,album2,etc}}
                      So each entry is a song which has an album related.

                      Lic-Ing. Rodrigo Lopez Gonzalez
                      Embedded Software Engineer
                      RidgeRun Engineering Ltd.
                      www.ridgerun.com
                      Email: rodrigo.lopez@ridgerun.com

                      fbg13F 1 Reply Last reply
                      0
                      • rrlopezR rrlopez

                        Hi, your model should be something like:
                        {{song1, album1, etc},{song2,album2,etc}}
                        So each entry is a song which has an album related.

                        fbg13F Offline
                        fbg13F Offline
                        fbg13
                        wrote on last edited by
                        #13

                        @rrlopez said in How to group items?:

                        Hi, your model should be something like:
                        {{song1, album1, etc},{song2,album2,etc}}
                        So each entry is a song which has an album related.

                        If I understand you correctly I should have a single model songsModel = {{song1, album1, etc},{song2,album2,etc}} ,
                        whose model is songsModel filtered to only hold the albums.

                        The delegate of that repeater should be another repeater (or another item with a model),
                        whose model is songsModel filtered to hold the songs of the album in the first repeater.
                        Is that correct?

                        1 Reply Last reply
                        0
                        • rrlopezR Offline
                          rrlopezR Offline
                          rrlopez
                          wrote on last edited by
                          #14

                          If I understand you correctly I should have a single model songsModel = {{song1, album1, etc},{song2,album2,etc}}
                          whose model is songsModel filtered to only hold the albums.

                          With this implementation you will have to sort each item, instead of filtering them out.
                          ListView has something named sections that will allow you to create a section for each album.

                          Lic-Ing. Rodrigo Lopez Gonzalez
                          Embedded Software Engineer
                          RidgeRun Engineering Ltd.
                          www.ridgerun.com
                          Email: rodrigo.lopez@ridgerun.com

                          fbg13F 1 Reply Last reply
                          0
                          • rrlopezR rrlopez

                            If I understand you correctly I should have a single model songsModel = {{song1, album1, etc},{song2,album2,etc}}
                            whose model is songsModel filtered to only hold the albums.

                            With this implementation you will have to sort each item, instead of filtering them out.
                            ListView has something named sections that will allow you to create a section for each album.

                            fbg13F Offline
                            fbg13F Offline
                            fbg13
                            wrote on last edited by
                            #15

                            @rrlopez said in How to group items?:

                            With this implementation you will have to sort each item, instead of filtering them out.

                            Then I really don't understand what you're suggesting with the filtering.
                            Can you provide a simple example of what you mean?

                            ListView has something named sections that will allow you to create a section for each album.

                            That's kinda what I want, but it doesn't look like I can get the songs on the right of the section, the height of the section would be ~300px.

                            1 Reply Last reply
                            0
                            • rrlopezR Offline
                              rrlopezR Offline
                              rrlopez
                              wrote on last edited by
                              #16

                              @fbg13, this is what I meant:

                              ColumnLayout {
                                      anchors.fill: parent
                                      RowLayout {
                                          id: group
                                          Layout.alignment: Qt.AlignTop
                                          Layout.fillHeight: true
                                          Layout.fillWidth: true
                                          ColumnLayout {
                                              id: songs
                                              Layout.alignment: Qt.AlignTop
                                              Layout.fillWidth: true
                                              Label {}
                                              ListView {
                                                  height: contentHeight
                                                  section.property: "album"
                                                  section.delegate: Text {
                                                      text: section
                                                      font.bold: true
                                                  }
                                                  model: songsModel
                                                  delegate: SongRow {
                                                      artist: model.artist
                                                      title: model.title
                                                      album: model.album
                                                  }
                                              }
                                          }
                                      }
                                  }
                              

                              I used a text as a delegate, but you can use whatever delegate you want. Let me know if it works for you.

                              Lic-Ing. Rodrigo Lopez Gonzalez
                              Embedded Software Engineer
                              RidgeRun Engineering Ltd.
                              www.ridgerun.com
                              Email: rodrigo.lopez@ridgerun.com

                              fbg13F 1 Reply Last reply
                              0
                              • rrlopezR rrlopez

                                @fbg13, this is what I meant:

                                ColumnLayout {
                                        anchors.fill: parent
                                        RowLayout {
                                            id: group
                                            Layout.alignment: Qt.AlignTop
                                            Layout.fillHeight: true
                                            Layout.fillWidth: true
                                            ColumnLayout {
                                                id: songs
                                                Layout.alignment: Qt.AlignTop
                                                Layout.fillWidth: true
                                                Label {}
                                                ListView {
                                                    height: contentHeight
                                                    section.property: "album"
                                                    section.delegate: Text {
                                                        text: section
                                                        font.bold: true
                                                    }
                                                    model: songsModel
                                                    delegate: SongRow {
                                                        artist: model.artist
                                                        title: model.title
                                                        album: model.album
                                                    }
                                                }
                                            }
                                        }
                                    }
                                

                                I used a text as a delegate, but you can use whatever delegate you want. Let me know if it works for you.

                                fbg13F Offline
                                fbg13F Offline
                                fbg13
                                wrote on last edited by
                                #17

                                @rrlopez I understood the ListView sections, but I don't think it fits my needs, since the section should hold the album cover and songs should be on the right of this image (like in the screenshot). If I add the image in the section I get this
                                99185144-5191-459c-bb4d-799d6a89dfb3-image.png

                                Gray area is the section, red is the "cover image".


                                What I don't understand is your QSortFilterProxyModel and QAbstractProxyModel suggestions.

                                @rrlopez said in How to group items?:

                                @fbg13 I would use a QAbstractProxyModel to act as a model of your table view and change the way you define stuff in your QML.
                                Basically add a row on the model for each song you want to display (artist, songname, artist, etc) and then access these roles on QML as model.artist, model.songname, etc.
                                As you'll be using a QAbstractProxyModel you will have access to its sorting and filtering methods, so you will be able to filter out songs on artist. You basically will have N items where N is the number of artists, and each item from N will have a different filter to show only songs related to the corresponding artist.

                                1 Reply Last reply
                                0

                                • Login

                                • Login or register to search.
                                • First post
                                  Last post
                                0
                                • Categories
                                • Recent
                                • Tags
                                • Popular
                                • Users
                                • Groups
                                • Search
                                • Get Qt Extensions
                                • Unsolved