Repository: biolab/orange3

Issue:
Data Table doesn't select full row
<!--
This is an issue template. Please fill in the relevant details in the
sections below.

Wrap code and verbatim terminal window output into triple backticks, see:
https://help.github.com/articles/basic-writing-and-formatting-syntax/#quoting-code

If you're raising an issue about an add-on (e.g. installed via
Options > Add-ons), raise an issue on the relevant add-on's issue
tracker instead. See: https://github.com/biolab?q=orange3
-->

##### Orange version
<!-- From menu _Help→About→Version_ or code `Orange.version.full_version` -->
3.16.0

##### Expected behavior
If select full row is checked in Data Table, full row should always be selected, even when data changes.

##### Actual behavior
Widget now seems to remember which row was selected and how many attributes were there, so when you change data set from one with 4 attributes to one with 10, only first four attributes are selected initially.


##### Steps to reproduce the behavior
In File widget choose Iris data set, connect it to Data Table, select a line. Now change the data set to heart_disease. Data Table will now select only first four attributes.

##### Additional info (worksheets, data, screenshots, ...)
![screenshot from 2018-09-21 12-28-40](https://user-images.githubusercontent.com/17765889/45876564-3ca7a380-bd9b-11e8-96f2-18cec67c388d.png)





Discussion:
This annoys the hell out of me. Shouldn't selection be context-dependent? If the domain changes, selection should be reset.

Resolving patch:
diff --git a/Orange/widgets/data/owtable.py b/Orange/widgets/data/owtable.py
--- a/Orange/widgets/data/owtable.py
+++ b/Orange/widgets/data/owtable.py
@@ -14,15 +14,14 @@
 from scipy.sparse import issparse
 
 from AnyQt.QtWidgets import (
-    QTableView, QHeaderView, QAbstractButton, QAction, QApplication,
-    QStyleOptionHeader, QStyle, QStylePainter, QStyledItemDelegate
+    QTableView, QHeaderView, QAbstractButton, QApplication, QStyleOptionHeader,
+    QStyle, QStylePainter, QStyledItemDelegate
 )
-from AnyQt.QtGui import QColor, QKeySequence, QClipboard
+from AnyQt.QtGui import QColor, QClipboard
 from AnyQt.QtCore import (
     Qt, QSize, QEvent, QByteArray, QMimeData, QObject, QMetaObject,
     QAbstractProxyModel, QIdentityProxyModel, QModelIndex,
-    QItemSelectionModel, QItemSelection, QItemSelectionRange,
-    QT_VERSION
+    QItemSelectionModel, QItemSelection, QItemSelectionRange
 )
 from AnyQt.QtCore import pyqtSlot as Slot
 
@@ -33,8 +32,7 @@
 from Orange.statistics import basic_stats
 
 from Orange.widgets import widget, gui
-from Orange.widgets.settings import (Setting, ContextSetting,
-                                     DomainContextHandler)
+from Orange.widgets.settings import Setting, DomainContextHandler
 from Orange.widgets.widget import Input, Output
 from Orange.widgets.utils import datacaching
 from Orange.widgets.utils.annotated_data import (create_annotated_table,
@@ -390,14 +388,19 @@ class Outputs:
     color_by_class = Setting(True)
     settingsHandler = DomainContextHandler(
         match_values=DomainContextHandler.MATCH_VALUES_ALL)
-    selected_rows = ContextSetting([])
-    selected_cols = ContextSetting([])
+    selected_rows = Setting([], schema_only=True)
+    selected_cols = Setting([], schema_only=True)
 
     def __init__(self):
         super().__init__()
 
         self._inputs = OrderedDict()
 
+        self.__pending_selected_rows = self.selected_rows
+        self.selected_rows = None
+        self.__pending_selected_cols = self.selected_cols
+        self.selected_cols = None
+
         self.dist_color = QColor(*self.dist_color_RGB)
 
         info_box = gui.vBox(self.controlArea, "Info")
@@ -514,9 +517,20 @@ def update(f):
                 self.set_info(current._input_slot.summary)
 
         self.tabs.tabBar().setVisible(self.tabs.count() > 1)
-        self.selected_rows = []
-        self.selected_cols = []
         self.openContext(data)
+
+        if self.__pending_selected_rows is not None:
+            self.selected_rows = self.__pending_selected_rows
+            self.__pending_selected_rows = None
+        else:
+            self.selected_rows = []
+
+        if self.__pending_selected_cols is not None:
+            self.selected_cols = self.__pending_selected_cols
+            self.__pending_selected_cols = None
+        else:
+            self.selected_cols = []
+
         self.set_selection()
         self.commit()
 


Test patch:
diff --git a/Orange/widgets/data/tests/test_owtable.py b/Orange/widgets/data/tests/test_owtable.py
--- a/Orange/widgets/data/tests/test_owtable.py
+++ b/Orange/widgets/data/tests/test_owtable.py
@@ -2,6 +2,7 @@
 # pylint: disable=missing-docstring
 from Orange.widgets.data.owtable import OWDataTable
 from Orange.widgets.tests.base import WidgetTest, WidgetOutputsTestMixin
+from Orange.data import Table
 
 
 class TestOWDataTable(WidgetTest, WidgetOutputsTestMixin):
@@ -30,6 +31,13 @@ def test_data_model(self):
         self.assertEqual(self.widget.tabs.widget(0).model().rowCount(),
                          len(self.data))
 
+    def test_reset_select(self):
+        self.send_signal(self.widget.Inputs.data, self.data)
+        self._select_data()
+        self.send_signal(self.widget.Inputs.data, Table('heart_disease'))
+        self.assertListEqual([], self.widget.selected_cols)
+        self.assertListEqual([], self.widget.selected_rows)
+
     def _select_data(self):
         self.widget.selected_cols = list(range(len(self.data.domain)))
         self.widget.selected_rows = list(range(0, len(self.data.domain), 10))