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 sort items in listview in qml
Forum Updated to NodeBB v4.3 + New Features

How to sort items in listview in qml

Scheduled Pinned Locked Moved QML and Qt Quick
13 Posts 7 Posters 36.3k Views 1 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.
  • D Offline
    D Offline
    deimos
    wrote on last edited by
    #3

    What Andre said is right and probably the best way. I tried another solution that works, but this implies a little more resources and a custom sort function.
    When the component is completed you can fill another ListModel with sorted elements of your first one and use it.
    I used a XmlListModel here, but the concept is the same.
    buttonsGridView is the GridView and you can fill listModel by:

    @Component:onCompleted: { fillListModel(); sortModel(); }@

    here there is what I did:

    @function sortModel()
    {
    var n;
    var i;
    for (n=0; n < buttonsGridView.count; n++)
    for (i=n+1; i < buttonsGridView.count; i++)
    {
    if (buttonsGridView.model.get(n).nameCat > buttonsGridView.model.get(i).nameCat)
    {
    buttonsGridView.model.move(i, n, 1);
    n=0; // Repeat at start since I can't swap items i and n
    }
    }
    }

    // Use a ListModel to sort out the list
    function fillListModel()
    {
        var n;
        for (n=0; n&lt; xmlModel.count; n++)
            listModel.append({"idCat": xmlModel.get(n).idCat, "nameCat": xmlModel.get(n).nameCat})
    }
    
    XmlListModel {
        id: xmlModel
        source: ...
        query: ...
    
        XmlRole { name: "idCat";  query: "id/string()" }
        XmlRole { name: "nameCat"; query: "name/string()" }
    
        onStatusChanged: if (status === XmlListModel.Ready) { fillListModel(); sortModel(); }
    }
    
    
    ListModel {
        id: listModel
    }@
    
    1 Reply Last reply
    0
    • A Offline
      A Offline
      andre
      wrote on last edited by
      #4

      Nice trick, but it will not work in the current form if the underlying model is dynamic (and that is what you need sorting for in the first place, otherwise you'd just use a static, pre-sorted model in the first place) and the sorting routine looks painfully slow. Not an issue if you need to sort a small list, but this will quickly start to be a performance hit I think.

      1 Reply Last reply
      0
      • D Offline
        D Offline
        deimos
        wrote on last edited by
        #5

        Yes, you are right. I used it for just 20~30 items and the bubble sort method isn't efficient because the swap element is not supported, but sort function could/should be reimplemented.
        If the model is dynamic something like this could be of some help ?

        @ Timer {
        id: waitTimer
        interval: 50
        repeat: false
        triggeredOnStart: false
        running: false
        onTriggered: { fillListModel(); sortModel(); }
        }

        ListModel {
            id: listModelToSort
            onItemsInserted: waitTimer.restart()
        }@
        
        1 Reply Last reply
        0
        • J Offline
          J Offline
          Julie1986
          wrote on last edited by
          #6

          Hallo, I was looking for soemthing really similar. I tried it but I am gettin error. could not rectify it. Kindly help me out!

          @import QtQuick 1.1
          //import "check.js" as Chk

          Rectangle{

          width:400
          height:width

          Component.onCompleted: { sortModel(); fillListModel();}
          function sortModel()
          {
          var n;
          var i;
          for (n=0; n < grdview.count; n++)
          for (i=n+1; i < grdview.count; i++)
          {
          if (grdview.model.get(n).id> grdview.model.get(i).id)
          {
          // console.log("checking for the id ")
          // console.log(grdview.model.get(n).title)
          grdview.model.move(i, n, 1);
          n=0;
          }
          }}

          function fillListModel()
          {
              var n;
              for (n=0; n &lt; xmlModel.count; n++)
              {
                  console.log(xmlModel.count)
                  console.log("Sfasd")
                  listModel.append({"title": xmlModel.get(n).title, "pubDate":xmlModel.get(n).pubDate, "id":xmlModel.get(n).id})
          }}
          

          XmlListModel {
          id: xmlModel
          source: "example.xml"
          query: "/rss/channel/item"
          XmlRole { name: "id"; query: "id/string()" }
          XmlRole { name: "title"; query: "title/string()" }
          XmlRole { name: "pubDate"; query: "pubDate/string()" }
          onStatusChanged: if (status === XmlListModel.Ready) {sortModel();fillListModel(); }
          }

          GridView{
          id:grdview
          width: 180; height: 300
          model:xmlModel
          delegate: Text { text:title+ ": " + pubDate+id
          }
          visible:false

          }

          ListModel {
          id: listModel

          }
          ListView{

          model:listModel
          width: 180; height: 300
          delegate: Text { text:title+ ": " + pubDate+id}

          }

          }
          @

          and the error i get is :TypeError: Result of expression 'grdview.model.move' [undefined] is not a function. kindly let me know what is the mistake. I can also send u the xml file if required.

          1 Reply Last reply
          0
          • J Offline
            J Offline
            Julie1986
            wrote on last edited by
            #7

            @<?xml version="1.0" encoding="utf-8"?>
            <rss version="2.0">
            ...
            <channel>
            <item>
            <title>A blog post</title>
            <pubDate>Sat, 07 Sep 2010 10:00:01 GMT</pubDate>
            <id> 3 </id>
            </item>
            <item>
            <title>A blog post</title>
            <pubDate>Sat, 07 Sep 2010 10:00:01 GMT</pubDate>
            <id> 4 </id>
            </item>
            <item>
            <title>A blog post</title>
            <pubDate>Sat, 07 Sep 2010 10:00:01 GMT</pubDate>
            <id> 2 </id> </item>
            <item>
            <title>A blog post</title>
            <pubDate>Sat, 07 Sep 2010 10:00:01 GMT</pubDate>
            <id> 1 </id>
            </item>
            <item>
            <title>Another blog post</title>
            <pubDate>Sat, 07 Sep 2010 15:35:01 GMT</pubDate>
            <id> 0 </id>
            </item>
            </channel>
            </rss>@

            This is the xml file am using

            1 Reply Last reply
            0
            • D Offline
              D Offline
              deimos
              wrote on last edited by
              #8

              Hi,

              I found something wrong in you code: the dummy model listModel should be filled before sorting it and gridView model is a XmlModelList that is read only, so in the sort function you can't move elements.
              I come into this implementation and added also a listModel.clear(); in the fillListModel() function because if the xml model get updated, the new reads will be appended to the already filled model.

              regards

              @import QtQuick 1.1
              //import "check.js" as Chk

              Rectangle{

              width:400
              height:width
              
              function sortModel()
              {
                  var n;
                  var i;
                  for (n=0; n < listModel.count; n++)
                      for (i=n+1; i < listModel.count; i++)
                      {
                          if (listModel.get(n).id> listModel.get(i).id)
                          {
                              listModel.move(i, n, 1);
                              n=0;
                          }
                      }
              }
              
              function fillListModel()
              {
                  var n;
                  listModel.clear();
                  for (n=0; n &lt; xmlModel.count; n++)
                  {
                      listModel.append({"title": xmlModel.get(n).title, "pubDate":xmlModel.get(n).pubDate, "id":xmlModel.get(n).id})
                  }
              }
              
              
              XmlListModel {
                  id: xmlModel
                  source: "example.xml"
                  query: "/rss/channel/item"
                  XmlRole { name: "id"; query: "id/string()" }
                  XmlRole { name: "title"; query: "title/string()" }
                  XmlRole { name: "pubDate"; query: "pubDate/string()" }
                  onStatusChanged: if (status === XmlListModel.Ready) { console.log("xml read: ", count); fillListModel(); sortModel(); }
              }
              
              GridView{
                  id:grdview
                  width: 180; height: 300
                  model: xmlModel
                  delegate: Text { text:title+ ": " + pubDate+id }
                  visible:false
              }
              
              ListModel {
                  id: listModel
              
              }
              
              ListView{
              
                  model:listModel
                  width: 180; height: 300
                  delegate: Text { text:title+ ": " + pubDate+id}
              }
              

              }@

              1 Reply Last reply
              0
              • J Offline
                J Offline
                Julie1986
                wrote on last edited by
                #9

                Hey, thanks you. works great.. I appreciate it. [Solved]

                1 Reply Last reply
                0
                • D Offline
                  D Offline
                  deimos
                  wrote on last edited by
                  #10

                  Your welcome, but remember what Andre wrote:

                  bq. the sorting routine looks painfully slow. Not an issue if you need to sort a small list, but this will quickly start to be a performance hit I think.

                  regards

                  1 Reply Last reply
                  0
                  • R Offline
                    R Offline
                    remy67
                    wrote on last edited by
                    #11

                    In my projetc i add the quick sort algorythm to ListModel.

                    It works pretty well.
                    Save this code into a qml file , for example SortListModel.qml
                    and use @SortListModel.sortColumnName="productName";
                    SortListModel.quick_sort();@

                    @import QtQuick 2.0

                    ListModel {

                    property string sortColumnName: ""
                    
                    id: sortlistmodel
                    
                    function swap(a,b) {
                        if (a<b) {
                            move(a,b,1);
                            move (b-1,a,1);
                        }
                        else if (a>b) {
                            move(b,a,1);
                            move (a-1,b,1);
                        }
                    }
                    
                    function partition(begin, end, pivot)
                    {
                        var piv=get(pivot)[sortColumnName];
                        swap(pivot, end-1);
                        var store=begin;
                        var ix;
                        for(ix=begin; ix<end-1; ++ix) {
                            if(get(ix)[sortColumnName] < piv) {
                                swap(store,ix);
                                ++store;
                            }
                        }
                        swap(end-1, store);
                    
                        return store;
                    }
                    
                    function qsort(begin, end)
                    {
                        if(end-1>begin) {
                            var pivot=begin+Math.floor(Math.random()*(end-begin));
                    
                            pivot=partition( begin, end, pivot);
                    
                            qsort(begin, pivot);
                            qsort(pivot+1, end);
                        }
                    }
                    
                    function quick_sort() {
                        qsort(0,count)
                    }
                    

                    }@

                    T 1 Reply Last reply
                    2
                    • R remy67

                      In my projetc i add the quick sort algorythm to ListModel.

                      It works pretty well.
                      Save this code into a qml file , for example SortListModel.qml
                      and use @SortListModel.sortColumnName="productName";
                      SortListModel.quick_sort();@

                      @import QtQuick 2.0

                      ListModel {

                      property string sortColumnName: ""
                      
                      id: sortlistmodel
                      
                      function swap(a,b) {
                          if (a<b) {
                              move(a,b,1);
                              move (b-1,a,1);
                          }
                          else if (a>b) {
                              move(b,a,1);
                              move (a-1,b,1);
                          }
                      }
                      
                      function partition(begin, end, pivot)
                      {
                          var piv=get(pivot)[sortColumnName];
                          swap(pivot, end-1);
                          var store=begin;
                          var ix;
                          for(ix=begin; ix<end-1; ++ix) {
                              if(get(ix)[sortColumnName] < piv) {
                                  swap(store,ix);
                                  ++store;
                              }
                          }
                          swap(end-1, store);
                      
                          return store;
                      }
                      
                      function qsort(begin, end)
                      {
                          if(end-1>begin) {
                              var pivot=begin+Math.floor(Math.random()*(end-begin));
                      
                              pivot=partition( begin, end, pivot);
                      
                              qsort(begin, pivot);
                              qsort(pivot+1, end);
                          }
                      }
                      
                      function quick_sort() {
                          qsort(0,count)
                      }
                      

                      }@

                      T Offline
                      T Offline
                      tunahammer
                      wrote on last edited by
                      #12

                      @remy67 I know it's been a long time, but thank you!! I was able to use this and it was very helpful

                      I added a sort order argument as well (super easy with your setup)


                      import QtQuick 2.0

                      ListModel {

                      property string sortColumnName: ""
                      property string order: "desc" //set to either asc or desc
                      id: sortlistmodel
                      
                      function swap(a,b) {
                          if (a<b) {
                              move(a,b,1);
                              move (b-1,a,1);
                          }
                          else if (a>b) {
                              move(b,a,1);
                              move (a-1,b,1);
                          }
                      }
                      
                      function partition(begin, end, pivot)
                      {
                          var piv=get(pivot)[sortColumnName];
                          swap(pivot, end-1);
                          var store=begin;
                          var ix;
                          for(ix=begin; ix<end-1; ++ix) {
                              if (order ==="asc"){
                                  if(get(ix)[sortColumnName] < piv) {
                                      swap(store,ix);
                                      ++store;
                                  }
                              }else if (order ==="desc"){
                                  if(get(ix)[sortColumnName] > piv) {
                                      swap(store,ix);
                                      ++store;
                                  }
                              }
                          }
                          swap(end-1, store);
                      
                          return store;
                      }
                      
                      function qsort(begin, end)
                      {
                          if(end-1>begin) {
                              var pivot=begin+Math.floor(Math.random()*(end-begin));
                      
                              pivot=partition( begin, end, pivot);
                      
                              qsort(begin, pivot);
                              qsort(pivot+1, end);
                          }
                      }
                      
                      function quick_sort() {
                          qsort(0,count)
                      }
                      

                      }

                      hammering tuna

                      1 Reply Last reply
                      1
                      • S Offline
                        S Offline
                        Stephen Quan
                        wrote on last edited by Stephen Quan
                        #13

                        We can make use of Array.prototype.sort():

                        • Create an array of indexes the same size of the listModel
                        • Use Array.prototype.sort() to rearrange the index with an appropriately written compareFunc
                        • Then rearrange the listModel as per the new order of items as shown in the index

                        Here's the QML ListModel sort function:

                            function listModelSort(listModel, compareFunc) {
                                var indexes = new Array(listModel.count);
                                for (var i = 0; i < listModel.count; i++) indexes[i] = i;
                                indexes.sort(function (indexA, indexB) { return compareFunc(get(indexA), get(indexB)) } );
                                var sorted = 0;
                                while (sorted < indexes.length && sorted === indexes[sorted]) sorted++;
                                if (sorted === indexes.length) return;
                                for (i = sorted; i < indexes.length; i++) {
                                    var idx = indexes[i];
                                    listModel.move(idx, listModel.count - 1, 1);
                                    listModel.insert(idx, { } );
                                }
                                listModel.remove(sorted, indexes.length - sorted);
                            }
                        

                        See Also:

                        • my full GIST code snippet: https://gist.github.com/stephenquan/fcad6ecd4b28051c61cf48853e39c9e4
                        • related StackOverflow post: https://stackoverflow.com/questions/29429710/how-to-auto-sort-qml-listelements-in-sections
                        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