3030)
3131from AnyQt .QtGui import (
3232 QStandardItemModel , QStandardItem , QKeySequence , QIcon , QBrush , QPalette ,
33- QHelpEvent
33+ QHelpEvent , QColor
3434)
3535from AnyQt .QtCore import (
3636 Qt , QSize , QModelIndex , QAbstractItemModel , QPersistentModelIndex , QRect ,
3737 QPoint , QItemSelectionModel
3838)
3939from AnyQt .QtCore import pyqtSignal as Signal , pyqtSlot as Slot
4040
41+ from orangecanvas .gui .utils import luminance
4142from orangecanvas .utils import assocf
4243from orangewidget .utils .listview import ListViewSearch
4344
@@ -1577,6 +1578,12 @@ def variable_icon(var):
15771578#: (`List[Union[ReinterpretTransform, Transform]]`)
15781579TransformRole = Qt .UserRole + 42
15791580
1581+ #: Any warnings applying to the transform (`list[tuple[Msg, str]]`)
1582+ RestoreWarningRole = TransformRole + 1
1583+
1584+ #: Hint key that was used to load stored settings.
1585+ RestoreHintKey = RestoreWarningRole + 1
1586+
15801587
15811588class VariableEditDelegate (QStyledItemDelegate ):
15821589 ReinterpretNames = {
@@ -1624,9 +1631,24 @@ def initStyleOption(self, option, index):
16241631 option .font .setItalic (True )
16251632
16261633 multiplicity = index .data (MultiplicityRole )
1634+ warnings_ = index .data (RestoreWarningRole )
1635+
1636+ def set_color (palette : QPalette , color ):
1637+ palette .setBrush (QPalette .Text , QBrush (color ))
1638+ palette .setBrush (QPalette .HighlightedText , QBrush (color ))
1639+
16271640 if isinstance (multiplicity , int ) and multiplicity > 1 :
1628- option .palette .setBrush (QPalette .Text , QBrush (Qt .red ))
1629- option .palette .setBrush (QPalette .HighlightedText , QBrush (Qt .red ))
1641+ set_color (option .palette , Qt .red )
1642+ elif warnings_ :
1643+ set_color (option .palette , self .warning_text_color (option .palette ))
1644+
1645+ @staticmethod
1646+ def warning_text_color (palette : QPalette ):
1647+ background = palette .color (QPalette .ColorRole .Base )
1648+ if luminance (background ) > 0.5 :
1649+ return QColor (255 , 148 , 11 )
1650+ else :
1651+ return QColor (Qt .GlobalColor .yellow )
16301652
16311653 def helpEvent (self , event : QHelpEvent , view : QAbstractItemView ,
16321654 option : QStyleOptionViewItem , index : QModelIndex ) -> bool :
@@ -2123,16 +2145,18 @@ def reset_selected(self):
21232145 modified = []
21242146 for ind in self .selected_var_indices ():
21252147 midx = model .index (ind )
2126- if midx .data (TransformRole ):
2127- model .setData (midx , [], TransformRole )
2128- var = midx .data (Qt .EditRole )
2129- self ._store_transform (var , [])
2130- modified .append (var )
2148+ model .setData (midx , [], TransformRole )
2149+ model .setData (midx , None , RestoreWarningRole )
2150+ key = model .data (midx , RestoreHintKey )
2151+ var = midx .data (Qt .EditRole )
2152+ self ._domain_change_hints .pop (key , None )
2153+ modified .append (var )
21312154 if modified :
21322155 with disconnected (editor .variable_changed ,
21332156 self ._on_variable_changed ):
21342157 self ._editor .set_data (modified )
21352158 self ._invalidate ()
2159+ self ._update_restore_warnings ()
21362160
21372161 def reset_all (self ):
21382162 """Reset all variables to their original state."""
@@ -2141,8 +2165,12 @@ def reset_all(self):
21412165 for i in range (model .rowCount ()):
21422166 midx = model .index (i )
21432167 model .setData (midx , [], TransformRole )
2168+ model .setData (midx , None , RestoreWarningRole )
2169+ key = model .data (midx , RestoreHintKey )
2170+ self ._domain_change_hints .pop (key , None )
21442171 self .open_editor ()
21452172 self ._invalidate ()
2173+ self ._update_restore_warnings ()
21462174
21472175 def selected_var_indices (self ):
21482176 """Return the current selected variable indices."""
@@ -2199,7 +2227,6 @@ def _restore(self):
21992227 model = self .variables_model
22002228 hints = self ._domain_change_hints
22012229 first_key = None
2202- msgs = []
22032230 for i in range (model .rowCount ()):
22042231 midx = model .index (i , 0 )
22052232 coldesc = model .data (midx , Qt .EditRole ) # type: DataVector
@@ -2208,9 +2235,10 @@ def _restore(self):
22082235 key , tr = res
22092236 if tr :
22102237 self ._store_transform (coldesc .vtype , tr , key )
2211- tr , msgs_ = self ._sanitize_transform (coldesc .vtype , tr )
2238+ tr , msgs = self ._sanitize_transform (coldesc .vtype , tr )
22122239 model .setData (midx , tr , TransformRole )
2213- msgs .extend (msgs_ )
2240+ model .setData (midx , msgs , RestoreWarningRole )
2241+ model .setData (midx , key , RestoreHintKey )
22142242 if first_key is None :
22152243 first_key = key
22162244 # Reduce the number of hints to MAX_HINTS, but keep all current hints
@@ -2219,9 +2247,7 @@ def _restore(self):
22192247 (key := next (iter (hints ))) != first_key :
22202248 del hints [key ] # pylint: disable=unsupported-delete-operation
22212249
2222- # Show warnings for non-applicable transforms
2223- for msg , names in groupby (msgs , key = itemgetter (0 )):
2224- msg (", " .join (map (itemgetter (1 ), names )))
2250+ self ._update_restore_warnings ()
22252251
22262252 # Restore the current variable selection
22272253 selected_rows = [i for i , vec in enumerate (model )
@@ -2230,6 +2256,19 @@ def _restore(self):
22302256 selected_rows = [0 ]
22312257 itemmodels .select_rows (self .variables_view , selected_rows )
22322258
2259+ def _update_restore_warnings (self ):
2260+ def messages (midx ):
2261+ msgs = model .data (midx , RestoreWarningRole )
2262+ return msgs or []
2263+ model = self .variables_model
2264+ msgs = chain .from_iterable (
2265+ messages (model .index (i )) for i in range (model .rowCount ())
2266+ )
2267+ self .Warning .cat_mapping_does_not_apply .clear ()
2268+ # Show warnings for non-applicable transforms
2269+ for msg , names in groupby (sorted (msgs ), key = itemgetter (0 )):
2270+ msg (", " .join (map (itemgetter (1 ), names )))
2271+
22332272 def _on_selection_changed (self , _ , deselected ):
22342273 # If the user deselected the last item, select it back with disabled
22352274 # signals, so nothing happens
@@ -2278,19 +2317,22 @@ def _on_variable_changed(self):
22782317 * editor .get_data ()):
22792318 midx = model .index (idx , 0 )
22802319 model .setData (midx , transform , TransformRole )
2320+ model .setData (midx , None , RestoreWarningRole )
22812321 self ._store_transform (var , transform )
22822322 self ._invalidate ()
2323+ self ._update_restore_warnings ()
22832324
22842325 def _store_transform (
2285- self , var : Variable , transform : Iterable [Transform ], deconvar = None
2326+ self , var : Variable , transform : Sequence [Transform ] | None , deconvar = None
22862327 ) -> None :
22872328 deconvar = deconvar or deconstruct (var )
22882329 # Remove the existing key (if any) to put the new one at the end,
22892330 # to make sure it comes after the sentinel
22902331 self ._domain_change_hints .pop (deconvar , None )
22912332 # pylint: disable=unsupported-assignment-operation
2292- self ._domain_change_hints [deconvar ] = \
2293- [deconstruct (t ) for t in transform ]
2333+ if transform :
2334+ self ._domain_change_hints [deconvar ] = \
2335+ [deconstruct (t ) for t in transform ]
22942336
22952337 def _find_stored_transform (
22962338 self , var : Variable
0 commit comments