Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ENH] OWSelectRows: Data info displayed in the status bar #4471

Merged
merged 1 commit into from
Mar 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 17 additions & 28 deletions Orange/widgets/data/owselectrows.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from AnyQt.QtWidgets import (
QWidget, QTableWidget, QHeaderView, QComboBox, QLineEdit, QToolButton,
QMessageBox, QMenu, QListView, QGridLayout, QPushButton, QSizePolicy,
QLabel)
QLabel, QHBoxLayout)
from AnyQt.QtGui import (
QDoubleValidator, QRegExpValidator, QStandardItemModel, QStandardItem,
QFontMetrics, QPalette
Expand All @@ -33,6 +33,7 @@
from Orange.widgets.widget import Msg
from Orange.widgets.utils.annotated_data import (create_annotated_table,
ANNOTATED_DATA_SIGNAL_NAME)
from Orange.widgets.utils.state_summary import format_summary_details


class SelectRowsContextHandler(DomainContextHandler):
Expand Down Expand Up @@ -214,32 +215,29 @@ def __init__(self):
box2, self, "Remove All", callback=self.remove_all)
gui.rubber(box2)

boxes = gui.widgetBox(self.controlArea, orientation=QGridLayout())
boxes = gui.widgetBox(self.controlArea, orientation=QHBoxLayout())
layout = boxes.layout()
layout.setColumnStretch(0, 1)
layout.setColumnStretch(1, 1)

box_data = gui.vBox(boxes, 'Data', addToLayout=False)
self.data_in_variables = gui.widgetLabel(box_data, " ")
self.data_out_rows = gui.widgetLabel(box_data, " ")
layout.addWidget(box_data, 0, 0)

box_setting = gui.vBox(boxes, 'Purging', addToLayout=False)
box_setting = gui.vBox(boxes, addToLayout=False, box=True)
self.cb_pa = gui.checkBox(
box_setting, self, "purge_attributes", "Remove unused features",
callback=self.conditions_changed)
gui.separator(box_setting, height=1)
self.cb_pc = gui.checkBox(
box_setting, self, "purge_classes", "Remove unused classes",
callback=self.conditions_changed)
layout.addWidget(box_setting, 0, 1)
layout.addWidget(box_setting, 1)

self.report_button.setFixedWidth(120)
gui.rubber(self.buttonsArea.layout())
layout.addWidget(self.buttonsArea, 1, 0)
layout.addWidget(self.buttonsArea)

acbox = gui.auto_send(None, self, "auto_commit")
layout.addWidget(acbox, 1, 1)
layout.addWidget(acbox, 1)
layout.setAlignment(acbox, Qt.AlignBottom)

self.info.set_input_summary(self.info.NoInput)
self.info.set_output_summary(self.info.NoOutput)

self.set_data(None)
self.resize(600, 400)
Expand Down Expand Up @@ -471,6 +469,7 @@ def set_data(self, data):
data is None or
len(data.domain.variables) + len(data.domain.metas) > 100)
if not data:
self.info.set_input_summary(self.info.NoInput)
self.data_desc = None
self.commit()
return
Expand All @@ -492,7 +491,8 @@ def set_data(self, data):
else:
self.add_row()

self.update_info(data, self.data_in_variables, "In: ")
self.info.set_input_summary(len(data),
format_summary_details(data))
self.unconditional_commit()

def conditions_changed(self):
Expand Down Expand Up @@ -628,20 +628,9 @@ def commit(self):
self.match_desc = report.describe_data_brief(matching_output)
self.nonmatch_desc = report.describe_data_brief(non_matching_output)

self.update_info(matching_output, self.data_out_rows, "Out: ")

def update_info(self, data, lab1, label):
def sp(s, capitalize=True):
return s and s or ("No" if capitalize else "no"), "s" * (s != 1)

if data is None:
lab1.setText("")
else:
lab1.setText(label + "~%s row%s, %s variable%s" %
(sp(data.approx_len()) +
sp(len(data.domain.variables) +
len(data.domain.metas)))
)
summary = len(matching_output) if matching_output else self.info.NoOutput
details = format_summary_details(matching_output) if matching_output else ""
self.info.set_output_summary(summary, details)

def send_report(self):
if not self.data:
Expand Down
28 changes: 27 additions & 1 deletion Orange/widgets/data/tests/test_owselectrows.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Test methods with long descriptive names can omit docstrings
# pylint: disable=missing-docstring
# pylint: disable=missing-docstring,unsubscriptable-object
import time
from unittest.mock import Mock

from AnyQt.QtCore import QLocale, Qt
from AnyQt.QtTest import QTest
Expand All @@ -17,6 +18,7 @@
from Orange.data.filter import FilterContinuous, FilterString
from Orange.widgets.tests.utils import simulate, override_locale
from Orange.widgets.utils.annotated_data import ANNOTATED_DATA_FEATURE_NAME
from Orange.widgets.utils.state_summary import format_summary_details
from Orange.tests import test_filename
from orangewidget.settings import VERSION_KEY

Expand Down Expand Up @@ -227,6 +229,30 @@ def test_is_defined_on_continuous_variable(self):
# Test saving of settings
self.widget.settingsHandler.pack_data(self.widget)

def test_summary(self):
"""Check if status bar displays correct input/output summary"""
input_sum = self.widget.info.set_input_summary = Mock()
output_sum = self.widget.info.set_output_summary = Mock()

data = Table("iris")
self.send_signal(self.widget.Inputs.data, data)
input_sum.assert_called_with(len(data), format_summary_details(data))
output = self.get_output("Matching Data")
output_sum.assert_called_with(len(output),
format_summary_details(output))

self.enterFilter(data.domain["iris"], "is", "Iris-setosa")
output = self.get_output("Matching Data")
output_sum.assert_called_with(len(output),
format_summary_details(output))
input_sum.reset_mock()
output_sum.reset_mock()
self.send_signal(self.widget.Inputs.data, None)
input_sum.assert_called_once()
self.assertEqual(input_sum.call_args[0][0].brief, "")
output_sum.assert_called_once()
self.assertEqual(output_sum.call_args[0][0].brief, "")

def test_output_filter(self):
"""
None on output when there is no data.
Expand Down