Repository: biolab/orange3

Issue:
Select Data By Index: miserably looking widget
**What's your use case?**

It's not only that it looks miserable: the new tooltip (window at the bottom right) already shows more information than what's in the widget. The tooltip for the output is even larger.

<img width="394" alt="Screenshot 2021-08-28 at 20 13 11" src="https://user-images.githubusercontent.com/2387315/131227067-24666e74-2809-4a1d-bad4-346272306ce6.png">

**What's your proposed solution?**

None, but it'd be good to think what to put into this widget instead. Given its mysteriousness, there could simply be a short label explaining what the widget does, to inform the user who is randomly exploring the widgets.



Discussion:
Same for Apply Domain, just a tad less ugly.

<img width="296" alt="Screenshot 2021-08-28 at 21 04 12" src="https://user-images.githubusercontent.com/2387315/131228231-d9d88224-ccb7-4be1-9401-a0cc35313b7a.png">

What about a 5-row preview? In a no-thrills data table (no sorting, selection, etc.).
Cancel that. We are going to implement tetris in those widgets.

Resolving patch:
diff --git a/Orange/widgets/data/owselectbydataindex.py b/Orange/widgets/data/owselectbydataindex.py
--- a/Orange/widgets/data/owselectbydataindex.py
+++ b/Orange/widgets/data/owselectbydataindex.py
@@ -45,35 +45,30 @@ def __init__(self):
         self.extra_model_unique = itemmodels.VariableListModel()
         self.extra_model_unique_with_id = itemmodels.VariableListModel()
 
-        box = gui.hBox(self.controlArea, box=None)
-        self.infoBoxData = gui.label(
-            box, self, self.data_info_text(None), box="Data")
-        self.infoBoxExtraData = gui.label(
-            box, self, self.data_info_text(None), box="Data Subset")
+        box = gui.widgetBox(self.controlArea, True)
+        gui.label(
+            box, self, """
+Data rows keep their identity even when some or all original variables
+are replaced by variables computed from the original ones.
+
+This widget gets two data tables ("Data" and "Data Subset") that
+can be traced back to the same source. It selects all rows from Data
+that appear in Data Subset, based on row identity and not actual data.
+""".strip(), box=True)
 
     @Inputs.data
     @check_sql_input
     def set_data(self, data):
         self.data = data
-        self.infoBoxData.setText(self.data_info_text(data))
 
     @Inputs.data_subset
     @check_sql_input
     def set_data_subset(self, data):
         self.data_subset = data
-        self.infoBoxExtraData.setText(self.data_info_text(data))
 
     def handleNewSignals(self):
         self._invalidate()
 
-    @staticmethod
-    def data_info_text(data):
-        if data is None:
-            return "No data."
-        else:
-            return "{}\n{} instances\n{} variables".format(
-                data.name, len(data), len(data.domain.variables) + len(data.domain.metas))
-
     def commit(self):
         self.Warning.instances_not_matching.clear()
         subset_ids = []
@@ -100,8 +95,15 @@ def _invalidate(self):
         self.commit()
 
     def send_report(self):
-        d_text = self.data_info_text(self.data).replace("\n", ", ")
-        ds_text = self.data_info_text(self.data_subset).replace("\n", ", ")
+        def data_info_text(data):
+            if data is None:
+                return "No data."
+            return "{}\n{} instances\n{} variables".format(
+                data.name, len(data),
+                len(data.domain.variables) + len(data.domain.metas))
+
+        d_text = data_info_text(self.data).replace("\n", ", ")
+        ds_text = data_info_text(self.data_subset).replace("\n", ", ")
         self.report_items("", [("Data", d_text), ("Data Subset", ds_text)])
 
 
diff --git a/Orange/widgets/data/owtransform.py b/Orange/widgets/data/owtransform.py
--- a/Orange/widgets/data/owtransform.py
+++ b/Orange/widgets/data/owtransform.py
@@ -36,42 +36,21 @@ def __init__(self):
         self.template_data = None  # type: Optional[Table]
         self.transformed_info = describe_data(None)  # type: OrderedDict
 
