@@ -318,3 +318,46 @@ def _apply(self, src, dst):
318318 self .model .dataChanged .emit (
319319 self .model_index , self .model_index , [Qt .DisplayRole ]
320320 )
321+
322+
323+ class RenameValueCommand (QUndoCommand ):
324+ """Command to rename values in specified columns."""
325+
326+ def __init__ (
327+ self , model , old_id : str , new_id : str , column_names : str | list [str ]
328+ ):
329+ super ().__init__ (f"Rename value { old_id } → { new_id } " )
330+ self .model = model
331+ self .old_id = old_id
332+ self .new_id = new_id
333+ self .column_names = (
334+ column_names if isinstance (column_names , list ) else [column_names ]
335+ )
336+ self .changes = {} # {(row_idx, col_name): (old_val, new_val)}
337+
338+ df = self .model ._data_frame
339+ for col_name in self .column_names :
340+ mask = df [col_name ].eq (self .old_id )
341+ for row_idx in df .index [mask ]:
342+ self .changes [(row_idx , col_name )] = (self .old_id , self .new_id )
343+
344+ def redo (self ):
345+ self ._apply_changes (use_new = True )
346+
347+ def undo (self ):
348+ self ._apply_changes (use_new = False )
349+
350+ def _apply_changes (self , use_new : bool ):
351+ df = self .model ._data_frame
352+ for (row_idx , col_name ), (old_val , new_val ) in self .changes .items ():
353+ df .at [row_idx , col_name ] = new_val if use_new else old_val
354+
355+ if self .changes :
356+ rows = [df .index .get_loc (row ) for (row , _ ) in self .changes ]
357+ cols = [df .columns .get_loc (col ) + 1 for (_ , col ) in self .changes ]
358+ top_left = self .model .index (min (rows ), min (cols ))
359+ bottom_right = self .model .index (max (rows ), max (cols ))
360+ self .model .dataChanged .emit (
361+ top_left , bottom_right , [Qt .DisplayRole , Qt .EditRole ]
362+ )
363+ self .model .something_changed .emit (True )
0 commit comments