diff --git a/Orange/widgets/utils/itemmodels.py b/Orange/widgets/utils/itemmodels.py index 267270776d0..c99c5fa4cf4 100644 --- a/Orange/widgets/utils/itemmodels.py +++ b/Orange/widgets/utils/itemmodels.py @@ -118,7 +118,7 @@ def mapToSourceRows(self, rows): Parameters ---------- - rows : int or list of int or numpy.ndarray or Ellipsis + rows : int or list of int or numpy.ndarray of dtype=int or Ellipsis View (sorted) rows. Returns @@ -127,7 +127,10 @@ def mapToSourceRows(self, rows): Source rows matching input rows. If they are the same, simply input `rows` is returned. """ - if self.__sortInd is not None: + # self.__sortInd[rows] fails if `rows` is an empty list or array + if self.__sortInd is not None \ + and (isinstance(rows, (Integral, type(Ellipsis))) + or len(rows)): new_rows = self.__sortInd[rows] if rows is Ellipsis: new_rows.setflags(write=False) @@ -139,7 +142,7 @@ def mapFromSourceRows(self, rows): Parameters ---------- - rows : int or list of int or numpy.ndarray or Ellipsis + rows : int or list of int or numpy.ndarray of dtype=int or Ellipsis Source model rows. Returns @@ -148,7 +151,10 @@ def mapFromSourceRows(self, rows): ModelIndex (sorted) rows matching input source rows. If they are the same, simply input `rows` is returned. """ - if self.__sortIndInv is not None: + # self.__sortInd[rows] fails if `rows` is an empty list or array + if self.__sortIndInv is not None \ + and (isinstance(rows, (Integral, type(Ellipsis))) + or len(rows)): new_rows = self.__sortIndInv[rows] if rows is Ellipsis: new_rows.setflags(write=False) diff --git a/Orange/widgets/utils/tests/test_itemmodels.py b/Orange/widgets/utils/tests/test_itemmodels.py index a586fda2944..f6576b05090 100644 --- a/Orange/widgets/utils/tests/test_itemmodels.py +++ b/Orange/widgets/utils/tests/test_itemmodels.py @@ -3,6 +3,8 @@ from unittest import TestCase +import numpy as np + from AnyQt.QtCore import Qt from Orange.data import Domain, ContinuousVariable, DiscreteVariable @@ -121,17 +123,31 @@ def test_other_roles(self): class TestAbstractSortTableModel(TestCase): - def setUp(self): - assert issubclass(PyTableModel, AbstractSortTableModel) - self.model = PyTableModel([[1, 4], - [2, 3]]) - def test_sorting(self): - self.model.sort(1, Qt.AscendingOrder) - self.assertSequenceEqual(self.model.mapToSourceRows(...).tolist(), [1, 0]) - - self.model.sort(1, Qt.DescendingOrder) - self.assertSequenceEqual(self.model.mapToSourceRows(...).tolist(), [0, 1]) + assert issubclass(PyTableModel, AbstractSortTableModel) + model = PyTableModel([[1, 4], + [2, 2], + [3, 3]]) + model.sort(1, Qt.AscendingOrder) + # mapToSourceRows + self.assertSequenceEqual(model.mapToSourceRows(...).tolist(), [1, 2, 0]) + self.assertEqual(model.mapToSourceRows(1).tolist(), 2) + self.assertSequenceEqual(model.mapToSourceRows([1, 2]).tolist(), [2, 0]) + self.assertSequenceEqual(model.mapToSourceRows([]), []) + self.assertSequenceEqual(model.mapToSourceRows(np.array([], dtype=int)).tolist(), []) + self.assertRaises(IndexError, model.mapToSourceRows, np.r_[0.]) + + # mapFromSourceRows + self.assertSequenceEqual(model.mapFromSourceRows(...).tolist(), [2, 0, 1]) + self.assertEqual(model.mapFromSourceRows(1).tolist(), 0) + self.assertSequenceEqual(model.mapFromSourceRows([1, 2]).tolist(), [0, 1]) + self.assertSequenceEqual(model.mapFromSourceRows([]), []) + self.assertSequenceEqual(model.mapFromSourceRows(np.array([], dtype=int)).tolist(), []) + self.assertRaises(IndexError, model.mapFromSourceRows, np.r_[0.]) + + model.sort(1, Qt.DescendingOrder) + self.assertSequenceEqual(model.mapToSourceRows(...).tolist(), [0, 2, 1]) + self.assertSequenceEqual(model.mapFromSourceRows(...).tolist(), [0, 2, 1]) class TestPyListModel(TestCase):