From 7464efbd9596110cf57324ebe9d40fec65e74372 Mon Sep 17 00:00:00 2001 From: PhatPhuckDave Date: Tue, 19 Aug 2025 08:38:27 +0200 Subject: [PATCH] feat(main.py): add undo jump functionality with H key --- main.py | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/main.py b/main.py index a91b573..b10df22 100644 --- a/main.py +++ b/main.py @@ -87,6 +87,9 @@ class MediaGrader: # Bisection navigation tracking self.last_jump_position = {} # Dict[file_path: last_frame] for bisection reference + # Jump history for H key (undo jump) + self.jump_history = {} # Dict[file_path: List[frame_positions]] for jump undo + def find_media_files(self) -> List[Path]: """Find all media files recursively in the directory""" media_files = [] @@ -313,6 +316,11 @@ class MediaGrader: # Track last position for bisection self.last_jump_position[current_file] = self.current_frame + # Track jump history for H key undo + if current_file not in self.jump_history: + self.jump_history[current_file] = [] + self.jump_history[current_file].append(self.current_frame) + # Jump to the target frame self.current_cap.set(cv2.CAP_PROP_POS_FRAMES, target_frame) self.load_current_frame() @@ -415,6 +423,36 @@ class MediaGrader: print(f"Bisected forwards to frame {midpoint} ({percentage:.1f}% through video)") return True + def undo_jump(self): + """Undo the last L jump by returning to previous position""" + if not self.is_video(self.media_files[self.current_index]): + return False + + current_file = str(self.media_files[self.current_index]) + + if current_file not in self.jump_history or not self.jump_history[current_file]: + print("No jump history to undo. Use L first to establish jump points.") + return False + + # Get the last position before the most recent jump + if len(self.jump_history[current_file]) < 1: + print("No previous position to return to.") + return False + + # Remove the current position from history and get the previous one + previous_position = self.jump_history[current_file].pop() + + # Jump back to previous position + self.current_cap.set(cv2.CAP_PROP_POS_FRAMES, previous_position) + self.load_current_frame() + + # Update last jump position for bisection reference + self.last_jump_position[current_file] = previous_position + + percentage = (previous_position / self.total_frames) * 100 + print(f"Undid jump: returned to frame {previous_position} ({percentage:.1f}% through video)") + return True + def display_current_frame(self): """Display the current cached frame with overlays""" if self.current_display_frame is None: @@ -719,8 +757,9 @@ class MediaGrader: print(" P: Previous file") print(" U: Undo last grading action") print(" L: Sample video at key points (videos only)") - print(" K: Bisect backwards from current position (videos only)") - print(" J: Bisect forwards toward next sample (videos only)") + print(" H: Undo last L jump (videos only)") + print(" J: Bisect backwards from current position (videos only)") + print(" K: Bisect forwards toward next sample (videos only)") print(" Q/ESC: Quit") cv2.namedWindow("Media Grader", cv2.WINDOW_NORMAL) @@ -782,6 +821,8 @@ class MediaGrader: self.bisect_backwards() elif key == ord("k"): self.bisect_forwards() + elif key == ord("h"): # Changed from "j" to "h" for undo jump + self.undo_jump() elif key in [ord("1"), ord("2"), ord("3"), ord("4"), ord("5")]: grade = int(chr(key)) if not self.grade_media(grade):