11from functools import partial
2- from typing import Optional
2+ from typing import Optional , Dict , Tuple
33
44from AnyQt .QtWidgets import QWidget , QGridLayout
55from AnyQt .QtWidgets import QListView
88 QMimeData , QAbstractItemModel
99)
1010
11+ from Orange .data import Domain , Variable
1112from Orange .widgets import gui , widget
1213from Orange .widgets .settings import (
1314 ContextSetting , Setting , DomainContextHandler
@@ -167,6 +168,7 @@ class Outputs:
167168 settingsHandler = SelectAttributesDomainContextHandler (first_match = False )
168169 domain_role_hints = ContextSetting ({})
169170 use_input_features = Setting (False )
171+ select_new_features = Setting (True )
170172 auto_commit = Setting (True )
171173
172174 class Warning (widget .OWWidget .Warning ):
@@ -286,7 +288,7 @@ def dropcompleted(action):
286288 self .down_class_button = gui .button (bbox , self , "Down" ,
287289 callback = partial (self .move_down , self .class_attrs_view ))
288290
289- bbox = gui .vBox (self .controlArea , addToLayout = False , margin = 0 )
291+ bbox = gui .vBox (self .controlArea , addToLayout = False )
290292 layout .addWidget (bbox , 2 , 1 , 1 , 1 )
291293 self .up_meta_button = gui .button (bbox , self , "Up" ,
292294 callback = partial (self .move_up , self .meta_attrs_view ))
@@ -297,8 +299,14 @@ def dropcompleted(action):
297299 self .down_meta_button = gui .button (bbox , self , "Down" ,
298300 callback = partial (self .move_down , self .meta_attrs_view ))
299301
302+ bbox = gui .vBox (self .controlArea , "Additional settings" , addToLayout = False )
303+ gui .checkBox (
304+ bbox , self , "select_new_features" , "Automatically select additional/new features"
305+ )
306+ layout .addWidget (bbox , 3 , 0 , 1 , 3 )
307+
300308 autobox = gui .auto_send (None , self , "auto_commit" )
301- layout .addWidget (autobox , 3 , 0 , 1 , 3 )
309+ layout .addWidget (autobox , 4 , 0 , 1 , 3 )
302310 reset = gui .button (None , self , "Reset" , callback = self .reset , width = 120 )
303311 autobox .layout ().insertWidget (0 , reset )
304312 autobox .layout ().insertStretch (1 , 20 )
@@ -370,19 +378,50 @@ def attrs_for_role(role):
370378 ]
371379 return sorted (selected_attrs , key = lambda attr : domain_hints [attr ][1 ])
372380
373- domain = data .domain
374- domain_hints = {}
375- domain_hints .update (self ._hints_from_seq ("attribute" , domain .attributes ))
376- domain_hints .update (self ._hints_from_seq ("meta" , domain .metas ))
377- domain_hints .update (self ._hints_from_seq ("class" , domain .class_vars ))
378- domain_hints .update (self .domain_role_hints )
379-
381+ domain_hints = self .restore_hints (data .domain )
380382 self .used_attrs [:] = attrs_for_role ("attribute" )
381383 self .class_attrs [:] = attrs_for_role ("class" )
382384 self .meta_attrs [:] = attrs_for_role ("meta" )
383385 self .available_attrs [:] = attrs_for_role ("available" )
384386 self .info .set_input_summary (len (data ), format_summary_details (data ))
385387
388+ def restore_hints (self , domain : Domain ) -> Dict [Variable , Tuple [str , int ]]:
389+ """
390+ Define hints for selected/unselected features.
391+ Rules:
392+ - if context available, restore new features based on checked/unchecked
393+ select_new_features, context hint should be took into account
394+ - in no context, restore features based on the domain (as selected)
395+
396+ Parameters
397+ ----------
398+ domain
399+ Data domain
400+
401+ Returns
402+ -------
403+ Dictionary with hints about order and model in which each feature
404+ should appear
405+ """
406+ domain_hints = {}
407+ if self .select_new_features or len (self .domain_role_hints ) == 0 :
408+ # select_new_features selected or no context - restore based on domain
409+ domain_hints .update (
410+ self ._hints_from_seq ("attribute" , domain .attributes )
411+ )
412+ domain_hints .update (self ._hints_from_seq ("meta" , domain .metas ))
413+ domain_hints .update (
414+ self ._hints_from_seq ("class" , domain .class_vars )
415+ )
416+ else :
417+ # if context restored and select_new_features unselected - restore
418+ # new features as available
419+ d = domain .attributes + domain .metas + domain .class_vars
420+ domain_hints .update (self ._hints_from_seq ("available" , d ))
421+
422+ domain_hints .update (self .domain_role_hints )
423+ return domain_hints
424+
386425 def update_domain_role_hints (self ):
387426 """ Update the domain hints to be stored in the widgets settings.
388427 """
0 commit comments