r336: Added an option to control the spring-loading feature. Added tooltips
[rox-filer.git] / ROX-Filer / src / options.c
blobbbad76b6b13593b2d76d14bf46e8020798d47255
1 /*
2 * $Id$
4 * ROX-Filer, filer for the ROX desktop project
5 * Copyright (C) 2000, Thomas Leonard, <tal197@ecs.soton.ac.uk>.
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 /* options.c - code for handling user choices */
24 #include "config.h"
26 #include <stdio.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <glib.h>
30 #include <gtk/gtk.h>
32 #include "gui_support.h"
33 #include "choices.h"
34 #include "options.h"
36 /* Add OptionsSection structs to this list in your _init() functions */
37 GSList *options_sections = NULL;
39 /* Add all option tooltips to this group */
40 GtkTooltips *option_tooltips = NULL;
42 static GtkWidget *window, *sections_vbox;
43 static FILE *save_file = NULL;
44 static GHashTable *option_hash = NULL;
46 enum {BUTTON_SAVE, BUTTON_OK, BUTTON_APPLY};
48 /* Static prototypes */
49 static void save_options(GtkWidget *widget, gpointer data);
50 static char *process_option_line(guchar *line);
52 void options_init()
54 GtkWidget *tl_vbox, *scrolled_area;
55 GtkWidget *border, *label;
56 GtkWidget *actions, *button;
57 char *string, *save_path;
59 option_tooltips = gtk_tooltips_new();
61 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
62 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
63 gtk_window_set_title(GTK_WINDOW(window), _("ROX-Filer options"));
64 gtk_signal_connect(GTK_OBJECT(window), "delete_event",
65 GTK_SIGNAL_FUNC(hide_dialog_event), window);
66 gtk_container_set_border_width(GTK_CONTAINER(window), 4);
67 gtk_window_set_default_size(GTK_WINDOW(window), 400, 400);
69 tl_vbox = gtk_vbox_new(FALSE, 4);
70 gtk_container_add(GTK_CONTAINER(window), tl_vbox);
72 scrolled_area = gtk_scrolled_window_new(NULL, NULL);
73 gtk_container_set_border_width(GTK_CONTAINER(scrolled_area), 4);
74 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_area),
75 GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
76 gtk_box_pack_start(GTK_BOX(tl_vbox), scrolled_area, TRUE, TRUE, 0);
78 border = gtk_frame_new(NULL);
79 gtk_frame_set_shadow_type(GTK_FRAME(border), GTK_SHADOW_NONE);
80 gtk_container_set_border_width(GTK_CONTAINER(border), 4);
81 gtk_scrolled_window_add_with_viewport(
82 GTK_SCROLLED_WINDOW(scrolled_area), border);
84 sections_vbox = gtk_vbox_new(FALSE, 4);
85 gtk_container_add(GTK_CONTAINER(border), sections_vbox);
87 save_path = choices_find_path_save("...", PROJECT, FALSE);
88 if (save_path)
90 string = g_strconcat(_("Choices will be saved as "),
91 save_path,
92 NULL);
93 label = gtk_label_new(string);
94 g_free(string);
96 else
97 label = gtk_label_new(_("Choices saving is disabled by "
98 "CHOICESPATH variable"));
99 gtk_box_pack_start(GTK_BOX(tl_vbox), label, FALSE, TRUE, 0);
101 actions = gtk_hbox_new(TRUE, 16);
102 gtk_box_pack_start(GTK_BOX(tl_vbox), actions, FALSE, TRUE, 0);
104 button = gtk_button_new_with_label(_("Save"));
105 gtk_box_pack_start(GTK_BOX(actions), button, FALSE, TRUE, 0);
106 if (!save_path)
107 gtk_widget_set_sensitive(button, FALSE);
108 gtk_signal_connect(GTK_OBJECT(button), "clicked",
109 GTK_SIGNAL_FUNC(save_options), (gpointer) BUTTON_SAVE);
111 button = gtk_button_new_with_label(_("OK"));
112 gtk_box_pack_start(GTK_BOX(actions), button, FALSE, TRUE, 0);
113 gtk_signal_connect(GTK_OBJECT(button), "clicked",
114 GTK_SIGNAL_FUNC(save_options), (gpointer) BUTTON_OK);
116 button = gtk_button_new_with_label(_("Apply"));
117 gtk_box_pack_start(GTK_BOX(actions), button, FALSE, TRUE, 0);
118 gtk_signal_connect(GTK_OBJECT(button), "clicked",
119 GTK_SIGNAL_FUNC(save_options), (gpointer) BUTTON_APPLY);
121 button = gtk_button_new_with_label(_("Cancel"));
122 gtk_box_pack_start(GTK_BOX(actions), button, FALSE, TRUE, 0);
123 gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
124 GTK_SIGNAL_FUNC(gtk_widget_hide), GTK_OBJECT(window));
127 void options_load(void)
129 static gboolean need_init = TRUE;
130 char *path;
132 if (need_init)
134 GtkWidget *group;
135 GSList *next = options_sections;
137 while (next)
139 OptionsSection *section = (OptionsSection *) next->data;
141 group = gtk_frame_new(_(section->name));
142 gtk_box_pack_start(GTK_BOX(sections_vbox), group,
143 FALSE, TRUE, 4);
144 gtk_container_add(GTK_CONTAINER(group),
145 section->create());
146 next = next->next;
149 need_init = FALSE;
152 path = choices_find_path_load("options", PROJECT);
153 if (!path)
154 return; /* Nothing to load */
156 parse_file(path, process_option_line);
160 /* Call this on init to register a handler for a key (thing before the = in
161 * the config file).
162 * The function returns a pointer to an error messages (which will
163 * NOT be free()d), or NULL on success.
165 void option_register(char *key, OptionFunc *func)
167 if (!option_hash)
168 option_hash = g_hash_table_new(g_str_hash, g_str_equal);
169 g_hash_table_insert(option_hash, key, func);
172 /* Process one line from the options file (\0 term'd).
173 * Returns NULL on success, or a pointer to an error message.
174 * The line is modified.
176 static char *process_option_line(guchar *line)
178 guchar *eq, *c;
179 OptionFunc *func;
181 g_return_val_if_fail(option_hash != NULL, "No registered functions!");
183 eq = strchr(line, '=');
184 if (!eq)
185 return _("Missing '='");
187 c = eq - 1;
188 while (c > line && (*c == ' ' || *c == '\t'))
189 c--;
190 c[1] = '\0';
191 c = eq + 1;
192 while (*c == ' ' || *c == '\t')
193 c++;
195 func = (OptionFunc *) g_hash_table_lookup(option_hash, line);
196 if (!func)
197 return _("Unknown option");
199 return func(c);
202 static void save_options(GtkWidget *widget, gpointer data)
204 int button = (int) data;
205 GSList *next = options_sections;
207 while (next)
209 OptionsSection *section = (OptionsSection *) next->data;
210 section->set();
211 next = next->next;
214 if (button == BUTTON_SAVE)
216 char *path;
218 path = choices_find_path_save("options", PROJECT, TRUE);
219 g_return_if_fail(path != NULL);
221 save_file = fopen(path, "wb");
222 if (!save_file)
224 char *str;
225 str = g_strdup_printf(
226 _("Unable to open '%s' for writing: %s"),
227 path, g_strerror(errno));
228 report_error(PROJECT, str);
229 g_free(str);
230 return;
233 next = options_sections;
234 while (next)
236 OptionsSection *section = (OptionsSection *) next->data;
237 section->save();
238 next = next->next;
241 if (save_file && fclose(save_file) == EOF)
243 report_error(PROJECT, g_strerror(errno));
244 return;
248 if (button != BUTTON_APPLY)
249 gtk_widget_hide(window);
252 void options_show(void)
254 GSList *next = options_sections;
256 if (GTK_WIDGET_MAPPED(window))
257 gtk_widget_hide(window);
259 while (next)
261 OptionsSection *section = (OptionsSection *) next->data;
262 section->update();
263 next = next->next;
266 gtk_widget_show_all(window);
269 void option_write(char *name, char *value)
271 char *string;
272 int len;
274 if (!save_file)
275 return; /* Error already reported hopefully */
277 string = g_strconcat(name, " = ", value, "\n", NULL);
278 len = strlen(string);
279 if (fwrite(string, sizeof(char), len, save_file) < len)
281 delayed_error(_("Saving options"), g_strerror(errno));
282 fclose(save_file);
283 save_file = NULL;
285 g_free(string);