QML ListView currentItem doesn't change after a sort



  • Hello. I have a ListView tied to a QAbstractListModel in C++ by way of a QSortFilterProxyModel so the list contents can be sorted (dynamic sorting is enabled).

    My problem is simple:
    Say the ListView contains the following items:

    0: A
    1: B
    2: C

    B is selected, and thus highlighted, so the currentIndex is 1 and the currentItem is B. Suddenly, the list is sorted to be:

    0: A
    1: C
    2: B

    And the ListView shows this. However, the currentIndex is still 1, which means the currentItem is now C and the highlight moves from B to C.

    My question is simple: what is the best way to ensure that if B is selected before the sort, B is still selected after the sort?



  • Really what this comes down to is this: if the ListView knew when an item was moved (e.g. sorted), I could run a function to loop through its children and make sure the right item (the models have IDs associated with them) is selected. Unfortunately, according to http://lists.qt.nokia.com/public/qt-qml/2010-September/001149.html , it seems ListViews have no way of knowing when something is moved. Does that sound accurate? This seems like a HUGE limitation if true.



  • I figured this out... but my solution was pretty nasty. The only way to ensure the right delegate was selected was to re-check which one was selected every time the layout changed (since the layout obviously has to change if the items are re-sorted).

    Below is a snippet of what I did. There has to be a better way!

    Note that "modelId" is a role on the model.

    @Component
    {
    id: myDelegate

      Column
      {
         id: column
    
         Component.onCompleted:
         {
            myListView.setSelected.connect(handleSetSelected)
         }
    
         // If we don't disconnect from the signal the handler will still be called
         // on destroyed components and errors will be thrown about undefined
         // variables.
         Component.onDestruction:
         {
             myListView.setSelected.disconnect(handleSetSelected)
         }
    
         function setSelected()
         {
            myListView.setCurrentItem(index, modelId);
         }
    
         function handleSetSelected(modelIdToBeSelected)
         {
            if (modelId === modelIdToBeSelected)
            {
               setSelected();
            }
         }
    
         // More delegate stuff...
      }
    

    }

    ListView
    {
    property int currentModelId: 0

      signal setSelected(int modelId)
    

    function setCurrentItem(index, modelId)
    {
    currentIndex = index;
    currentModelId = modelId;
    }

      id: myListView
      objectName: "MyList"
      model: myModel
      delegate: myDelegate
    
      // Signal handlers
      Connections
      {
         target: myModel
    
         onLayoutChanged:
         {
            myListView.setSelected(myListView.currentModelId)
         }
      }
    

    }@


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.