-        info_box = gui.widgetBox(self.controlArea, "Info")
-        self.input_label = gui.widgetLabel(info_box, "")
-        self.template_label = gui.widgetLabel(info_box, "")
-        self.output_label = gui.widgetLabel(info_box, "")
-        self.set_input_label_text()
-        self.set_template_label_text()
-
-    def set_input_label_text(self):
-        text = "No data on input."
-        if self.data:
-            text = "Input data with {:,} instances and {:,} features.".format(
-                len(self.data),
-                len(self.data.domain.attributes))
-        self.input_label.setText(text)
+        box = gui.widgetBox(self.controlArea, True)
+        gui.label(
+            box, self, """
+The widget takes Data, to which it re-applies transformations
+that were applied to Template Data.
 
-    def set_template_label_text(self):
-        text = "No template data on input."
-        if self.data and self.template_data:
-            text = "Template domain applied."
-        elif self.template_data:
-            text = "Template data includes {:,} features.".format(
-                len(self.template_data.domain.attributes))
-        self.template_label.setText(text)
-
-    def set_output_label_text(self, data):
-        text = ""
-        if data:
-            text = "Output data includes {:,} features.".format(
-                len(data.domain.attributes))
-        self.output_label.setText(text)
+These include selecting a subset of variables as well as
+computing variables from other variables appearing in the data,
+like, for instance, discretization, feature construction, PCA etc.
+""".strip(), box=True)
 
     @Inputs.data
     @check_sql_input
     def set_data(self, data):
         self.data = data
-        self.set_input_label_text()
 
     @Inputs.template_data
     @check_sql_input
@@ -93,8 +72,6 @@ def apply(self):
         data = transformed_data
         self.transformed_info = describe_data(data)
         self.Outputs.transformed_data.send(data)
-        self.set_template_label_text()
-        self.set_output_label_text(data)
 
     def send_report(self):
         if self.data:


Test patch:
diff --git a/Orange/widgets/data/tests/test_owtransform.py b/Orange/widgets/data/tests/test_owtransform.py
--- a/Orange/widgets/data/tests/test_owtransform.py
+++ b/Orange/widgets/data/tests/test_owtransform.py
@@ -23,49 +23,24 @@ def test_output(self):
         self.send_signal(self.widget.Inputs.template_data, self.disc_data)
         output = self.get_output(self.widget.Outputs.transformed_data)
         self.assertTableEqual(output, self.disc_data[::15])
-        self.assertEqual("Input data with 10 instances and 4 features.",
-                         self.widget.input_label.text())
-        self.assertEqual("Template domain applied.",
-                         self.widget.template_label.text())
-        self.assertEqual("Output data includes 4 features.",
-                         self.widget.output_label.text())
 
         # remove template data
         self.send_signal(self.widget.Inputs.template_data, None)
         output = self.get_output(self.widget.Outputs.transformed_data)
         self.assertIsNone(output)
-        self.assertEqual("Input data with 10 instances and 4 features.",
-                         self.widget.input_label.text())
-        self.assertEqual("No template data on input.",
-                         self.widget.template_label.text())
-        self.assertEqual("", self.widget.output_label.text())
 
         # send template data
         self.send_signal(self.widget.Inputs.template_data, self.disc_data)
         output = self.get_output(self.widget.Outputs.transformed_data)
         self.assertTableEqual(output, self.disc_data[::15])
-        self.assertEqual("Input data with 10 instances and 4 features.",
-                         self.widget.input_label.text())
-        self.assertEqual("Template domain applied.",
-                         self.widget.template_label.text())
-        self.assertEqual("Output data includes 4 features.",
-                         self.widget.output_label.text())
 
         # remove data
         self.send_signal(self.widget.Inputs.data, None)
         output = self.get_output(self.widget.Outputs.transformed_data)
         self.assertIsNone(output)
-        self.assertEqual("No data on input.", self.widget.input_label.text())
-        self.assertEqual("Template data includes 4 features.",
-                         self.widget.template_label.text())
-        self.assertEqual("", self.widget.output_label.text())
 
         # remove template data
         self.send_signal(self.widget.Inputs.template_data, None)
-        self.assertEqual("No data on input.", self.widget.input_label.text())
-        self.assertEqual("No template data on input.",
-                         self.widget.template_label.text())
-        self.assertEqual("", self.widget.output_label.text())
 
     def assertTableEqual(self, table1, table2):
         self.assertIs(table1.domain, table2.domain)
@@ -82,7 +57,7 @@ def test_input_pca_output(self):
         self.send_signal(self.widget.Inputs.data, self.data[::10])
         self.send_signal(self.widget.Inputs.template_data, pca_out)
         output = self.get_output(self.widget.Outputs.transformed_data)
-        npt.assert_array_equal(pca_out.X[::10], output.X)
+        npt.assert_array_almost_equal(pca_out.X[::10], output.X)
 
     def test_error_transforming(self):
         data = self.data[::10]