Skip to content

Commit

Permalink
ListViewFilter: Retain selection when filtering (#270)
Browse files Browse the repository at this point in the history
ListViewFilter: Retain selection when filtering
  • Loading branch information
VesnaT committed May 14, 2024
1 parent 6ddb801 commit 29a6da8
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 1 deletion.
25 changes: 24 additions & 1 deletion orangewidget/utils/listview.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@
QSortFilterProxyModel,
QItemSelection,
QSize,
QItemSelectionModel,
)

from orangewidget.utils.itemmodels import signal_blocking


class ListViewFilter(QListView):
"""
Expand All @@ -27,6 +30,7 @@ def __init__(
**kwargs
):
super().__init__(*args, **kwargs)
self.__selection = QItemSelection()
self.__search = QLineEdit(self, placeholderText="Filter...")
self.__search.textEdited.connect(self.__on_text_edited)
self.__preferred_size = preferred_size
Expand All @@ -40,9 +44,28 @@ def __init__(
assert isinstance(proxy, QSortFilterProxyModel)
super().setModel(proxy)
self.set_source_model(model)
self.selectionModel().selectionChanged.connect(self.__on_sel_changed)

def __on_sel_changed(
self,
selected: QItemSelection,
deselected: QItemSelection
):
selected = self.model().mapSelectionToSource(selected)
deselected = self.model().mapSelectionToSource(deselected)
self.__selection.merge(selected, QItemSelectionModel.Select)
self.__selection.merge(deselected, QItemSelectionModel.Deselect)
self.__select()

def __on_text_edited(self, string: str):
self.model().setFilterFixedString(string)
with signal_blocking(self.selectionModel()):
self.model().setFilterFixedString(string)
self.__select()

def __select(self):
selection = self.model().mapSelectionFromSource(self.__selection)
self.selectionModel().select(selection,
QItemSelectionModel.ClearAndSelect)

def setModel(self, _):
raise TypeError("The model cannot be changed. "
Expand Down
15 changes: 15 additions & 0 deletions orangewidget/utils/tests/test_listview.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,21 @@ def test_set_proxy(self):
def test_set_proxy_raises(self):
self.assertRaises(Exception, ListViewFilter, proxy=PyListModel())

def test_selection(self):
view = ListViewFilter()
view.model().setSourceModel(PyListModel(["one", "two", "three"]))
sel_model = view.selectionModel()
selected_row = 0
index = view.model().index(selected_row, 0)
sel_model.select(index, sel_model.ClearAndSelect)
self.assertEqual(sel_model.selectedRows(0)[0].row(), selected_row)

view._ListViewFilter__search.textEdited.emit("two")
self.assertEqual(len(sel_model.selectedRows(0)), 0)

view._ListViewFilter__search.textEdited.emit("")
self.assertEqual(sel_model.selectedRows(0)[0].row(), selected_row)


if __name__ == "__main__":
unittest.main()

0 comments on commit 29a6da8

Please sign in to comment.