Mercurial > pidgin.yaz
diff finch/libgnt/gntfilesel.c @ 15925:f8c16848b76d
Allow selecting multiple files from the file-select dialog.
You need to tag the files by pressing 't' to select the files. It is possible
to tag files from different locations, ie. when you change the directory, the
tags are remembered. You can untag a selection by pressing 't' again. To untag
all selections, press 'c'.
author | Sadrul Habib Chowdhury <imadil@gmail.com> |
---|---|
date | Mon, 26 Mar 2007 01:19:59 +0000 |
parents | b4086a92568f |
children | 5f9b7e2652f0 5b065c7ff5cd |
line wrap: on
line diff
--- a/finch/libgnt/gntfilesel.c Mon Mar 26 00:44:09 2007 +0000 +++ b/finch/libgnt/gntfilesel.c Mon Mar 26 01:19:59 2007 +0000 @@ -28,6 +28,10 @@ { GntFileSel *sel = GNT_FILE_SEL(widget); g_free(sel->current); + if (sel->tags) { + g_list_foreach(sel->tags, (GFunc)g_free, NULL); + g_list_free(sel->tags); + } } static char * @@ -73,6 +77,15 @@ } static gboolean +is_tagged(GntFileSel *sel, const char *f) +{ + char *ret = g_strdup_printf("%s%s%s", sel->current, sel->current[1] ? G_DIR_SEPARATOR_S : "", f); + gboolean find = g_list_find_custom(sel->tags, ret, (GCompareFunc)g_utf8_collate) != NULL; + g_free(ret); + return find; +} + +static gboolean location_changed(GntFileSel *sel, GError **err) { GDir *dir; @@ -109,15 +122,19 @@ if (stat(fp, &st)) { g_printerr("Error stating location %s\n", fp); } else { - if (S_ISDIR(st.st_mode)) + if (S_ISDIR(st.st_mode)) { gnt_tree_add_row_after(GNT_TREE(sel->dirs), g_strdup(str), gnt_tree_create_row(GNT_TREE(sel->dirs), str), NULL, NULL); - else if (!sel->dirsonly) { + if (sel->multiselect && sel->dirsonly && is_tagged(sel, str)) + gnt_tree_set_row_flags(GNT_TREE(sel->dirs), (gpointer)str, GNT_TEXT_FLAG_BOLD); + } else if (!sel->dirsonly) { char size[128]; snprintf(size, sizeof(size), "%ld", (long)st.st_size); gnt_tree_add_row_after(GNT_TREE(sel->files), g_strdup(str), gnt_tree_create_row(GNT_TREE(sel->files), str, size, ""), NULL, NULL); + if (sel->multiselect && is_tagged(sel, str)) + gnt_tree_set_row_flags(GNT_TREE(sel->files), (gpointer)str, GNT_TEXT_FLAG_BOLD); } } g_free(fp); @@ -131,7 +148,6 @@ dir_key_pressed(GntTree *tree, const char *key, GntFileSel *sel) { if (strcmp(key, "\r") == 0) { - /* XXX: if we are moving up the tree, make sure the current node is selected after the redraw */ char *str = g_strdup(gnt_tree_get_selection_data(tree)); char *path = g_build_filename(sel->current, str, NULL); char *dir = g_path_get_basename(sel->current); @@ -225,7 +241,7 @@ vbox = gnt_vbox_new(FALSE); gnt_box_set_pad(GNT_BOX(vbox), 0); - gnt_box_set_alignment(GNT_BOX(vbox), GNT_ALIGN_LEFT); + gnt_box_set_alignment(GNT_BOX(vbox), GNT_ALIGN_MID); /* The dir. and files list */ hbox = gnt_hbox_new(FALSE); @@ -253,9 +269,64 @@ update_location(sel); } +static gboolean +toggle_tag_selection(GntBindable *bind, GList *null) +{ + GntFileSel *sel = GNT_FILE_SEL(bind); + char *str; + GList *find; + char *file; + GntWidget *tree; + + if (!sel->multiselect) + return FALSE; + tree = sel->dirsonly ? sel->dirs : sel->files; + if (!gnt_widget_has_focus(tree)) + return FALSE; + + file = gnt_tree_get_selection_data(sel->dirsonly ? GNT_TREE(sel->dirs) : GNT_TREE(sel->files)); + + str = gnt_file_sel_get_selected_file(sel); + if ((find = g_list_find_custom(sel->tags, str, (GCompareFunc)g_utf8_collate)) != NULL) { + g_free(find->data); + sel->tags = g_list_delete_link(sel->tags, find); + gnt_tree_set_row_flags(GNT_TREE(tree), file, GNT_TEXT_FLAG_NORMAL); + g_free(str); + } else { + sel->tags = g_list_prepend(sel->tags, str); + gnt_tree_set_row_flags(GNT_TREE(tree), file, GNT_TEXT_FLAG_BOLD); + } + + return TRUE; +} + +static gboolean +clear_tags(GntBindable *bind, GList *null) +{ + GntFileSel *sel = GNT_FILE_SEL(bind); + GntWidget *tree; + GList *iter; + + if (!sel->multiselect) + return FALSE; + tree = sel->dirsonly ? sel->dirs : sel->files; + if (!gnt_widget_has_focus(tree)) + return FALSE; + + g_list_foreach(sel->tags, (GFunc)g_free, NULL); + g_list_free(sel->tags); + sel->tags = NULL; + + for (iter = GNT_TREE(tree)->list; iter; iter = iter->next) + gnt_tree_set_row_flags(GNT_TREE(tree), iter->data, GNT_TEXT_FLAG_NORMAL); + + return TRUE; +} + static void gnt_file_sel_class_init(GntFileSelClass *klass) { + GntBindableClass *bindable = GNT_BINDABLE_CLASS(klass); GntWidgetClass *kl = GNT_WIDGET_CLASS(klass); parent_class = GNT_WINDOW_CLASS(klass); kl->destroy = gnt_file_sel_destroy; @@ -270,6 +341,9 @@ NULL, NULL, gnt_closure_marshal_VOID__STRING_STRING, G_TYPE_NONE, 0); + + gnt_bindable_class_register_action(bindable, "toggle-tag", toggle_tag_selection, "t", NULL); + gnt_bindable_class_register_action(bindable, "clear-tags", clear_tags, "c", NULL); gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass)); GNTDEBUG; @@ -395,3 +469,26 @@ return sel->must_exist; } +void gnt_file_sel_set_multi_select(GntFileSel *sel, gboolean set) +{ + sel->multiselect = set; +} + +GList *gnt_file_sel_get_selected_multi_files(GntFileSel *sel) +{ + GList *list = NULL, *iter; + char *str = gnt_file_sel_get_selected_file(sel); + + for (iter = sel->tags; iter; iter = iter->next) { + list = g_list_prepend(list, g_strdup(iter->data)); + if (g_utf8_collate(str, iter->data)) { + g_free(str); + str = NULL; + } + } + if (str) + list = g_list_prepend(list, str); + list = g_list_reverse(list); + return list; +} +