refactor: Update AutoMatchPanel to enable search controls dynamically

This commit modifies the `AutoMatchPanel` class to enable search entry and buttons when the auto-match process starts. The search controls are disabled when there is only one matched person, and the help label text is updated accordingly. Additionally, the search controls are disabled when clearing the search, improving user experience by providing clear feedback on search functionality status.
This commit is contained in:
tanyar09 2025-10-21 13:21:54 -04:00
parent f8fefd2983
commit f44cb8b777
2 changed files with 49 additions and 88 deletions

View File

@ -112,18 +112,18 @@ class AutoMatchPanel:
# Search input
self.components['search_var'] = tk.StringVar()
search_entry = ttk.Entry(search_frame, textvariable=self.components['search_var'], width=20)
search_entry.grid(row=0, column=0, sticky=(tk.W, tk.E), padx=(0, 5))
self.components['search_entry'] = ttk.Entry(search_frame, textvariable=self.components['search_var'], width=20, state='disabled')
self.components['search_entry'].grid(row=0, column=0, sticky=(tk.W, tk.E), padx=(0, 5))
# Search buttons
search_btn = ttk.Button(search_frame, text="Search", width=8, command=self._apply_search_filter)
search_btn.grid(row=0, column=1, padx=(0, 5))
self.components['search_btn'] = ttk.Button(search_frame, text="Search", width=8, command=self._apply_search_filter, state='disabled')
self.components['search_btn'].grid(row=0, column=1, padx=(0, 5))
clear_btn = ttk.Button(search_frame, text="Clear", width=6, command=self._clear_search_filter)
clear_btn.grid(row=0, column=2)
self.components['clear_btn'] = ttk.Button(search_frame, text="Clear", width=6, command=self._clear_search_filter, state='disabled')
self.components['clear_btn'].grid(row=0, column=2)
# Search help label
self.components['search_help_label'] = ttk.Label(search_frame, text="Type Last Name",
self.components['search_help_label'] = ttk.Label(search_frame, text="Search disabled - click 'Start Auto-Match' first",
font=("Arial", 8), foreground="gray")
self.components['search_help_label'].grid(row=1, column=0, columnspan=3, sticky=tk.W, pady=(2, 0))
@ -309,20 +309,21 @@ class AutoMatchPanel:
self.original_checkbox_states_per_person = {}
self.identified_count = 0
# Enable search controls now that auto-match has started
self.components['search_entry'].config(state='normal')
self.components['search_btn'].config(state='normal')
self.components['clear_btn'].config(state='normal')
# Check if there's only one person - disable search if so
has_only_one_person = len(self.matched_ids) == 1
if has_only_one_person:
self.components['search_var'].set("")
search_entry = None
for widget in self.components['left_panel'].winfo_children():
if isinstance(widget, ttk.Frame) and len(widget.winfo_children()) > 0:
for child in widget.winfo_children():
if isinstance(child, ttk.Entry):
search_entry = child
break
if search_entry:
search_entry.config(state='disabled')
self.components['search_entry'].config(state='disabled')
self.components['search_btn'].config(state='disabled')
self.components['clear_btn'].config(state='disabled')
self.components['search_help_label'].config(text="(Search disabled - only one person found)")
else:
self.components['search_help_label'].config(text="Type Last Name")
# Enable controls
self._update_control_states()
@ -873,20 +874,12 @@ class AutoMatchPanel:
self.components['select_all_btn'].config(state='disabled')
self.components['clear_all_btn'].config(state='disabled')
# Clear search
# Clear search and disable search controls
self.components['search_var'].set("")
self.components['search_help_label'].config(text="Type Last Name")
# Re-enable search entry
search_entry = None
for widget in self.components['left_panel'].winfo_children():
if isinstance(widget, ttk.Frame) and len(widget.winfo_children()) > 0:
for child in widget.winfo_children():
if isinstance(child, ttk.Entry):
search_entry = child
break
if search_entry:
search_entry.config(state='normal')
self.components['search_entry'].config(state='disabled')
self.components['search_btn'].config(state='disabled')
self.components['clear_btn'].config(state='disabled')
self.components['search_help_label'].config(text="Search disabled - click 'Start Auto-Match' first")
self.is_active = False

View File

@ -755,39 +755,22 @@ class SearchPanel:
if not vals or len(vals) < 6:
return
# Determine column offsets based on search type
is_name_search = (self.search_type_var.get() == self.SEARCH_TYPES[0])
is_photos_without_faces = (self.search_type_var.get() == self.SEARCH_TYPES[6])
# Get the actual column name from the displaycolumns
display_columns = self.tree["displaycolumns"]
col_index = int(col_id[1:]) - 1 # Convert '#1' to 0, '#2' to 1, etc.
if is_name_search:
# Name search: all columns visible including person (processed column hidden)
select_col = "#1" # select is column 1
open_dir_col = "#4" # open_dir is column 4
face_col = "#5" # open_photo is column 5
path_col = "#6" # path is column 6
path_index = 6 # path is at index 6 in values array (still same since processed is hidden from display)
elif is_photos_without_faces:
# Photos without faces: person and people icon columns are hidden
select_col = "#1" # select is column 1
open_dir_col = "#4" # open_dir is column 4
face_col = "#5" # open_photo is column 5 (but hidden)
path_col = "#5" # path is column 5 (since people icon is hidden)
path_index = 6 # path is at index 6 in values array
else:
# All other searches: person column is hidden, people icon visible
select_col = "#1" # select is column 1
open_dir_col = "#4" # open_dir is column 4
face_col = "#5" # open_photo is column 5
path_col = "#6" # path is column 6
path_index = 6 # path is at index 6 in values array
if col_index < 0 or col_index >= len(display_columns):
return
column_name = display_columns[col_index]
path = vals[6] # Photo path is always at index 6 in values array
path = vals[path_index] # Photo path
if col_id == open_dir_col: # Open directory column
if column_name == "open_dir": # Open directory column
self.open_dir(path)
elif col_id == face_col: # Face icon column
elif column_name == "open_photo": # Face icon column
# No popup needed, just tooltip
pass
elif col_id == path_col: # Photo path column - clickable to open photo
elif column_name == "path": # Photo path column - clickable to open photo
try:
import os
import sys
@ -801,7 +784,7 @@ class SearchPanel:
subprocess.run(["xdg-open", path], check=False)
except Exception:
messagebox.showerror("Open Photo", "Failed to open the selected photo.", parent=self.parent_frame)
elif col_id == select_col: # Checkbox column
elif column_name == "select": # Checkbox column
self.toggle_photo_selection(row_id, vals)
def on_tree_motion(self, event):
@ -814,33 +797,18 @@ class SearchPanel:
col_id = self.tree.identify_column(event.x)
row_id = self.tree.identify_row(event.y)
# Determine column offsets based on search type
is_name_search = (self.search_type_var.get() == self.SEARCH_TYPES[0])
is_photos_without_faces = (self.search_type_var.get() == self.SEARCH_TYPES[6])
# Get the actual column name from the displaycolumns
display_columns = self.tree["displaycolumns"]
col_index = int(col_id[1:]) - 1 # Convert '#1' to 0, '#2' to 1, etc.
if is_name_search:
# Name search: all columns visible including person (processed column hidden)
tags_col = "#3" # tags is column 3
open_dir_col = "#4" # open_dir is column 4
face_col = "#5" # open_photo is column 5
path_col = "#6" # path is column 6
path_index = 6 # path is at index 6 in values array (still same since processed is hidden from display)
elif is_photos_without_faces:
# Photos without faces: person and people icon columns are hidden
tags_col = "#2" # tags is column 2
open_dir_col = "#4" # open_dir is column 4
face_col = "#5" # open_photo is column 5 (but hidden)
path_col = "#5" # path is column 5 (since people icon is hidden)
path_index = 6 # path is at index 6 in values array
else:
# All other searches: person column is hidden, people icon visible
tags_col = "#2" # tags is column 2
open_dir_col = "#4" # open_dir is column 4
face_col = "#5" # open_photo is column 5
path_col = "#6" # path is column 6
path_index = 6 # path is at index 6 in values array
if col_index < 0 or col_index >= len(display_columns):
self.tree.config(cursor="")
self.hide_tooltip()
return
column_name = display_columns[col_index]
if col_id == tags_col: # Tags column
if column_name == "tags": # Tags column
self.tree.config(cursor="")
# Show tags tooltip
if row_id:
@ -849,19 +817,19 @@ class SearchPanel:
# Tags are at index 2 for all search types (after select, person is hidden in most)
tags_text = vals[2]
self.show_tooltip(self.tree, event.x_root, event.y_root, f"Tags: {tags_text}")
elif col_id == open_dir_col: # Open directory column
elif column_name == "open_dir": # Open directory column
self.tree.config(cursor="hand2")
self.show_tooltip(self.tree, event.x_root, event.y_root, "Open file location")
elif col_id == face_col: # Face icon column
elif column_name == "open_photo": # Face icon column
self.tree.config(cursor="hand2")
# Show people tooltip
if row_id:
vals = self.tree.item(row_id, "values")
if len(vals) >= 5:
path = vals[path_index]
if len(vals) >= 6:
path = vals[6] # Photo path is always at index 6
people_text = self.get_photo_people_tooltip(path)
self.show_tooltip(self.tree, event.x_root, event.y_root, people_text)
elif col_id == path_col: # Photo path column
elif column_name == "path": # Photo path column
self.tree.config(cursor="hand2")
self.show_tooltip(self.tree, event.x_root, event.y_root, "Open photo")
else: