From f44cb8b777b42b35c648bcd4a8042783e77c5726 Mon Sep 17 00:00:00 2001 From: tanyar09 Date: Tue, 21 Oct 2025 13:21:54 -0400 Subject: [PATCH] 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. --- src/gui/auto_match_panel.py | 51 ++++++++++------------ src/gui/dashboard_gui.py | 86 ++++++++++++------------------------- 2 files changed, 49 insertions(+), 88 deletions(-) diff --git a/src/gui/auto_match_panel.py b/src/gui/auto_match_panel.py index e802060..3b3080c 100644 --- a/src/gui/auto_match_panel.py +++ b/src/gui/auto_match_panel.py @@ -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 diff --git a/src/gui/dashboard_gui.py b/src/gui/dashboard_gui.py index 8631691..7a5e503 100644 --- a/src/gui/dashboard_gui.py +++ b/src/gui/dashboard_gui.py @@ -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: