diff --git a/search_gui.py b/search_gui.py index def7832..aba1ef2 100644 --- a/search_gui.py +++ b/search_gui.py @@ -35,6 +35,10 @@ class SearchGUI: self.search_stats = search_stats self.gui_core = gui_core self.verbose = verbose + + # Sorting state + self.sort_column = None + self.sort_reverse = False def search_gui(self) -> int: """Open the Search GUI window.""" @@ -77,10 +81,10 @@ class SearchGUI: columns = ("person", "open_dir", "open_photo", "path") tree = ttk.Treeview(results_frame, columns=columns, show="headings", selectmode="browse") - tree.heading("person", text="Person") + tree.heading("person", text="Person", command=lambda: sort_treeview("person")) tree.heading("open_dir", text="📁") tree.heading("open_photo", text="📷") - tree.heading("path", text="Photo path") + tree.heading("path", text="Photo path", command=lambda: sort_treeview("path")) tree.column("person", width=220, anchor="w") tree.column("open_dir", width=50, anchor="center") tree.column("open_photo", width=50, anchor="center") @@ -97,6 +101,52 @@ class SearchGUI: close_btn = ttk.Button(btns, text="Close", command=lambda: root.destroy()) close_btn.pack(side=tk.RIGHT) + # Sorting functionality + def sort_treeview(col: str): + """Sort the treeview by the specified column.""" + # Get all items and their values + items = [(tree.set(child, col), child) for child in tree.get_children('')] + + # Determine sort direction + if self.sort_column == col: + # Same column clicked - toggle direction + self.sort_reverse = not self.sort_reverse + else: + # Different column clicked - start with ascending + self.sort_reverse = False + self.sort_column = col + + # Sort the items + # For person and path columns, sort alphabetically + # For icon columns, maintain original order + if col in ['person', 'path']: + items.sort(key=lambda x: x[0].lower(), reverse=self.sort_reverse) + else: + # For icon columns, just reverse if clicking same column + if self.sort_column == col and self.sort_reverse: + items.reverse() + + # Reorder items in treeview + for index, (val, child) in enumerate(items): + tree.move(child, '', index) + + # Update header display + update_header_display() + + def update_header_display(): + """Update header display to show sort indicators.""" + # Reset all headers + tree.heading("person", text="Person") + tree.heading("path", text="Photo path") + + # Add sort indicator to current sort column + if self.sort_column == "person": + indicator = " ↓" if self.sort_reverse else " ↑" + tree.heading("person", text="Person" + indicator) + elif self.sort_column == "path": + indicator = " ↓" if self.sort_reverse else " ↑" + tree.heading("path", text="Photo path" + indicator) + # Behavior def switch_inputs(*_): for w in inputs.winfo_children(): @@ -114,11 +164,29 @@ class SearchGUI: def clear_results(): for i in tree.get_children(): tree.delete(i) + # Reset sorting state for new search + self.sort_column = None + self.sort_reverse = False + update_header_display() def add_results(rows: List[tuple]): # rows expected: List[(full_name, path)] for full_name, p in rows: tree.insert("", tk.END, values=(full_name, "📁", "📷", p)) + + # Sort by person name by default when results are first loaded + if rows and self.sort_column is None: + # Force ascending sort on first load + self.sort_column = "person" + self.sort_reverse = False + # Get all items and sort them directly + items = [(tree.set(child, "person"), child) for child in tree.get_children('')] + items.sort(key=lambda x: x[0].lower(), reverse=False) # Ascending + # Reorder items in treeview + for index, (val, child) in enumerate(items): + tree.move(child, '', index) + # Update header display + update_header_display() def do_search(): clear_results()