*/
/** @file disobedience/search.c
* @brief Search support
- *
- * TODO:
- * - cleverer focus to implement typeahead find
- * - don't steal ^A
*/
#include "disobedience.h"
#include "choose.h"
-static GtkWidget *choose_search_entry;
+int choose_auto_expanding;
+
+GtkWidget *choose_search_entry;
static GtkWidget *choose_next;
static GtkWidget *choose_prev;
static GtkWidget *choose_clear;
}
if(is_prefix(dir, track)) {
/* We found a prefix of the target track. */
- //fprintf(stderr, " is a prefix\n");
+ //fprintf(stderr, " %s is a prefix\n", dir);
const gboolean expanded
= gtk_tree_view_row_expanded(GTK_TREE_VIEW(choose_view), path);
if(expanded) {
} else {
//fprintf(stderr, " requesting expansion of %s\n", dir);
/* Track is below a non-expanded directory. So let's expand it.
- * choose_make_visible() will arrange a revisit in due course. */
+ * choose_make_visible() will arrange a revisit in due course.
+ *
+ * We mark the row as auto-expanded.
+ */
+ ++choose_auto_expanding;
gtk_tree_view_expand_row(GTK_TREE_VIEW(choose_view),
path,
FALSE/*open_all*/);
gtk_tree_path_free(path);
- /* TODO: the old version would remember which rows had been expanded
- * just to show search results and collapse them again. We should
- * probably do that. */
+ --choose_auto_expanding;
return 0;
}
} else
/* If there's work left to be done make sure we get a callback when
* something changes */
if(!choose_inserted_handle)
- choose_inserted_handle = event_register("choose-inserted-tracks",
+ choose_inserted_handle = event_register("choose-more-tracks",
choose_make_visible, 0);
} else {
/* Suppress callbacks if there's nothing more to do */
return;
}
//fprintf(stderr, "*** %d search results\n", nvec);
+ /* We're actually going to use these search results. Autocollapse anything
+ * left over from the old search. */
+ choose_auto_collapse();
choose_search_hash = hash_new(1);
if(nvec) {
for(int n = 0; n < nvec; ++n)
} else {
gtk_widget_set_sensitive(choose_next, FALSE);
gtk_widget_set_sensitive(choose_prev, FALSE);
+ choose_n_search_results = 0;
+ choose_search_results = 0;
+ choose_n_search_references = 0;
+ choose_search_references = 0;
}
event_raise("search-results-changed", 0);
}
return TRUE;
}
-static void choose_next_clicked(GtkButton attribute((unused)) *button,
- gpointer attribute((unused)) userdata) {
+void choose_next_clicked(GtkButton attribute((unused)) *button,
+ gpointer attribute((unused)) userdata) {
+ gtk_widget_grab_focus(choose_view);
+ if(!choose_n_search_results)
+ return;
/* Find the last visible row */
GtkTreePath *endpath;
gboolean endvalid = choose_get_visible_range(GTK_TREE_VIEW(choose_view),
}
gtk_tree_path_free(path);
}
+ /* We didn't find one. Loop back to the first. */
+ for(int n = 0; n < choose_n_search_references; ++n) {
+ GtkTreePath *path
+ = gtk_tree_row_reference_get_path(choose_search_references[n]);
+ if(!path)
+ continue;
+ choose_make_path_visible(path, 0.5);
+ gtk_tree_path_free(path);
+ return;
+ }
}
-static void choose_prev_clicked(GtkButton attribute((unused)) *button,
- gpointer attribute((unused)) userdata) {
+void choose_prev_clicked(GtkButton attribute((unused)) *button,
+ gpointer attribute((unused)) userdata) {
+ gtk_widget_grab_focus(choose_view);
/* TODO can we de-dupe with choose_next_clicked? Probably yes. */
+ if(!choose_n_search_results)
+ return;
/* Find the first visible row */
GtkTreePath *startpath;
gboolean startvalid = choose_get_visible_range(GTK_TREE_VIEW(choose_view),
}
gtk_tree_path_free(path);
}
+ /* We didn't find one. Loop down to the last. */
+ for(int n = choose_n_search_references - 1; n >= 0; --n) {
+ GtkTreePath *path
+ = gtk_tree_row_reference_get_path(choose_search_references[n]);
+ if(!path)
+ continue;
+ choose_make_path_visible(path, 0.5);
+ gtk_tree_path_free(path);
+ return;
+ }
}
/** @brief Called when the cancel search button is clicked */
static void choose_clear_clicked(GtkButton attribute((unused)) *button,
gpointer attribute((unused)) userdata) {
gtk_entry_set_text(GTK_ENTRY(choose_search_entry), "");
+ gtk_widget_grab_focus(choose_view);
/* We start things off straight away in this case */
initiate_search();
}
+/** @brief Called when the user hits ^F to start a new search */
+void choose_search_new(void) {
+ gtk_editable_select_region(GTK_EDITABLE(choose_search_entry), 0, -1);
+}
+
/** @brief Create the search widget */
GtkWidget *choose_search_widget(void) {