r2918: Doing a Refresh in a directory under /uri/0install triggers a remote refresh.
[rox-filer.git] / ROX-Filer / src / toolbar.c
blobb2b15c090b2a389da74fdb2166bbff4765e66a11
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;
65 /* TRUE if the button presses (or released) should open a new window,
66 * rather than reusing the existing one.
68 #define NEW_WIN_BUTTON(button_event) \
69 (o_new_button_1.int_value \
70 ? ((GdkEventButton *) button_event)->button == 1 \
71 : ((GdkEventButton *) button_event)->button != 1)
73 /* Static prototypes */
74 static void toolbar_close_clicked(GtkWidget *widget, FilerWindow *filer_window);
75 static void toolbar_up_clicked(GtkWidget *widget, FilerWindow *filer_window);
76 static void toolbar_home_clicked(GtkWidget *widget, FilerWindow *filer_window);
77 static void toolbar_bookmarks_clicked(GtkWidget *widget,
78 FilerWindow *filer_window);
79 static void toolbar_help_clicked(GtkWidget *widget, FilerWindow *filer_window);
80 static void toolbar_refresh_clicked(GtkWidget *widget,
81 FilerWindow *filer_window);
82 static void toolbar_size_clicked(GtkWidget *widget, FilerWindow *filer_window);
83 static void toolbar_autosize_clicked(GtkWidget *widget, FilerWindow *filer_window);
84 static void toolbar_details_clicked(GtkWidget *widget,
85 FilerWindow *filer_window);
86 static void toolbar_hidden_clicked(GtkWidget *widget,
87 FilerWindow *filer_window);
88 static void toolbar_select_clicked(GtkWidget *widget,
89 FilerWindow *filer_window);
90 static void toolbar_sort_clicked(GtkWidget *widget,
91 FilerWindow *filer_window);
92 static GtkWidget *add_button(GtkWidget *bar, Tool *tool,
93 FilerWindow *filer_window);
94 static GtkWidget *create_toolbar(FilerWindow *filer_window);
95 static gboolean drag_motion(GtkWidget *widget,
96 GdkDragContext *context,
97 gint x,
98 gint y,
99 guint time,
100 FilerWindow *filer_window);
101 static void drag_leave(GtkWidget *widget,
102 GdkDragContext *context,
103 guint32 time,
104 FilerWindow *filer_window);
105 static void handle_drops(FilerWindow *filer_window,
106 GtkWidget *button,
107 DropDest dest);
108 static void toggle_selected(GtkToggleButton *widget, gpointer data);
109 static void option_notify(void);
110 static GList *build_tool_options(Option *option, xmlNode *node, guchar *label);
111 static void tally_items(gpointer key, gpointer value, gpointer data);
113 static Tool all_tools[] = {
114 {N_("Close"), GTK_STOCK_CLOSE, N_("Close filer window"),
115 toolbar_close_clicked, DROP_NONE, FALSE,
116 FALSE},
118 {N_("Up"), GTK_STOCK_GO_UP, N_("Change to parent directory"),
119 toolbar_up_clicked, DROP_TO_PARENT, TRUE,
120 FALSE},
122 {N_("Home"), GTK_STOCK_HOME, N_("Change to home directory"),
123 toolbar_home_clicked, DROP_TO_HOME, TRUE,
124 FALSE},
126 {N_("Bookmarks"), ROX_STOCK_BOOKMARKS, N_("Bookmarks menu"),
127 toolbar_bookmarks_clicked, DROP_BOOKMARK, FALSE,
128 TRUE},
130 {N_("Scan"), GTK_STOCK_REFRESH, N_("Rescan directory contents"),
131 toolbar_refresh_clicked, DROP_NONE, TRUE,
132 FALSE},
134 {N_("Size"), GTK_STOCK_ZOOM_IN, N_("Change icon size"),
135 toolbar_size_clicked, DROP_NONE, TRUE,
136 FALSE},
138 {N_("Size"), GTK_STOCK_ZOOM_FIT, N_("Automatic size mode"),
139 toolbar_autosize_clicked, DROP_NONE, TRUE,
140 FALSE},
142 {N_("Details"), ROX_STOCK_SHOW_DETAILS, N_("Show extra details"),
143 toolbar_details_clicked, DROP_NONE, TRUE,
144 FALSE},
146 {N_("Sort"), GTK_STOCK_SORT_ASCENDING, N_("Change sort criteria"),
147 toolbar_sort_clicked, DROP_NONE, FALSE,
148 FALSE},
150 {N_("Hidden"), ROX_STOCK_SHOW_HIDDEN, N_("Show/hide hidden files"),
151 toolbar_hidden_clicked, DROP_NONE, TRUE,
152 FALSE},
154 {N_("Select"), GTK_STOCK_COPY, N_("Select all/invert selection"),
155 toolbar_select_clicked, DROP_NONE, FALSE,
156 FALSE},
158 {N_("Help"), GTK_STOCK_HELP, N_("Show ROX-Filer help"),
159 toolbar_help_clicked, DROP_NONE, TRUE,
160 FALSE},
164 /****************************************************************
165 * EXTERNAL INTERFACE *
166 ****************************************************************/
168 void toolbar_init(void)
170 option_add_int(&o_toolbar, "toolbar_type", TOOLBAR_NORMAL);
171 option_add_int(&o_toolbar_info, "toolbar_show_info", 1);
172 option_add_string(&o_toolbar_disable, "toolbar_disable",
173 GTK_STOCK_CLOSE);
174 option_add_notify(option_notify);
176 tooltips = gtk_tooltips_new();
178 option_register_widget("tool-options", build_tool_options);
181 void toolbar_update_info(FilerWindow *filer_window)
183 gchar *label;
184 ViewIface *view;
185 int n_selected;
187 if (o_toolbar.int_value == TOOLBAR_NONE || !o_toolbar_info.int_value)
188 return; /* Not showing info */
190 if (filer_window->target_cb)
191 return;
193 view = filer_window->view;
195 n_selected = view_count_selected(view);
197 if (n_selected == 0)
199 gchar *s = NULL;
200 int n_items;
202 if (filer_window->scanning)
204 gtk_label_set_text(
205 GTK_LABEL(filer_window->toolbar_text), "");
206 return;
209 if (!filer_window->show_hidden)
211 GHashTable *hash = filer_window->directory->known_items;
212 int tally = 0;
214 g_hash_table_foreach(hash, tally_items, &tally);
216 if (tally)
217 s = g_strdup_printf(_(" (%u hidden)"), tally);
220 n_items = view_count_items(view);
222 if (n_items)
223 label = g_strdup_printf("%d %s%s",
224 n_items,
225 n_items != 1 ? _("items") : _("item"),
226 s ? s : "");
227 else /* (French plurals work differently for zero) */
228 label = g_strdup_printf(_("No items%s"),
229 s ? s : "");
230 g_free(s);
232 else
234 double size = 0;
235 ViewIter iter;
236 DirItem *item;
238 view_get_iter(filer_window->view, &iter, VIEW_ITER_SELECTED);
240 while ((item = iter.next(&iter)))
241 if (item->base_type != TYPE_DIRECTORY)
242 size += (double) item->size;
244 label = g_strdup_printf(_("%u selected (%s)"),
245 n_selected, format_double_size(size));
248 gtk_label_set_text(GTK_LABEL(filer_window->toolbar_text), label);
249 g_free(label);
252 /* Create, destroy or recreate toolbar for this window so that it
253 * matches the option setting.
255 void toolbar_update_toolbar(FilerWindow *filer_window)
257 g_return_if_fail(filer_window != NULL);
259 if (filer_window->toolbar)
261 gtk_widget_destroy(filer_window->toolbar);
262 filer_window->toolbar = NULL;
263 filer_window->toolbar_text = NULL;
266 if (o_toolbar.int_value != TOOLBAR_NONE)
268 filer_window->toolbar = create_toolbar(filer_window);
269 gtk_box_pack_start(filer_window->toplevel_vbox,
270 filer_window->toolbar, FALSE, TRUE, 0);
271 gtk_box_reorder_child(filer_window->toplevel_vbox,
272 filer_window->toolbar, 0);
273 gtk_widget_show_all(filer_window->toolbar);
276 filer_target_mode(filer_window, NULL, NULL, NULL);
277 toolbar_update_info(filer_window);
280 /****************************************************************
281 * INTERNAL FUNCTIONS *
282 ****************************************************************/
284 static void toolbar_help_clicked(GtkWidget *widget, FilerWindow *filer_window)
286 GdkEvent *event;
288 event = gtk_get_current_event();
289 if (event->type == GDK_BUTTON_RELEASE &&
290 ((GdkEventButton *) event)->button != 1)
291 menu_rox_help(NULL, HELP_MANUAL, NULL);
292 else
293 filer_opendir(make_path(app_dir, "Help"), NULL, NULL);
296 static void toolbar_refresh_clicked(GtkWidget *widget,
297 FilerWindow *filer_window)
299 GdkEvent *event;
301 event = gtk_get_current_event();
302 if (event->type == GDK_BUTTON_RELEASE &&
303 ((GdkEventButton *) event)->button != 1)
305 filer_opendir(filer_window->sym_path, filer_window, NULL);
307 else
308 filer_refresh(filer_window);
311 static void toolbar_home_clicked(GtkWidget *widget, FilerWindow *filer_window)
313 GdkEvent *event;
315 event = gtk_get_current_event();
316 if (event->type == GDK_BUTTON_RELEASE && NEW_WIN_BUTTON(event))
318 filer_opendir(home_dir, filer_window, NULL);
320 else
321 filer_change_to(filer_window, home_dir, NULL);
324 static void toolbar_bookmarks_clicked(GtkWidget *widget,
325 FilerWindow *filer_window)
327 GdkEvent *event;
329 g_return_if_fail(filer_window != NULL);
331 event = gtk_get_current_event();
332 if (event->type == GDK_BUTTON_PRESS &&
333 ((GdkEventButton *) event)->button == 1)
335 bookmarks_show_menu(filer_window);
337 else if (event->type == GDK_BUTTON_RELEASE &&
338 ((GdkEventButton *) event)->button != 1)
340 bookmarks_edit();
344 static void toolbar_close_clicked(GtkWidget *widget, FilerWindow *filer_window)
346 GdkEvent *event;
348 g_return_if_fail(filer_window != NULL);
350 event = gtk_get_current_event();
351 if (event->type == GDK_BUTTON_RELEASE &&
352 ((GdkEventButton *) event)->button != 1)
354 filer_opendir(filer_window->sym_path, filer_window, NULL);
356 else if (!filer_window_delete(filer_window->window, NULL, filer_window))
357 gtk_widget_destroy(filer_window->window);
360 static void toolbar_up_clicked(GtkWidget *widget, FilerWindow *filer_window)
362 GdkEvent *event;
364 event = gtk_get_current_event();
365 if (event->type == GDK_BUTTON_RELEASE && NEW_WIN_BUTTON(event))
367 filer_open_parent(filer_window);
369 else
370 change_to_parent(filer_window);
373 static void toolbar_autosize_clicked(GtkWidget *widget, FilerWindow *filer_window)
375 GdkEventButton *bev;
377 bev = (GdkEventButton *) gtk_get_current_event();
378 if (bev->type != GDK_BUTTON_RELEASE)
379 return;
381 display_set_layout(filer_window, AUTO_SIZE_ICONS, filer_window->details_type,
382 TRUE);
385 static void toolbar_size_clicked(GtkWidget *widget, FilerWindow *filer_window)
387 GdkEventButton *bev;
389 bev = (GdkEventButton *) gtk_get_current_event();
390 if (bev->type != GDK_BUTTON_RELEASE)
391 return;
393 display_change_size(filer_window, bev->button == 1);
396 static void toolbar_sort_clicked(GtkWidget *widget,
397 FilerWindow *filer_window)
399 GdkEventButton *bev;
400 int i, current, next;
401 gboolean adjust;
402 GtkSortType dir;
403 gchar *tip;
405 static const SortType sorts[]={
406 SORT_NAME, SORT_TYPE, SORT_DATE, SORT_SIZE,
407 SORT_OWNER, SORT_GROUP,
409 static const int nsorts=sizeof(sorts)/sizeof(sorts[0]);
410 static const char *sort_names[]={
411 N_("Sort by name"), N_("Sort by type"), N_("Sort by date"),
412 N_("Sort by size"), N_("Sort by owner"), N_("Sort by group"),
415 bev = (GdkEventButton *) gtk_get_current_event();
416 adjust=(bev->button == 2) && bev->type == GDK_BUTTON_RELEASE;
418 current=-1;
419 dir=filer_window->sort_order;
420 for(i=0; i<nsorts; i++)
421 if(filer_window->sort_type==sorts[i]) {
422 current=i;
423 break;
425 if(current==-1) {
426 next=0;
427 dir=GTK_SORT_ASCENDING;
428 } else if(adjust) {
429 next=current-1;
430 if(next<0) {
431 next=nsorts-1;
432 dir=(dir==GTK_SORT_ASCENDING)?
433 GTK_SORT_DESCENDING: GTK_SORT_ASCENDING;
435 } else {
436 next=current+1;
437 if(next>=nsorts) {
438 next=0;
439 dir=(dir==GTK_SORT_ASCENDING)?
440 GTK_SORT_DESCENDING: GTK_SORT_ASCENDING;
444 display_set_sort_type(filer_window, sorts[next], dir);
445 tip=g_strconcat(_(sort_names[next]), ", ",
446 dir==GTK_SORT_ASCENDING? _("ascending"): _("descending"),
447 NULL);
448 tooltip_show(tip);
449 g_free(tip);
452 static void toolbar_details_clicked(GtkWidget *widget,
453 FilerWindow *filer_window)
455 if (filer_window->view_type == VIEW_TYPE_DETAILS)
456 filer_set_view_type(filer_window, VIEW_TYPE_COLLECTION);
457 else
458 filer_set_view_type(filer_window, VIEW_TYPE_DETAILS);
461 static void toolbar_hidden_clicked(GtkWidget *widget,
462 FilerWindow *filer_window)
464 display_set_hidden(filer_window, !filer_window->show_hidden);
467 static gboolean invert_cb(ViewIter *iter, gpointer data)
469 return !view_get_selected((ViewIface *) data, iter);
472 static void toolbar_select_clicked(GtkWidget *widget, FilerWindow *filer_window)
474 GdkEvent *event;
476 event = gtk_get_current_event();
477 if (event->type == GDK_BUTTON_RELEASE &&
478 ((GdkEventButton *) event)->button==2)
480 view_select_if(filer_window->view, invert_cb,
481 filer_window->view);
483 else if (event->type == GDK_BUTTON_RELEASE &&
484 ((GdkEventButton *) event)->button==1)
486 view_select_all(filer_window->view);
488 filer_window->temp_item_selected = FALSE;
491 /* If filer_window is NULL, the toolbar is for the options window */
492 static GtkWidget *create_toolbar(FilerWindow *filer_window)
494 GtkWidget *bar;
495 GtkWidget *b;
496 int i;
498 bar = gtk_toolbar_new();
499 if (filer_window)
500 gtk_widget_set_size_request(bar, 100, -1);
502 if (o_toolbar.int_value == TOOLBAR_NORMAL || !filer_window)
503 gtk_toolbar_set_style(GTK_TOOLBAR(bar), GTK_TOOLBAR_ICONS);
504 else if (o_toolbar.int_value == TOOLBAR_HORIZONTAL)
505 gtk_toolbar_set_style(GTK_TOOLBAR(bar), GTK_TOOLBAR_BOTH_HORIZ);
506 else
507 gtk_toolbar_set_style(GTK_TOOLBAR(bar), GTK_TOOLBAR_BOTH);
509 for (i = 0; i < sizeof(all_tools) / sizeof(*all_tools); i++)
511 Tool *tool = &all_tools[i];
513 if (filer_window && !tool->enabled)
514 continue;
516 b = add_button(bar, tool, filer_window);
517 if (filer_window && tool->drop_action != DROP_NONE)
518 handle_drops(filer_window, b, tool->drop_action);
521 if (filer_window)
523 filer_window->toolbar_text = gtk_label_new("");
524 gtk_misc_set_alignment(GTK_MISC(filer_window->toolbar_text),
525 0, 0.5);
526 gtk_toolbar_append_widget(GTK_TOOLBAR(bar),
527 filer_window->toolbar_text, NULL, NULL);
530 return bar;
533 /* This is used to simulate a click when button 3 is used (GtkButton
534 * normally ignores this).
536 static gint toolbar_other_button = 0;
537 static gint toolbar_button_pressed(GtkButton *button,
538 GdkEventButton *event,
539 FilerWindow *filer_window)
541 gint b = event->button;
542 Tool *tool;
544 tool = g_object_get_data(G_OBJECT(button), "rox-tool");
545 g_return_val_if_fail(tool != NULL, TRUE);
547 if (tool->menu && b == 1)
549 tool->clicked((GtkWidget *) button, filer_window);
550 return TRUE;
553 if ((b == 2 || b == 3) && toolbar_other_button == 0)
555 toolbar_other_button = event->button;
556 gtk_grab_add(GTK_WIDGET(button));
557 gtk_button_pressed(button);
559 return TRUE;
562 return FALSE;
565 static gint toolbar_button_released(GtkButton *button,
566 GdkEventButton *event,
567 FilerWindow *filer_window)
569 if (event->button == toolbar_other_button)
571 toolbar_other_button = 0;
572 gtk_grab_remove(GTK_WIDGET(button));
573 gtk_button_released(button);
575 return TRUE;
578 return FALSE;
581 /* If filer_window is NULL, the toolbar is for the options window */
582 static GtkWidget *add_button(GtkWidget *bar, Tool *tool,
583 FilerWindow *filer_window)
585 GtkWidget *button, *icon_widget;
587 icon_widget = gtk_image_new_from_stock(tool->name,
588 GTK_ICON_SIZE_LARGE_TOOLBAR);
590 button = gtk_toolbar_insert_element(GTK_TOOLBAR(bar),
591 filer_window ? GTK_TOOLBAR_CHILD_BUTTON
592 : GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
593 NULL,
594 _(tool->label),
595 _(tool->tip), NULL,
596 icon_widget,
597 NULL, NULL, /* CB, userdata */
598 GTK_TOOLBAR(bar)->num_children);
600 if (o_toolbar.int_value == TOOLBAR_HORIZONTAL)
602 GtkWidget *hbox, *label;
603 GList *kids;
604 hbox = GTK_BIN(button)->child;
605 kids = gtk_container_get_children(GTK_CONTAINER(hbox));
606 label = g_list_nth_data(kids, 1);
607 g_list_free(kids);
609 if (label)
611 gtk_box_set_child_packing(GTK_BOX(hbox), label,
612 TRUE, TRUE, 0, GTK_PACK_END);
613 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
617 g_object_set_data(G_OBJECT(button), "rox-tool", tool);
619 if (filer_window)
621 g_signal_connect(button, "clicked",
622 G_CALLBACK(tool->clicked), filer_window);
623 g_signal_connect(button, "button_press_event",
624 G_CALLBACK(toolbar_button_pressed), filer_window);
625 g_signal_connect(button, "button_release_event",
626 G_CALLBACK(toolbar_button_released), filer_window);
628 else
630 g_signal_connect(button, "clicked",
631 G_CALLBACK(toggle_selected), NULL);
632 g_object_set_data(G_OBJECT(button), "tool_name",
633 (gpointer) tool->name);
636 return button;
639 static void toggle_selected(GtkToggleButton *widget, gpointer data)
641 option_check_widget(&o_toolbar_disable);
644 /* Called during the drag when the mouse is in a widget registered
645 * as a drop target. Returns TRUE if we can accept the drop.
647 static gboolean drag_motion(GtkWidget *widget,
648 GdkDragContext *context,
649 gint x,
650 gint y,
651 guint time,
652 FilerWindow *filer_window)
654 GdkDragAction action = context->suggested_action;
655 DropDest dest;
656 gpointer type = (gpointer) drop_dest_dir;
658 dest = (DropDest) g_object_get_data(G_OBJECT(widget), "toolbar_dest");
660 if ((context->actions & GDK_ACTION_ASK) && o_dnd_left_menu.int_value &&
661 dest != DROP_BOOKMARK)
663 guint state;
664 gdk_window_get_pointer(NULL, NULL, NULL, &state);
665 if (state & GDK_BUTTON1_MASK)
666 action = GDK_ACTION_ASK;
669 if (dest == DROP_TO_HOME)
670 g_dataset_set_data(context, "drop_dest_path",
671 (gchar *) home_dir);
672 else if (dest == DROP_BOOKMARK)
673 type = (gpointer) drop_dest_bookmark;
674 else
675 g_dataset_set_data_full(context, "drop_dest_path",
676 g_path_get_dirname(filer_window->sym_path),
677 g_free);
679 g_dataset_set_data(context, "drop_dest_type", type);
680 gdk_drag_status(context, action, time);
682 dnd_spring_load(context, filer_window);
683 gtk_button_set_relief(GTK_BUTTON(widget), GTK_RELIEF_NORMAL);
685 return TRUE;
688 static void drag_leave(GtkWidget *widget,
689 GdkDragContext *context,
690 guint32 time,
691 FilerWindow *filer_window)
693 gtk_button_set_relief(GTK_BUTTON(widget), GTK_RELIEF_NONE);
694 dnd_spring_abort();
697 static void handle_drops(FilerWindow *filer_window,
698 GtkWidget *button,
699 DropDest dest)
701 make_drop_target(button, 0);
702 g_signal_connect(button, "drag_motion",
703 G_CALLBACK(drag_motion), filer_window);
704 g_signal_connect(button, "drag_leave",
705 G_CALLBACK(drag_leave), filer_window);
706 g_object_set_data(G_OBJECT(button), "toolbar_dest", (gpointer) dest);
709 static void tally_items(gpointer key, gpointer value, gpointer data)
711 guchar *leafname = (guchar *) key;
712 int *tally = (int *) data;
714 if (leafname[0] == '.')
715 (*tally)++;
718 static void option_notify(void)
720 int i;
721 gboolean changed = FALSE;
722 guchar *list = o_toolbar_disable.value;
724 for (i = 0; i < sizeof(all_tools) / sizeof(*all_tools); i++)
726 Tool *tool = &all_tools[i];
727 gboolean old = tool->enabled;
729 tool->enabled = !in_list(tool->name, list);
731 if (old != tool->enabled)
732 changed = TRUE;
735 if (changed || o_toolbar.has_changed || o_toolbar_info.has_changed)
737 GList *next;
739 for (next = all_filer_windows; next; next = next->next)
741 FilerWindow *filer_window = (FilerWindow *) next->data;
743 toolbar_update_toolbar(filer_window);
748 static void update_tools(Option *option)
750 GList *next, *kids;
752 kids = gtk_container_get_children(GTK_CONTAINER(option->widget));
754 for (next = kids; next; next = next->next)
756 GtkToggleButton *kid = (GtkToggleButton *) next->data;
757 guchar *name;
759 name = g_object_get_data(G_OBJECT(kid), "tool_name");
761 g_return_if_fail(name != NULL);
763 gtk_toggle_button_set_active(kid,
764 !in_list(name, option->value));
767 g_list_free(kids);
770 static guchar *read_tools(Option *option)
772 GList *next, *kids;
773 GString *list;
774 guchar *retval;
776 list = g_string_new(NULL);
778 kids = gtk_container_get_children(GTK_CONTAINER(option->widget));
780 for (next = kids; next; next = next->next)
782 GtkToggleButton *kid = (GtkToggleButton *) next->data;
783 guchar *name;
785 if (!gtk_toggle_button_get_active(kid))
787 name = g_object_get_data(G_OBJECT(kid), "tool_name");
788 g_return_val_if_fail(name != NULL, list->str);
790 if (list->len)
791 g_string_append(list, ", ");
792 g_string_append(list, name);
796 g_list_free(kids);
797 retval = list->str;
798 g_string_free(list, FALSE);
800 return retval;
803 static GList *build_tool_options(Option *option, xmlNode *node, guchar *label)
805 GtkWidget *bar;
807 g_return_val_if_fail(option != NULL, NULL);
809 bar = create_toolbar(NULL);
811 option->update_widget = update_tools;
812 option->read_widget = read_tools;
813 option->widget = bar;
815 return g_list_append(NULL, bar);