QML ListView currentItem doesn't change after a sort
-
wrote on 20 Feb 2013, 15:40 last edited by
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: CB 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: BAnd 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?
-
wrote on 21 Feb 2013, 13:22 last edited by
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.
-
wrote on 26 Feb 2013, 17:51 last edited by
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: myDelegateColumn { 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: 0signal 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) } }
}@
1/3