r3353: Changed hidden files code, now supports filtering by name.
[rox-filer.git] / ROX-Filer / src / toolbar.c
blobb738f42a15784b5928309e379f4bfb34960f99df
1 /*
2 * $Id$
4 * ROX-Filer, filer for the ROX desktop project
5 * Copyright (C) 2003, the ROX-Filer team.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 * Place, Suite 330, Boston, MA 02111-1307 USA
22 /* toolbar.c - for the button bars that go along the tops of windows */
24 #include "config.h"
26 #include <string.h>
28 #include "global.h"
30 #include "toolbar.h"
31 #include "options.h"
32 #include "support.h"
33 #include "main.h"
34 #include "menu.h"
35 #include "dnd.h"
36 #include "filer.h"
37 #include "display.h"
38 #include "pixmaps.h"
39 #include "bind.h"
40 #include "type.h"
41 #include "dir.h"
42 #include "diritem.h"
43 #include "view_iface.h"
44 #include "bookmarks.h"
45 #include "gui_support.h"
47 typedef struct _Tool Tool;
49 typedef enum {DROP_NONE, DROP_TO_PARENT, DROP_TO_HOME, DROP_BOOKMARK} DropDest;
51 struct _Tool {
52 const gchar *label;
53 const gchar *name;
54 const gchar *tip; /* Tooltip */
55 void (*clicked)(GtkWidget *w, FilerWindow *filer_window);
56 DropDest drop_action;
57 gboolean enabled;
58 gboolean menu; /* Activate on button-press */
61 Option o_toolbar, o_toolbar_info, o_toolbar_disable;
63 static GtkTooltips *tooltips = NULL;
64 static FilerWindow *filer_window_being_counted;
66 /* TRUE if the button presses (or released) should open a new window,
67 * rather than reusing the existing one.
69 #define NEW_WIN_BUTTON(button_event) \
70 (o_new_button_1.int_value \
71 ? ((GdkEventButton *) button_event)->button == 1 \
72 : ((GdkEventButton *) button_event)->button != 1)
74 /* Static prototypes */
75 static void toolbar_close_clicked(GtkWidget *widget, FilerWindow *filer_window);
76 static void toolbar_up_clicked(GtkWidget *widget, FilerWindow *filer_window);
77 static void toolbar_home_clicked(GtkWidget *widget, FilerWindow *filer_window);
78 static void toolbar_bookmarks_clicked(GtkWidget *widget,
79 FilerWindow *filer_window);
80 static void toolbar_help_clicked(GtkWidget *widget, FilerWindow *filer_window);
81 static void toolbar_refresh_clicked(GtkWidget *widget,
82 FilerWindow *filer_window);
83 static void toolbar_size_clicked(GtkWidget *widget, FilerWindow *filer_window);
84 static void toolbar_autosize_clicked(GtkWidget *widget, FilerWindow *filer_window);
85 static void toolbar_details_clicked(GtkWidget *widget,
86 FilerWindow *filer_window);
87 static void toolbar_hidden_clicked(GtkWidget *widget,
88 FilerWindow *filer_window);
89 static void toolbar_select_clicked(GtkWidget *widget,
90 FilerWindow *filer_window);
91 static void toolbar_sort_clicked(GtkWidget *widget,
92 FilerWindow *filer_window);
93 static GtkWidget *add_button(GtkWidget *bar, Tool *tool,
94 FilerWindow *filer_window);
95 static GtkWidget *create_toolbar(FilerWindow *filer_window);
96 static gboolean drag_motion(GtkWidget *widget,
97 GdkDragContext *context,
98 gint x,
99 gint y,
100 guint time,
101 FilerWindow *filer_window);
102 static void drag_leave(GtkWidget *widget,
103 GdkDragContext *context,
104 guint32 time,
105 FilerWindow *filer_window);
106 static void handle_drops(FilerWindow *filer_window,
107 GtkWidget *button,
108 DropDest dest);
109 static void toggle_selected(GtkToggleButton *widget, gpointer data);
110 static void option_notify(void);
111 static GList *build_tool_options(Option *option, xmlNode *node, guchar *label);
112 static void tally_items(gpointer key, gpointer value, gpointer data);
114 static Tool all_tools[] = {
115 {N_("Close"), GTK_STOCK_CLOSE, N_("Close filer window"),
116 toolbar_close_clicked, DROP_NONE, FALSE,
117 FALSE},
119 {N_("Up"), GTK_STOCK_GO_UP, N_("Change to parent directory"),
120 toolbar_up_clicked, DROP_TO_PARENT, TRUE,
121 FALSE},
123 {N_("Home"), GTK_STOCK_HOME, N_("Change to home directory"),
124 toolbar_home_clicked, DROP_TO_HOME, TRUE,
125 FALSE},
127 {N_("Bookmarks"), ROX_STOCK_BOOKMARKS, N_("Bookmarks menu"),
128 toolbar_bookmarks_clicked, DROP_BOOKMARK, FALSE,
129 TRUE},
131 {N_("Scan"), GTK_STOCK_REFRESH, N_("Rescan directory contents"),
132 toolbar_refresh_clicked, DROP_NONE, TRUE,
133 FALSE},
135 {N_("Size"), GTK_STOCK_ZOOM_IN, N_("Change icon size"),
136 toolbar_size_clicked, DROP_NONE, TRUE,
137 FALSE},
139 {N_("Size"), GTK_STOCK_ZOOM_FIT, N_("Automatic size mode"),
140 toolbar_autosize_clicked, DROP_NONE, TRUE,
141 FALSE},
143 {N_("Details"), ROX_STOCK_SHOW_DETAILS, N_("Show extra details"),
144 toolbar_details_clicked, DROP_NONE, TRUE,
145 FALSE},
147 {N_("Sort"), GTK_STOCK_SORT_ASCENDING, N_("Change sort criteria"),
148 toolbar_sort_clicked, DROP_NONE, FALSE,
149 FALSE},
151 {N_("Hidden"), ROX_STOCK_SHOW_HIDDEN, N_("Show/hide hidden files"),
152 toolbar_hidden_clicked, DROP_NONE, TRUE,
153 FALSE},
155 {N_("Select"), ROX_STOCK_SELECT, N_("Select all/invert selection"),
156 toolbar_select_clicked, DROP_NONE, FALSE,
157 FALSE},
159 {N_("Help"), GTK_STOCK_HELP, N_("Show ROX-Filer help"),
160 toolbar_help_clicked, DROP_NONE, TRUE,
161 FALSE},
165 /****************************************************************
166 * EXTERNAL INTERFACE *
167 ****************************************************************/
169 void toolbar_init(void)
171 option_add_int(&o_toolbar, "toolbar_type", TOOLBAR_NORMAL);
172 option_add_int(&o_toolbar_info, "toolbar_show_info", 1);
173 option_add_string(&o_toolbar_disable, "toolbar_disable",
174 GTK_STOCK_CLOSE);
175 option_add_notify(option_notify);
177 tooltips = gtk_tooltips_new();
179 option_register_widget("tool-options", build_tool_options);
182 void toolbar_update_info(FilerWindow *filer_window)
184 gchar *label;
185 ViewIface *view;
186 int n_selected;
188 if (o_toolbar.int_value == TOOLBAR_NONE || !o_toolbar_info.int_value)
189 return; /* Not showing info */
191 if (filer_window->target_cb)
192 return;
194 view = filer_window->view;
196 n_selected = view_count_selected(view);
198 if (n_selected == 0)
200 gchar *s = NULL;
201 int n_items;
203 if (filer_window->scanning)
205 gtk_label_set_text(
206 GTK_LABEL(filer_window->toolbar_text), "");
207 return;
210 if (!(filer_window->show_hidden ||
211 filer_window->temp_show_hidden) ||
212 filer_window->filter!=FILER_SHOW_ALL)
214 GHashTable *hash = filer_window->directory->known_items;
215 int tally = 0;
217 filer_window_being_counted=filer_window;
218 g_hash_table_foreach(hash, tally_items, &tally);
220 if (tally)
221 s = g_strdup_printf(_(" (%u hidden)"), tally);
224 n_items = view_count_items(view);
226 if (n_items)
227 label = g_strdup_printf("%d %s%s",
228 n_items,
229 n_items != 1 ? _("items") : _("item"),
230 s ? s : "");
231 else /* (French plurals work differently for zero) */
232 label = g_strdup_printf(_("No items%s"),
233 s ? s : "");
234 g_free(s);
236 else
238 double size = 0;
239 ViewIter iter;
240 DirItem *item;
242 view_get_iter(filer_window->view, &iter, VIEW_ITER_SELECTED);
244 while ((item = iter.next(&iter)))
245 if (item->base_type != TYPE_DIRECTORY)
246 size += (double) item->size;
248 label = g_strdup_printf(_("%u selected (%s)"),
249 n_selected, format_double_size(size));
252 gtk_label_set_text(GTK_LABEL(filer_window->toolbar_text), label);
253 g_free(label);
256 /* Create, destroy or recreate toolbar for this window so that it
257 * matches the option setting.
259 void toolbar_update_toolbar(FilerWindow *filer_window)
261 g_return_if_fail(filer_window != NULL);
263 if (filer_window->toolbar)
265 gtk_widget_destroy(filer_window->toolbar);
266 filer_window->toolbar = NULL;
267 filer_window->toolbar_text = NULL;
270 if (o_toolbar.int_value != TOOLBAR_NONE)
272 filer_window->toolbar = create_toolbar(filer_window);
273 gtk_box_pack_start(filer_window->toplevel_vbox,
274 filer_window->toolbar, FALSE, TRUE, 0);
275 gtk_box_reorder_child(filer_window->toplevel_vbox,
276 filer_window->toolbar, 0);
277 gtk_widget_show_all(filer_window->toolbar);
280 filer_target_mode(filer_window, NULL, NULL, NULL);
281 toolbar_update_info(filer_window);
284 /****************************************************************
285 * INTERNAL FUNCTIONS *
286 ****************************************************************/
288 static void toolbar_help_clicked(GtkWidget *widget, FilerWindow *filer_window)
290 GdkEvent *event;
292 event = gtk_get_current_event();
293 if (event->type == GDK_BUTTON_RELEASE &&
294 ((GdkEventButton *) event)->button != 1)
295 menu_rox_help(NULL, HELP_MANUAL, NULL);
296 else
297 filer_opendir(make_path(app_dir, "Help"), NULL, NULL);
300 static void toolbar_refresh_clicked(GtkWidget *widget,
301 FilerWindow *filer_window)
303 GdkEvent *event;
305 event = gtk_get_current_event();
306 if (event->type == GDK_BUTTON_RELEASE &&
307 ((GdkEventButton *) event)->button != 1)
309 filer_opendir(filer_window->sym_path, filer_window, NULL);
311 else
312 filer_refresh(filer_window);
315 static void toolbar_home_clicked(GtkWidget *widget, FilerWindow *filer_window)
317 GdkEvent *event;
319 event = gtk_get_current_event();
320 if (event->type == GDK_BUTTON_RELEASE && NEW_WIN_BUTTON(event))
322 filer_opendir(home_dir, filer_window, NULL);
324 else
325 filer_change_to(filer_window, home_dir, NULL);
328 static void toolbar_bookmarks_clicked(GtkWidget *widget,
329 FilerWindow *filer_window)
331 GdkEvent *event;
333 g_return_if_fail(filer_window != NULL);
335 event = gtk_get_current_event();
336 if (event->type == GDK_BUTTON_PRESS &&
337 ((GdkEventButton *) event)->button == 1)
339 bookmarks_show_menu(filer_window);
341 else if (event->type == GDK_BUTTON_RELEASE &&
342 ((GdkEventButton *) event)->button != 1)
344 bookmarks_edit();
348 static void toolbar_close_clicked(GtkWidget *widget, FilerWindow *filer_window)
350 GdkEvent *event;
352 g_return_if_fail(filer_window != NULL);
354 event = gtk_get_current_event();
355 if (event->type == GDK_BUTTON_RELEASE &&
356 ((GdkEventButton *) event)->button != 1)
358 filer_opendir(filer_window->sym_path, filer_window, NULL);
360 else if (!filer_window_delete(filer_window->window, NULL, filer_window))
361 gtk_widget_destroy(filer_window->window);
364 static void toolbar_up_clicked(GtkWidget *widget, FilerWindow *filer_window)
366 GdkEvent *event;
368 event = gtk_get_current_event();
369 if (event->type == GDK_BUTTON_RELEASE && NEW_WIN_BUTTON(event))
371 filer_open_parent(filer_window);
373 else
374 change_to_parent(filer_window);
377 static void toolbar_autosize_clicked(GtkWidget *widget, FilerWindow *filer_window)
379 GdkEventButton *bev;
381 bev = (GdkEventButton *) gtk_get_current_event();
382 if (bev->type != GDK_BUTTON_RELEASE)
383 return;
385 display_set_layout(filer_window, AUTO_SIZE_ICONS, filer_window->details_type,
386 TRUE);
389 static void toolbar_size_clicked(GtkWidget *widget, FilerWindow *filer_window)
391 GdkEventButton *bev;
393 bev = (GdkEventButton *) gtk_get_current_event();
394 if (bev->type != GDK_BUTTON_RELEASE)
395 return;
397 display_change_size(filer_window, bev->button == 1);
400 static void toolbar_sort_clicked(GtkWidget *widget,
401 FilerWindow *filer_window)
403 GdkEventButton *bev;
404 int i, current, next, next_wrapped;
405 gboolean adjust;
406 GtkSortType dir;
407 gchar *tip;
409 static const SortType sorts[]={
410 SORT_NAME, SORT_TYPE, SORT_DATE, SORT_SIZE,
411 SORT_OWNER, SORT_GROUP,
413 static const char *sort_names[] = {
414 N_("Sort by name"), N_("Sort by type"), N_("Sort by date"),
415 N_("Sort by size"), N_("Sort by owner"), N_("Sort by group"),
418 bev = (GdkEventButton *) gtk_get_current_event();
419 adjust = (bev->button != 1) && bev->type == GDK_BUTTON_RELEASE;
421 current = -1;
422 dir = filer_window->sort_order;
423 for (i=0; i < G_N_ELEMENTS(sort_names); i++)
425 if (filer_window->sort_type == sorts[i])
427 current = i;
428 break;
432 if (current == -1)
433 next = 0;
434 else if (adjust)
435 next = current - 1;
436 else
437 next = current + 1;
439 next_wrapped = next % G_N_ELEMENTS(sorts);
441 if (next_wrapped != next)
442 dir = (dir == GTK_SORT_ASCENDING)
443 ? GTK_SORT_DESCENDING : GTK_SORT_ASCENDING;
445 display_set_sort_type(filer_window, sorts[next_wrapped], dir);
446 tip = g_strconcat(_(sort_names[next_wrapped]), ", ",
447 dir == GTK_SORT_ASCENDING
448 ? _("ascending") : _("descending"),
449 NULL);
450 tooltip_show(tip);
451 g_free(tip);
454 static void toolbar_details_clicked(GtkWidget *widget,
455 FilerWindow *filer_window)
457 if (filer_window->view_type == VIEW_TYPE_DETAILS)
458 filer_set_view_type(filer_window, VIEW_TYPE_COLLECTION);
459 else
460 filer_set_view_type(filer_window, VIEW_TYPE_DETAILS);
463 static void toolbar_hidden_clicked(GtkWidget *widget,
464 FilerWindow *filer_window)
466 display_set_hidden(filer_window, !filer_window->show_hidden);
469 static gboolean invert_cb(ViewIter *iter, gpointer data)
471 return !view_get_selected((ViewIface *) data, iter);
474 static void toolbar_select_clicked(GtkWidget *widget, FilerWindow *filer_window)
476 GdkEvent *event;
478 event = gtk_get_current_event();
479 if (event->type == GDK_BUTTON_RELEASE)
481 if (((GdkEventButton *) event)->button == 1)
482 view_select_all(filer_window->view);
483 else
484 view_select_if(filer_window->view, invert_cb,
485 filer_window->view);
487 filer_window->temp_item_selected = FALSE;
490 /* If filer_window is NULL, the toolbar is for the options window */
491 static GtkWidget *create_toolbar(FilerWindow *filer_window)
493 GtkWidget *bar;
494 GtkWidget *b;
495 int i;
497 bar = gtk_toolbar_new();
498 if (filer_window)
499 gtk_widget_set_size_request(bar, 100, -1);
501 if (o_toolbar.int_value == TOOLBAR_NORMAL || !filer_window)
502 gtk_toolbar_set_style(GTK_TOOLBAR(bar), GTK_TOOLBAR_ICONS);
503 else if (o_toolbar.int_value == TOOLBAR_HORIZONTAL)
504 gtk_toolbar_set_style(GTK_TOOLBAR(bar), GTK_TOOLBAR_BOTH_HORIZ);
505 else
506 gtk_toolbar_set_style(GTK_TOOLBAR(bar), GTK_TOOLBAR_BOTH);
508 for (i = 0; i < sizeof(all_tools) / sizeof(*all_tools); i++)
510 Tool *tool = &all_tools[i];
512 if (filer_window && !tool->enabled)
513 continue;
515 b = add_button(bar, tool, filer_window);
516 if (filer_window && tool->drop_action != DROP_NONE)
517 handle_drops(filer_window, b, tool->drop_action);
520 if (filer_window)
522 filer_window->toolbar_text = gtk_label_new("");
523 gtk_misc_set_alignment(GTK_MISC(filer_window->toolbar_text),
524 0, 0.5);
525 gtk_toolbar_append_widget(GTK_TOOLBAR(bar),
526 filer_window->toolbar_text, NULL, NULL);
529 return bar;
532 /* This is used to simulate a click when button 3 is used (GtkButton
533 * normally ignores this).
535 static gint toolbar_other_button = 0;
536 static gint toolbar_button_pressed(GtkButton *button,
537 GdkEventButton *event,
538 FilerWindow *filer_window)
540 gint b = event->button;
541 Tool *tool;
543 tool = g_object_get_data(G_OBJECT(button), "rox-tool");
544 g_return_val_if_fail(tool != NULL, TRUE);
546 if (tool->menu && b == 1)
548 tool->clicked((GtkWidget *) button, filer_window);
549 return TRUE;
552 if ((b == 2 || b == 3) && toolbar_other_button == 0)
554 toolbar_other_button = event->button;
555 gtk_grab_add(GTK_WIDGET(button));
556 gtk_button_pressed(button);
558 return TRUE;
561 return FALSE;
564 static gint toolbar_button_released(GtkButton *button,
565 GdkEventButton *event,
566 FilerWindow *filer_window)
568 if (event->button == toolbar_other_button)
570 toolbar_other_button = 0;
571 gtk_grab_remove(GTK_WIDGET(button));
572 gtk_button_released(button);
574 return TRUE;
577 return FALSE;
580 /* If filer_window is NULL, the toolbar is for the options window */
581 static GtkWidget *add_button(GtkWidget *bar, Tool *tool,
582 FilerWindow *filer_window)
584 GtkWidget *button, *icon_widget;
586 icon_widget = gtk_image_new_from_stock(tool->name,
587 GTK_ICON_SIZE_LARGE_TOOLBAR);
589 button = gtk_toolbar_insert_element(GTK_TOOLBAR(bar),
590 filer_window ? GTK_TOOLBAR_CHILD_BUTTON
591 : GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
592 NULL,
593 _(tool->label),
594 _(tool->tip), NULL,
595 icon_widget,
596 NULL, NULL, /* CB, userdata */
597 GTK_TOOLBAR(bar)->num_children);
599 if (o_toolbar.int_value == TOOLBAR_HORIZONTAL)
601 GtkWidget *hbox, *label;
602 GList *kids;
603 hbox = GTK_BIN(button)->child;
604 kids = gtk_container_get_children(GTK_CONTAINER(hbox));
605 label = g_list_nth_data(kids, 1);
606 g_list_free(kids);
608 if (label)
610 gtk_box_set_child_packing(GTK_BOX(hbox), label,
611 TRUE, TRUE, 0, GTK_PACK_END);
612 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
616 g_object_set_data(G_OBJECT(button), "rox-tool", tool);
618 if (filer_window)
620 g_signal_connect(button, "clicked",
621 G_CALLBACK(tool->clicked), filer_window);
622 g_signal_connect(button, "button_press_event",
623 G_CALLBACK(toolbar_button_pressed), filer_window);
624 g_signal_connect(button, "button_release_event",
625 G_CALLBACK(toolbar_button_released), filer_window);
627 else
629 g_signal_connect(button, "clicked",
630 G_CALLBACK(toggle_selected), NULL);
631 g_object_set_data(G_OBJECT(button), "tool_name",
632 (gpointer) tool->name);
635 return button;
638 static void toggle_selected(GtkToggleButton *widget, gpointer data)
640 option_check_widget(&o_toolbar_disable);
643 /* Called during the drag when the mouse is in a widget registered
644 * as a drop target. Returns TRUE if we can accept the drop.
646 static gboolean drag_motion(GtkWidget *widget,
647 GdkDragContext *context,
648 gint x,
649 gint y,
650 guint time,
651 FilerWindow *filer_window)
653 GdkDragAction action = context->suggested_action;
654 DropDest dest;
655 gpointer type = (gpointer) drop_dest_dir;
657 dest = (DropDest) g_object_get_data(G_OBJECT(widget), "toolbar_dest");
659 if ((context->actions & GDK_ACTION_ASK) && o_dnd_left_menu.int_value &&
660 dest != DROP_BOOKMARK)
662 guint state;
663 gdk_window_get_pointer(NULL, NULL, NULL, &state);
664 if (state & GDK_BUTTON1_MASK)
665 action = GDK_ACTION_ASK;
668 if (dest == DROP_TO_HOME)
669 g_dataset_set_data(context, "drop_dest_path",
670 (gchar *) home_dir);
671 else if (dest == DROP_BOOKMARK)
672 type = (gpointer) drop_dest_bookmark;
673 else
674 g_dataset_set_data_full(context, "drop_dest_path",
675 g_path_get_dirname(filer_window->sym_path),
676 g_free);
678 g_dataset_set_data(context, "drop_dest_type", type);
679 gdk_drag_status(context, action, time);
681 dnd_spring_load(context, filer_window);
682 gtk_button_set_relief(GTK_BUTTON(widget), GTK_RELIEF_NORMAL);
684 return TRUE;
687 static void drag_leave(GtkWidget *widget,
688 GdkDragContext *context,
689 guint32 time,
690 FilerWindow *filer_window)
692 gtk_button_set_relief(GTK_BUTTON(widget), GTK_RELIEF_NONE);
693 dnd_spring_abort();
696 static void handle_drops(FilerWindow *filer_window,
697 GtkWidget *button,
698 DropDest dest)
700 make_drop_target(button, 0);
701 g_signal_connect(button, "drag_motion",
702 G_CALLBACK(drag_motion), filer_window);
703 g_signal_connect(button, "drag_leave",
704 G_CALLBACK(drag_leave), filer_window);
705 g_object_set_data(G_OBJECT(button), "toolbar_dest", (gpointer) dest);
708 static void tally_items(gpointer key, gpointer value, gpointer data)
710 guchar *leafname = (guchar *) key;
711 int *tally = (int *) data;
713 if (!filer_match_filter(filer_window_being_counted, leafname))
714 (*tally)++;
717 static void option_notify(void)
719 int i;
720 gboolean changed = FALSE;
721 guchar *list = o_toolbar_disable.value;
723 for (i = 0; i < sizeof(all_tools) / sizeof(*all_tools); i++)
725 Tool *tool = &all_tools[i];
726 gboolean old = tool->enabled;
728 tool->enabled = !in_list(tool->name, list);
730 if (old != tool->enabled)
731 changed = TRUE;
734 if (changed || o_toolbar.has_changed || o_toolbar_info.has_changed)
736 GList *next;
738 for (next = all_filer_windows; next; next = next->next)
740 FilerWindow *filer_window = (FilerWindow *) next->data;
742 toolbar_update_toolbar(filer_window);
747 static void update_tools(Option *option)
749 GList *next, *kids;
751 kids = gtk_container_get_children(GTK_CONTAINER(option->widget));
753 for (next = kids; next; next = next->next)
755 GtkToggleButton *kid = (GtkToggleButton *) next->data;
756 guchar *name;
758 name = g_object_get_data(G_OBJECT(kid), "tool_name");
760 g_return_if_fail(name != NULL);
762 gtk_toggle_button_set_active(kid,
763 !in_list(name, option->value));
766 g_list_free(kids);
769 static guchar *read_tools(Option *option)
771 GList *next, *kids;
772 GString *list;
773 guchar *retval;
775 list = g_string_new(NULL);
777 kids = gtk_container_get_children(GTK_CONTAINER(option->widget));
779 for (next = kids; next; next = next->next)
781 GtkToggleButton *kid = (GtkToggleButton *) next->data;
782 guchar *name;
784 if (!gtk_toggle_button_get_active(kid))
786 name = g_object_get_data(G_OBJECT(kid), "tool_name");
787 g_return_val_if_fail(name != NULL, list->str);
789 if (list->len)
790 g_string_append(list, ", ");
791 g_string_append(list, name);
795 g_list_free(kids);
796 retval = list->str;
797 g_string_free(list, FALSE);
799 return retval;
802 static GList *build_tool_options(Option *option, xmlNode *node, guchar *label)
804 GtkWidget *bar;
806 g_return_val_if_fail(option != NULL, NULL);
808 bar = create_toolbar(NULL);
810 option->update_widget = update_tools;
811 option->read_widget = read_tools;
812 option->widget = bar;
814 return g_list_append(NULL, bar);