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.2k 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.
  • 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