From 267519a034b3e01a82da5112929ccaa793e152e0 Mon Sep 17 00:00:00 2001 From: tanyar09 Date: Mon, 29 Sep 2025 12:24:34 -0400 Subject: [PATCH] Implement tracking of original checkbox states in PhotoTagger to enhance unsaved changes detection. Update logic to compare current and original states, ensuring accurate identification of unsaved changes. Refactor save functionality to avoid modifying original states, improving user experience and data integrity. --- photo_tagger.py | 50 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/photo_tagger.py b/photo_tagger.py index dc1274a..7e116cc 100644 --- a/photo_tagger.py +++ b/photo_tagger.py @@ -2782,6 +2782,7 @@ class PhotoTagger: match_vars = [] identified_faces_per_person = {} # Track which faces were identified for each person checkbox_states_per_person = {} # Track checkbox states for each person (unsaved selections) + original_checkbox_states_per_person = {} # Track original/default checkbox states for comparison def on_confirm_matches(): nonlocal identified_count, current_matched_index, identified_faces_per_person @@ -2832,9 +2833,13 @@ class PhotoTagger: for person_id in set(match['person_id'] for match in matches_for_this_person if match['person_id']): self._update_person_encodings(person_id) - # Clear checkbox states for this person after saving - if matched_id in checkbox_states_per_person: - del checkbox_states_per_person[matched_id] + # After saving, set original states to the current UI states so there are no unsaved changes + current_snapshot = {} + for match, var in zip(matches_for_this_person, match_vars): + unique_key = f"{matched_id}_{match['unidentified_id']}" + current_snapshot[unique_key] = var.get() + checkbox_states_per_person[matched_id] = dict(current_snapshot) + original_checkbox_states_per_person[matched_id] = dict(current_snapshot) def on_skip_current(): nonlocal current_matched_index @@ -2855,8 +2860,19 @@ class PhotoTagger: update_display() def has_unsaved_changes(): - """Check if there are any unsaved changes in checkbox_states_per_person""" - return len(checkbox_states_per_person) > 0 + """Check if there are any unsaved changes by comparing current states with original states""" + for person_id, current_states in checkbox_states_per_person.items(): + if person_id in original_checkbox_states_per_person: + original_states = original_checkbox_states_per_person[person_id] + # Check if any checkbox state differs from its original state + for key, current_value in current_states.items(): + if key not in original_states or original_states[key] != current_value: + return True + else: + # If person has current states but no original states, there are changes + if any(current_states.values()): + return True + return False def on_quit_auto_match(): nonlocal window_destroyed @@ -3003,7 +3019,10 @@ class PhotoTagger: save_btn.config(text="💾 Save Changes") def save_current_checkbox_states(): - """Save current checkbox states for the current person""" + """Save current checkbox states for the current person. + Note: Do NOT modify original states here to avoid false positives + when a user toggles and reverts a checkbox. + """ if current_matched_index < len(matched_ids) and match_vars: current_matched_id = matched_ids[current_matched_index] matches_for_current_person = matches_by_matched[current_matched_id] @@ -3015,9 +3034,11 @@ class PhotoTagger: # Save current checkbox states for this person for i, (match, var) in enumerate(zip(matches_for_current_person, match_vars)): unique_key = f"{current_matched_id}_{match['unidentified_id']}" - checkbox_states_per_person[current_matched_id][unique_key] = var.get() + current_value = var.get() + checkbox_states_per_person[current_matched_id][unique_key] = current_value + if self.verbose >= 2: - print(f"DEBUG: Saved state for person {current_matched_id}, face {match['unidentified_id']}: {var.get()}") + print(f"DEBUG: Saved state for person {current_matched_id}, face {match['unidentified_id']}: {current_value}") def update_display(): nonlocal current_matched_index @@ -3137,14 +3158,23 @@ class PhotoTagger: match_vars.append(match_var) + # Capture original state at render time (once per person per face) + if matched_id not in original_checkbox_states_per_person: + original_checkbox_states_per_person[matched_id] = {} + if unique_key not in original_checkbox_states_per_person[matched_id]: + original_checkbox_states_per_person[matched_id][unique_key] = match_var.get() + # Add callback to save state immediately when checkbox changes def on_checkbox_change(var, person_id, face_id): unique_key = f"{person_id}_{face_id}" if person_id not in checkbox_states_per_person: checkbox_states_per_person[person_id] = {} - checkbox_states_per_person[person_id][unique_key] = var.get() + + current_value = var.get() + checkbox_states_per_person[person_id][unique_key] = current_value + if self.verbose >= 2: - print(f"DEBUG: Checkbox changed for person {person_id}, face {face_id}: {var.get()}") + print(f"DEBUG: Checkbox changed for person {person_id}, face {face_id}: {current_value}") # Bind the callback to the variable match_var.trace('w', lambda *args: on_checkbox_change(match_var, matched_id, match['unidentified_id']))