comparison finch/libgnt/gntfilesel.c @ 15923: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
comparison
equal deleted inserted replaced
15922:b4086a92568f 15923:f8c16848b76d
26 static void 26 static void
27 gnt_file_sel_destroy(GntWidget *widget) 27 gnt_file_sel_destroy(GntWidget *widget)
28 { 28 {
29 GntFileSel *sel = GNT_FILE_SEL(widget); 29 GntFileSel *sel = GNT_FILE_SEL(widget);
30 g_free(sel->current); 30 g_free(sel->current);
31 if (sel->tags) {
32 g_list_foreach(sel->tags, (GFunc)g_free, NULL);
33 g_list_free(sel->tags);
34 }
31 } 35 }
32 36
33 static char * 37 static char *
34 process_path(const char *path) 38 process_path(const char *path)
35 { 39 {
71 gnt_entry_set_text(GNT_ENTRY(sel->location), old); 75 gnt_entry_set_text(GNT_ENTRY(sel->location), old);
72 g_free(old); 76 g_free(old);
73 } 77 }
74 78
75 static gboolean 79 static gboolean
80 is_tagged(GntFileSel *sel, const char *f)
81 {
82 char *ret = g_strdup_printf("%s%s%s", sel->current, sel->current[1] ? G_DIR_SEPARATOR_S : "", f);
83 gboolean find = g_list_find_custom(sel->tags, ret, (GCompareFunc)g_utf8_collate) != NULL;
84 g_free(ret);
85 return find;
86 }
87
88 static gboolean
76 location_changed(GntFileSel *sel, GError **err) 89 location_changed(GntFileSel *sel, GError **err)
77 { 90 {
78 GDir *dir; 91 GDir *dir;
79 const char *str; 92 const char *str;
80 93
107 struct stat st; 120 struct stat st;
108 121
109 if (stat(fp, &st)) { 122 if (stat(fp, &st)) {
110 g_printerr("Error stating location %s\n", fp); 123 g_printerr("Error stating location %s\n", fp);
111 } else { 124 } else {
112 if (S_ISDIR(st.st_mode)) 125 if (S_ISDIR(st.st_mode)) {
113 gnt_tree_add_row_after(GNT_TREE(sel->dirs), g_strdup(str), 126 gnt_tree_add_row_after(GNT_TREE(sel->dirs), g_strdup(str),
114 gnt_tree_create_row(GNT_TREE(sel->dirs), str), NULL, NULL); 127 gnt_tree_create_row(GNT_TREE(sel->dirs), str), NULL, NULL);
115 else if (!sel->dirsonly) { 128 if (sel->multiselect && sel->dirsonly && is_tagged(sel, str))
129 gnt_tree_set_row_flags(GNT_TREE(sel->dirs), (gpointer)str, GNT_TEXT_FLAG_BOLD);
130 } else if (!sel->dirsonly) {
116 char size[128]; 131 char size[128];
117 snprintf(size, sizeof(size), "%ld", (long)st.st_size); 132 snprintf(size, sizeof(size), "%ld", (long)st.st_size);
118 133
119 gnt_tree_add_row_after(GNT_TREE(sel->files), g_strdup(str), 134 gnt_tree_add_row_after(GNT_TREE(sel->files), g_strdup(str),
120 gnt_tree_create_row(GNT_TREE(sel->files), str, size, ""), NULL, NULL); 135 gnt_tree_create_row(GNT_TREE(sel->files), str, size, ""), NULL, NULL);
136 if (sel->multiselect && is_tagged(sel, str))
137 gnt_tree_set_row_flags(GNT_TREE(sel->files), (gpointer)str, GNT_TEXT_FLAG_BOLD);
121 } 138 }
122 } 139 }
123 g_free(fp); 140 g_free(fp);
124 } 141 }
125 if (GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(sel), GNT_WIDGET_MAPPED)) 142 if (GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(sel), GNT_WIDGET_MAPPED))
129 146
130 static gboolean 147 static gboolean
131 dir_key_pressed(GntTree *tree, const char *key, GntFileSel *sel) 148 dir_key_pressed(GntTree *tree, const char *key, GntFileSel *sel)
132 { 149 {
133 if (strcmp(key, "\r") == 0) { 150 if (strcmp(key, "\r") == 0) {
134 /* XXX: if we are moving up the tree, make sure the current node is selected after the redraw */
135 char *str = g_strdup(gnt_tree_get_selection_data(tree)); 151 char *str = g_strdup(gnt_tree_get_selection_data(tree));
136 char *path = g_build_filename(sel->current, str, NULL); 152 char *path = g_build_filename(sel->current, str, NULL);
137 char *dir = g_path_get_basename(sel->current); 153 char *dir = g_path_get_basename(sel->current);
138 if (!gnt_file_sel_set_current_location(sel, path)) { 154 if (!gnt_file_sel_set_current_location(sel, path)) {
139 gnt_tree_set_selected(tree, str); 155 gnt_tree_set_selected(tree, str);
223 GntFileSel *sel = GNT_FILE_SEL(widget); 239 GntFileSel *sel = GNT_FILE_SEL(widget);
224 GntWidget *hbox, *vbox; 240 GntWidget *hbox, *vbox;
225 241
226 vbox = gnt_vbox_new(FALSE); 242 vbox = gnt_vbox_new(FALSE);
227 gnt_box_set_pad(GNT_BOX(vbox), 0); 243 gnt_box_set_pad(GNT_BOX(vbox), 0);
228 gnt_box_set_alignment(GNT_BOX(vbox), GNT_ALIGN_LEFT); 244 gnt_box_set_alignment(GNT_BOX(vbox), GNT_ALIGN_MID);
229 245
230 /* The dir. and files list */ 246 /* The dir. and files list */
231 hbox = gnt_hbox_new(FALSE); 247 hbox = gnt_hbox_new(FALSE);
232 gnt_box_set_pad(GNT_BOX(hbox), 0); 248 gnt_box_set_pad(GNT_BOX(hbox), 0);
233 249
251 gnt_box_add_widget(GNT_BOX(sel), vbox); 267 gnt_box_add_widget(GNT_BOX(sel), vbox);
252 orig_map(widget); 268 orig_map(widget);
253 update_location(sel); 269 update_location(sel);
254 } 270 }
255 271
272 static gboolean
273 toggle_tag_selection(GntBindable *bind, GList *null)
274 {
275 GntFileSel *sel = GNT_FILE_SEL(bind);
276 char *str;
277 GList *find;
278 char *file;
279 GntWidget *tree;
280
281 if (!sel->multiselect)
282 return FALSE;
283 tree = sel->dirsonly ? sel->dirs : sel->files;
284 if (!gnt_widget_has_focus(tree))
285 return FALSE;
286
287 file = gnt_tree_get_selection_data(sel->dirsonly ? GNT_TREE(sel->dirs) : GNT_TREE(sel->files));
288
289 str = gnt_file_sel_get_selected_file(sel);
290 if ((find = g_list_find_custom(sel->tags, str, (GCompareFunc)g_utf8_collate)) != NULL) {
291 g_free(find->data);
292 sel->tags = g_list_delete_link(sel->tags, find);
293 gnt_tree_set_row_flags(GNT_TREE(tree), file, GNT_TEXT_FLAG_NORMAL);
294 g_free(str);
295 } else {
296 sel->tags = g_list_prepend(sel->tags, str);
297 gnt_tree_set_row_flags(GNT_TREE(tree), file, GNT_TEXT_FLAG_BOLD);
298 }
299
300 return TRUE;
301 }
302
303 static gboolean
304 clear_tags(GntBindable *bind, GList *null)
305 {
306 GntFileSel *sel = GNT_FILE_SEL(bind);
307 GntWidget *tree;
308 GList *iter;
309
310 if (!sel->multiselect)
311 return FALSE;
312 tree = sel->dirsonly ? sel->dirs : sel->files;
313 if (!gnt_widget_has_focus(tree))
314 return FALSE;
315
316 g_list_foreach(sel->tags, (GFunc)g_free, NULL);
317 g_list_free(sel->tags);
318 sel->tags = NULL;
319
320 for (iter = GNT_TREE(tree)->list; iter; iter = iter->next)
321 gnt_tree_set_row_flags(GNT_TREE(tree), iter->data, GNT_TEXT_FLAG_NORMAL);
322
323 return TRUE;
324 }
325
256 static void 326 static void
257 gnt_file_sel_class_init(GntFileSelClass *klass) 327 gnt_file_sel_class_init(GntFileSelClass *klass)
258 { 328 {
329 GntBindableClass *bindable = GNT_BINDABLE_CLASS(klass);
259 GntWidgetClass *kl = GNT_WIDGET_CLASS(klass); 330 GntWidgetClass *kl = GNT_WIDGET_CLASS(klass);
260 parent_class = GNT_WINDOW_CLASS(klass); 331 parent_class = GNT_WINDOW_CLASS(klass);
261 kl->destroy = gnt_file_sel_destroy; 332 kl->destroy = gnt_file_sel_destroy;
262 orig_map = kl->map; 333 orig_map = kl->map;
263 kl->map = gnt_file_sel_map; 334 kl->map = gnt_file_sel_map;
268 G_SIGNAL_RUN_LAST, 339 G_SIGNAL_RUN_LAST,
269 G_STRUCT_OFFSET(GntFileSelClass, file_selected), 340 G_STRUCT_OFFSET(GntFileSelClass, file_selected),
270 NULL, NULL, 341 NULL, NULL,
271 gnt_closure_marshal_VOID__STRING_STRING, 342 gnt_closure_marshal_VOID__STRING_STRING,
272 G_TYPE_NONE, 0); 343 G_TYPE_NONE, 0);
344
345 gnt_bindable_class_register_action(bindable, "toggle-tag", toggle_tag_selection, "t", NULL);
346 gnt_bindable_class_register_action(bindable, "clear-tags", clear_tags, "c", NULL);
273 gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass)); 347 gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), GNT_BINDABLE_CLASS(klass));
274 348
275 GNTDEBUG; 349 GNTDEBUG;
276 } 350 }
277 351
393 gboolean gnt_file_sel_get_must_exist(GntFileSel *sel) 467 gboolean gnt_file_sel_get_must_exist(GntFileSel *sel)
394 { 468 {
395 return sel->must_exist; 469 return sel->must_exist;
396 } 470 }
397 471
472 void gnt_file_sel_set_multi_select(GntFileSel *sel, gboolean set)
473 {
474 sel->multiselect = set;
475 }
476
477 GList *gnt_file_sel_get_selected_multi_files(GntFileSel *sel)
478 {
479 GList *list = NULL, *iter;
480 char *str = gnt_file_sel_get_selected_file(sel);
481
482 for (iter = sel->tags; iter; iter = iter->next) {
483 list = g_list_prepend(list, g_strdup(iter->data));
484 if (g_utf8_collate(str, iter->data)) {
485 g_free(str);
486 str = NULL;
487 }
488 }
489 if (str)
490 list = g_list_prepend(list, str);
491 list = g_list_reverse(list);
492 return list;
493 }
494