Skip to content

Commit 31e35f9

Browse files
janezdPrimozGodec
authored andcommitted
Select Columns: Show variable counts
1 parent 6b268bf commit 31e35f9

File tree

3 files changed

+48
-10
lines changed

3 files changed

+48
-10
lines changed

Orange/widgets/data/owselectcolumns.py

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,12 @@ def __init__(self):
187187
self.__interface_update_timer = QTimer(self, interval=0, singleShot=True)
188188
self.__interface_update_timer.timeout.connect(
189189
self.__update_interface_state)
190+
# If __update_var_counts were connected directly to textChanged of
191+
# view box's edit, it could be called before the related proxy is
192+
# updated
193+
self.__var_counts_update_timer = QTimer(self, interval=0, singleShot=True)
194+
self.__var_counts_update_timer.timeout.connect(
195+
self.update_var_counts)
190196
# The last view that has the selection for move operation's source
191197
self.__last_active_view = None # type: Optional[QListView]
192198

@@ -200,16 +206,21 @@ def update_on_change(view):
200206
self.controlArea = new_control_area
201207

202208
# init grid
209+
self.view_boxes = []
203210
layout = QGridLayout()
204211
self.controlArea.setLayout(layout)
205212
layout.setContentsMargins(0, 0, 0, 0)
206-
box = gui.vBox(self.controlArea, "Ignored",
213+
214+
name = "Ignored"
215+
box = gui.vBox(self.controlArea, name,
207216
addToLayout=False)
208217

209218
self.available_attrs = VariablesListItemModel()
210219
filter_edit, self.available_attrs_view = variables_filter(
211220
parent=self, model=self.available_attrs)
212221
box.layout().addWidget(filter_edit)
222+
self.view_boxes.append((name, box, self.available_attrs_view))
223+
filter_edit.textChanged.connect(self.__var_counts_update_timer.start)
213224

214225
def dropcompleted(action):
215226
if action == Qt.MoveAction:
@@ -223,7 +234,8 @@ def dropcompleted(action):
223234
layout.addWidget(box, 0, 0, 3, 1)
224235

225236
# 3rd column
226-
box = gui.vBox(self.controlArea, "Features", addToLayout=False)
237+
name = "Features"
238+
box = gui.vBox(self.controlArea, name, addToLayout=False)
227239
self.used_attrs = VariablesListItemModel()
228240
filter_edit, self.used_attrs_view = variables_filter(
229241
parent=self, model=self.used_attrs,
@@ -245,8 +257,11 @@ def dropcompleted(action):
245257
box.layout().addWidget(filter_edit)
246258
box.layout().addWidget(self.used_attrs_view)
247259
layout.addWidget(box, 0, 2, 1, 1)
260+
self.view_boxes.append((name, box, self.used_attrs_view))
261+
filter_edit.textChanged.connect(self.__var_counts_update_timer.start)
248262

249-
box = gui.vBox(self.controlArea, "Target", addToLayout=False)
263+
name = "Target"
264+
box = gui.vBox(self.controlArea, name, addToLayout=False)
250265
self.class_attrs = VariablesListItemModel()
251266
self.class_attrs_view = VariablesListItemView(
252267
acceptedType=(Orange.data.DiscreteVariable,
@@ -259,8 +274,10 @@ def dropcompleted(action):
259274

260275
box.layout().addWidget(self.class_attrs_view)
261276
layout.addWidget(box, 1, 2, 1, 1)
277+
self.view_boxes.append((name, box, self.class_attrs_view))
262278

263-
box = gui.vBox(self.controlArea, "Metas", addToLayout=False)
279+
name = "Metas"
280+
box = gui.vBox(self.controlArea, name, addToLayout=False)
264281
self.meta_attrs = VariablesListItemModel()
265282
self.meta_attrs_view = VariablesListItemView(
266283
acceptedType=Orange.data.Variable)
@@ -270,6 +287,7 @@ def dropcompleted(action):
270287
self.meta_attrs_view.dragDropActionDidComplete.connect(dropcompleted)
271288
box.layout().addWidget(self.meta_attrs_view)
272289
layout.addWidget(box, 2, 2, 1, 1)
290+
self.view_boxes.append((name, box, self.meta_attrs_view))
273291

274292
# 2nd column
275293
bbox = gui.vBox(self.controlArea, addToLayout=False, margin=0)
@@ -541,9 +559,22 @@ def __update_interface_state(self):
541559
if last_view is not None:
542560
self.update_interface_state(last_view)
543561

562+
def update_var_counts(self):
563+
for name, box, view in self.view_boxes:
564+
model = view.model()
565+
source = source_model(view) # may be the same as model
566+
nall = source.rowCount()
567+
nvars = view.model().rowCount()
568+
if source is not model and model.filter_string():
569+
box.setTitle(f"{name} ({nvars}/{nall})")
570+
elif nall:
571+
box.setTitle(f"{name} ({nvars})")
572+
else:
573+
box.setTitle(name)
574+
544575
def update_interface_state(self, focus=None):
545-
for view in [self.available_attrs_view, self.used_attrs_view,
546-
self.class_attrs_view, self.meta_attrs_view]:
576+
self.update_var_counts()
577+
for *_, view in self.view_boxes:
547578
if view is not focus and not view.hasFocus() \
548579
and view.selectionModel().hasSelection():
549580
view.selectionModel().clear()

Orange/widgets/data/tests/test_owselectcolumns.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,14 @@ def setUp(self):
133133
self.widget = self.create_widget(OWSelectAttributes)
134134

135135
def assertVariableCountsEqual(self, available, used, classattrs, metas=0):
136-
self.assertEqual(len(self.widget.available_attrs), available)
137-
self.assertEqual(len(self.widget.used_attrs), used)
138-
self.assertEqual(len(self.widget.class_attrs), classattrs)
139-
self.assertEqual(len(self.widget.meta_attrs), metas)
136+
self.widget.update_interface_state()
137+
for (name, box, view), nattrs in zip(self.widget.view_boxes,
138+
(available, used, classattrs, metas)):
139+
self.assertEqual(view.model().rowCount(), nattrs)
140+
if nattrs:
141+
self.assertEqual(box.title(), f"{name} ({nattrs})")
142+
else:
143+
self.assertEqual(box.title(), name)
140144

141145
def assertControlsEnabled(self, _list, button, box, widget=None):
142146
if widget is None:

Orange/widgets/utils/listfilter.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@ def set_filter_string(self, filter):
135135
self._filter_string = str(filter).lower()
136136
self.invalidateFilter()
137137

138+
def filter_string(self):
139+
return self._filter_string
140+
138141
def filter_accepts_variable(self, var):
139142
row_str = var.name + " ".join(("%s=%s" % item)
140143
for item in var.attributes.items())

0 commit comments

Comments
 (0)