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.

This commit is contained in:
tanyar09 2025-09-29 12:24:34 -04:00
parent 8c9da7362b
commit 267519a034

View File

@ -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']))