# HG changeset patch # User Sadrul Habib Chowdhury # Date 1165749977 0 # Node ID c6b79e535eb8c6cd1249b6a079fede72de45dbc4 # Parent 9ca8095b62434bf2661c2af6baee61d5f5bb7b9a [gaim-migrate @ 17946] Experimental search-as-you-type in GntTree. Press "/" to enter the search-mode, and when you're done, press escape to cancel. The search-mode remains active for 4 seconds before returning to normal. Someone should update the manual, and possibly enhance the behaviour. committer: Tailor Script diff -r 9ca8095b6243 -r c6b79e535eb8 console/gntblist.c --- a/console/gntblist.c Sun Dec 10 09:38:02 2006 +0000 +++ b/console/gntblist.c Sun Dec 10 11:26:17 2006 +0000 @@ -1362,11 +1362,13 @@ } else if (strcmp(text, GNT_KEY_CTRL_O) == 0) { gaim_prefs_set_bool(PREF_ROOT "/showoffline", !gaim_prefs_get_bool(PREF_ROOT "/showoffline")); - } else if (strcmp(text, "t") == 0) { - gg_blist_toggle_tag_buddy(gnt_tree_get_selection_data(GNT_TREE(ggblist->tree))); - gnt_bindable_perform_action_named(GNT_BINDABLE(ggblist->tree), "move-down"); - } else if (strcmp(text, "a") == 0) { - gg_blist_place_tagged(gnt_tree_get_selection_data(GNT_TREE(ggblist->tree))); + } else if (GNT_TREE(ggblist->tree)->search == NULL) { + if (strcmp(text, "t") == 0) { + gg_blist_toggle_tag_buddy(gnt_tree_get_selection_data(GNT_TREE(ggblist->tree))); + gnt_bindable_perform_action_named(GNT_BINDABLE(ggblist->tree), "move-down"); + } else if (strcmp(text, "a") == 0) { + gg_blist_place_tagged(gnt_tree_get_selection_data(GNT_TREE(ggblist->tree))); + } } else return FALSE; diff -r 9ca8095b6243 -r c6b79e535eb8 console/libgnt/gnttree.c --- a/console/libgnt/gnttree.c Sun Dec 10 09:38:02 2006 +0000 +++ b/console/libgnt/gnttree.c Sun Dec 10 11:26:17 2006 +0000 @@ -6,6 +6,8 @@ #include #include +#define SEARCH_TIMEOUT 4000 /* 4 secs */ + enum { SIG_SELECTION_CHANGED, @@ -35,6 +37,7 @@ GntTreeRow *prev; GList *columns; + GntTree *tree; }; struct _GnTreeCol @@ -70,12 +73,32 @@ return _get_next(row->parent, FALSE); } +static gboolean +row_matches_search(GntTreeRow *row) +{ + GntTree *t = row->tree; + if (t->search && t->search->len > 0) { + char *one = g_utf8_casefold(((GntTreeCol*)row->columns->data)->text, -1); + char *two = g_utf8_casefold(t->search->str, -1); + char *z = strstr(one, two); + g_free(one); + g_free(two); + if (z == NULL) + return FALSE; + } + return TRUE; +} + static GntTreeRow * get_next(GntTreeRow *row) { if (row == NULL) return NULL; - return _get_next(row, !row->collapsed); + while ((row = _get_next(row, !row->collapsed)) != NULL) { + if (row_matches_search(row)) + break; + } + return row; } /* Returns the n-th next row. If it doesn't exist, returns NULL */ @@ -135,9 +158,15 @@ { if (row == NULL) return NULL; - if (row->prev) - return get_last_child(row->prev); - return row->parent; + while (row) { + if (row->prev) + row = get_last_child(row->prev); + else + row = row->parent; + if (!row || row_matches_search(row)) + break; + } + return row; } static GntTreeRow * @@ -332,6 +361,8 @@ else if (up >= widget->priv.height - pos) tree->top = get_prev_n(tree->current, rows); + if (tree->top && !row_matches_search(tree->top)) + tree->top = get_next(tree->top); row = tree->top; scrcol = widget->priv.width - 1 - 2 * pos; /* exclude the borders and the scrollbar */ for (i = start + pos; row && i < widget->priv.height - pos; @@ -343,6 +374,8 @@ GntTextFormatFlags flags = row->flags; int attr = 0; + if (!row_matches_search(row)) + continue; str = update_row_text(tree, row); if ((wr = gnt_util_onscreen_width(str, NULL)) > scrcol) @@ -574,18 +607,46 @@ return TRUE; } +static void +end_search(GntTree *tree) +{ + if (tree->search) { + g_source_remove(tree->search_timeout); + g_string_free(tree->search, TRUE); + tree->search = NULL; + tree->search_timeout = 0; + } +} + +static gboolean +search_timeout(gpointer data) +{ + GntTree *tree = data; + + end_search(tree); + redraw_tree(tree); + + return FALSE; +} + static gboolean gnt_tree_key_pressed(GntWidget *widget, const char *text) { GntTree *tree = GNT_TREE(widget); GntTreeRow *old = tree->current; - if (text[0] == '\r') - { + if (text[0] == '\r') { + end_search(tree); gnt_widget_activate(widget); - } - else if (text[0] == ' ' && text[1] == 0) - { + } else if (tree->search) { + if (isalnum(*text)) { + tree->search = g_string_append_c(tree->search, *text); + redraw_tree(tree); + g_source_remove(tree->search_timeout); + tree->search_timeout = g_timeout_add(SEARCH_TIMEOUT, search_timeout, tree); + } + return TRUE; + } else if (text[0] == ' ' && text[1] == 0) { /* Space pressed */ GntTreeRow *row = tree->current; if (row && row->child) @@ -616,6 +677,7 @@ GntTree *tree = GNT_TREE(widget); int i; + end_search(tree); g_hash_table_destroy(tree->hash); g_list_free(tree->list); @@ -684,6 +746,28 @@ tree->columns[tree->ncol - 1].width += widget->priv.width - n - 2 - 1 * tree->ncol; } +static gboolean +start_search(GntBindable *bindable, GList *list) +{ + GntTree *tree = GNT_TREE(bindable); + if (tree->search) + return FALSE; + tree->search = g_string_new(NULL); + tree->search_timeout = g_timeout_add(SEARCH_TIMEOUT, search_timeout, tree); + return TRUE; +} + +static gboolean +end_search_action(GntBindable *bindable, GList *list) +{ + GntTree *tree = GNT_TREE(bindable); + if (tree->search == NULL) + return FALSE; + end_search(tree); + redraw_tree(tree); + return TRUE; +} + static void gnt_tree_class_init(GntTreeClass *klass) { @@ -732,6 +816,10 @@ GNT_KEY_PGUP, NULL); gnt_bindable_class_register_action(bindable, "page-down", action_page_down, GNT_KEY_PGDOWN, NULL); + gnt_bindable_class_register_action(bindable, "start-search", start_search, + "/", NULL); + gnt_bindable_class_register_action(bindable, "end-search", end_search_action, + "\033", NULL); gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), bindable); GNTDEBUG; @@ -956,6 +1044,7 @@ GntTreeRow *pr = NULL; g_hash_table_replace(tree->hash, key, row); + row->tree = tree; if (bigbro == NULL && tree->compare) { diff -r 9ca8095b6243 -r c6b79e535eb8 console/libgnt/gnttree.h --- a/console/libgnt/gnttree.h Sun Dec 10 09:38:02 2006 +0000 +++ b/console/libgnt/gnttree.h Sun Dec 10 11:26:17 2006 +0000 @@ -52,6 +52,9 @@ gboolean show_title; gboolean show_separator; /* Whether to show column separators */ + GString *search; + int search_timeout; + GCompareFunc compare; };