1 /* GTK - The GIMP Toolkit
2 * gtkfilechoosersettings.c: Internal settings for the GtkFileChooser widget
3 * Copyright (C) 2006, Novell, Inc.
5 * Authors: Federico Mena-Quintero <federico@novell.com>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
27 * - browse_for_other_folders?
29 * - Do we want lockdown?
35 #include <glib/gi18n-lib.h>
36 #include "gtkfilechoosersettings.h"
39 /* Increment this every time you change the configuration format */
40 #define CONFIG_VERSION 0
42 #define ELEMENT_TOPLEVEL "gtkfilechooser"
43 #define ELEMENT_LOCATION "location"
44 #define ELEMENT_SHOW_HIDDEN "show_hidden"
45 #define ATTRIBUTE_VERSION "version"
46 #define ATTRIBUTE_MODE "mode"
47 #define ATTRIBUTE_VALUE "value"
48 #define MODE_PATH_BAR "path-bar"
49 #define MODE_FILENAME_ENTRY "filename-entry"
50 #define VALUE_TRUE "true"
51 #define VALUE_FALSE "false"
53 #define EQ(a, b) (g_ascii_strcasecmp ((a), (b)) == 0)
56 get_config_dirname (void)
58 return g_build_filename (g_get_user_config_dir (), "gtk-2.0", NULL);
62 get_config_filename (void)
64 return g_build_filename (g_get_user_config_dir (), "gtk-2.0", "gtkfilechooser", NULL);
68 set_defaults (GtkFileChooserSettings *settings)
70 settings->location_mode = LOCATION_MODE_PATH_BAR;
71 settings->show_hidden = FALSE;
84 GtkFileChooserSettings *settings;
90 get_attribute_value (const char **attribute_names,
91 const char **attribute_values,
92 const char *attribute)
97 name = attribute_names;
98 value = attribute_values;
102 if (EQ (*name, attribute))
113 set_missing_attribute_error (struct parse_state *state,
116 const char *attribute,
119 state->state = STATE_ERROR;
122 G_MARKUP_ERROR_INVALID_CONTENT,
123 _("Line %d, column %d: missing attribute \"%s\""),
130 set_unexpected_element_error (struct parse_state *state,
136 state->state = STATE_ERROR;
139 G_MARKUP_ERROR_UNKNOWN_ELEMENT,
140 _("Line %d, column %d: unexpected element \"%s\""),
147 set_unexpected_element_end_error (struct parse_state *state,
150 const char *expected_element,
151 const char *unexpected_element,
154 state->state = STATE_ERROR;
157 G_MARKUP_ERROR_UNKNOWN_ELEMENT,
158 _("Line %d, column %d: expected end of element \"%s\", but found end for element \"%s\" instead"),
167 parse_start_element_cb (GMarkupParseContext *context,
168 const char *element_name,
169 const char **attribute_names,
170 const char **attribute_values,
174 struct parse_state *state;
178 g_markup_parse_context_get_position (context, &line, &col);
180 switch (state->state)
183 if (EQ (element_name, ELEMENT_TOPLEVEL))
185 const char *version_str;
187 state->state = STATE_IN_TOPLEVEL;
189 version_str = get_attribute_value (attribute_names, attribute_values, ATTRIBUTE_VERSION);
193 if (sscanf (version_str, "%d", &state->version) != 1 || state->version < 0)
198 state->state = STATE_ERROR;
201 G_MARKUP_ERROR_UNKNOWN_ELEMENT,
202 _("Line %d, column %d: expected \"%s\" at the toplevel, but found \"%s\" instead"),
211 g_assert_not_reached ();
215 g_assert_not_reached ();
218 case STATE_IN_TOPLEVEL:
219 if (EQ (element_name, ELEMENT_LOCATION))
221 const char *location_mode_str;
223 state->state = STATE_IN_LOCATION;
225 location_mode_str = get_attribute_value (attribute_names, attribute_values, ATTRIBUTE_MODE);
226 if (!location_mode_str)
227 set_missing_attribute_error (state, line, col, ATTRIBUTE_MODE, error);
228 else if (EQ (location_mode_str, MODE_PATH_BAR))
229 state->settings->location_mode = LOCATION_MODE_PATH_BAR;
230 else if (EQ (location_mode_str, MODE_FILENAME_ENTRY))
231 state->settings->location_mode = LOCATION_MODE_FILENAME_ENTRY;
234 state->state = STATE_ERROR;
237 G_MARKUP_ERROR_INVALID_CONTENT,
238 _("Line %d, column %d: expected \"%s\" or \"%s\", but found \"%s\" instead"),
246 else if (EQ (element_name, ELEMENT_SHOW_HIDDEN))
248 const char *value_str;
250 state->state = STATE_IN_SHOW_HIDDEN;
252 value_str = get_attribute_value (attribute_names, attribute_values, ATTRIBUTE_VALUE);
255 set_missing_attribute_error (state, line, col, ATTRIBUTE_VALUE, error);
256 else if (EQ (value_str, VALUE_TRUE))
257 state->settings->show_hidden = TRUE;
258 else if (EQ (value_str, VALUE_FALSE))
259 state->settings->show_hidden = FALSE;
262 state->state = STATE_ERROR;
265 G_MARKUP_ERROR_INVALID_CONTENT,
266 _("Line %d, column %d: expected \"%s\" or \"%s\", but found \"%s\" instead"),
275 set_unexpected_element_error (state, line, col, element_name, error);
279 case STATE_IN_LOCATION:
280 case STATE_IN_SHOW_HIDDEN:
281 set_unexpected_element_error (state, line, col, element_name, error);
285 g_assert_not_reached ();
290 parse_end_element_cb (GMarkupParseContext *context,
291 const char *element_name,
295 struct parse_state *state;
299 g_markup_parse_context_get_position (context, &line, &col);
301 switch (state->state)
304 g_assert_not_reached ();
308 g_assert_not_reached ();
312 g_assert_not_reached ();
315 case STATE_IN_TOPLEVEL:
316 if (EQ (element_name, ELEMENT_TOPLEVEL))
317 state->state = STATE_END;
319 set_unexpected_element_end_error (state, line, col, ELEMENT_TOPLEVEL, element_name, error);
323 case STATE_IN_LOCATION:
324 if (EQ (element_name, ELEMENT_LOCATION))
325 state->state = STATE_IN_TOPLEVEL;
327 set_unexpected_element_end_error (state, line, col, ELEMENT_LOCATION, element_name, error);
331 case STATE_IN_SHOW_HIDDEN:
332 if (EQ (element_name, ELEMENT_SHOW_HIDDEN))
333 state->state = STATE_IN_TOPLEVEL;
335 set_unexpected_element_end_error (state, line, col, ELEMENT_SHOW_HIDDEN, element_name, error);
340 g_assert_not_reached ();
345 parse_config (GtkFileChooserSettings *settings,
346 const char *contents,
349 GMarkupParser parser = { 0, };
350 GMarkupParseContext *context;
351 struct parse_state state;
354 parser.start_element = parse_start_element_cb;
355 parser.end_element = parse_end_element_cb;
357 state.settings = settings;
359 state.state = STATE_START;
361 context = g_markup_parse_context_new (&parser,
366 retval = g_markup_parse_context_parse (context, contents, -1, error);
367 g_markup_parse_context_free (context);
373 read_config (GtkFileChooserSettings *settings,
381 filename = get_config_filename ();
383 success = g_file_get_contents (filename, &contents, &contents_len, error);
388 set_defaults (settings);
392 success = parse_config (settings, contents, error);
400 ensure_settings_read (GtkFileChooserSettings *settings)
402 if (settings->settings_read)
406 read_config (settings, NULL);
408 settings->settings_read = TRUE;
411 G_DEFINE_TYPE (GtkFileChooserSettings, _gtk_file_chooser_settings, G_TYPE_OBJECT)
414 _gtk_file_chooser_settings_class_init (GtkFileChooserSettingsClass *class)
419 _gtk_file_chooser_settings_init (GtkFileChooserSettings *settings)
423 GtkFileChooserSettings *
424 _gtk_file_chooser_settings_new (void)
426 return g_object_new (GTK_FILE_CHOOSER_SETTINGS_TYPE, NULL);
430 _gtk_file_chooser_settings_get_location_mode (GtkFileChooserSettings *settings)
432 ensure_settings_read (settings);
433 return settings->location_mode;
437 _gtk_file_chooser_settings_set_location_mode (GtkFileChooserSettings *settings,
438 LocationMode location_mode)
440 settings->location_mode = location_mode;
444 _gtk_file_chooser_settings_get_show_hidden (GtkFileChooserSettings *settings)
446 ensure_settings_read (settings);
447 return settings->show_hidden;
451 _gtk_file_chooser_settings_set_show_hidden (GtkFileChooserSettings *settings,
452 gboolean show_hidden)
454 settings->show_hidden = show_hidden ? TRUE : FALSE;
458 settings_to_markup (GtkFileChooserSettings *settings)
460 const char *location_mode_str;
461 const char *show_hidden_str;
463 if (settings->location_mode == LOCATION_MODE_PATH_BAR)
464 location_mode_str = MODE_PATH_BAR;
465 else if (settings->location_mode == LOCATION_MODE_FILENAME_ENTRY)
466 location_mode_str = MODE_FILENAME_ENTRY;
469 g_assert_not_reached ();
473 show_hidden_str = settings->show_hidden ? VALUE_TRUE : VALUE_FALSE;
475 return g_strdup_printf
476 ("<" ELEMENT_TOPLEVEL ">\n" /* <gtkfilechooser> */
477 " <" ELEMENT_LOCATION " " ATTRIBUTE_MODE "=\"%s\"/>\n" /* <location mode="path-bar"/> */
478 " <" ELEMENT_SHOW_HIDDEN " " ATTRIBUTE_VALUE "=\"%s\"/>\n" /* <show_hidden value="false"/> */
479 "</" ELEMENT_TOPLEVEL ">\n", /* </gtkfilechooser> */
485 _gtk_file_chooser_settings_save (GtkFileChooserSettings *settings,
493 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
495 contents = settings_to_markup (settings);
497 filename = get_config_filename ();
502 if (!g_file_set_contents (filename, contents, -1, NULL))
507 /* Directory is not there? */
509 dirname = get_config_dirname ();
510 if (g_mkdir_with_parents (dirname, 0700) != 0) /* 0700 per the XDG basedir spec */
515 g_file_error_from_errno (saved_errno),
516 _("Could not create directory: %s"),
521 if (!g_file_set_contents (filename, contents, -1, error))