2 #include "translation.h"
3 #include "tilda-config.h"
6 #include "tilda-types.h"
7 #include "tilda-window.h"
8 #include "tilda-terminal.h"
9 #include <glib-object.h>
12 GKeyFile *config_defaults = NULL;
13 GKeyFile *config_userprefs = NULL;
18 * Add some capability to version the config file. Maybe a [meta] section.
20 * Make it possible to get the version number without firing up the config system
21 * as a whole. Or maybe just add the migration here, in this file, upon startup.
23 * The whole idea of this is that each of the objects that accesses the config
24 * system implements their own lookup engine.
28 * The main idea behind this configuration system is that each of the objects
29 * that accesses the config system implements their own lookup scheme. Since
30 * both TildaWindow and TildaTerminal need to lookup things different ways,
31 * I thought this would be the most logical solution.
35 * This essentially works. You still need to feasibility-test it to make sure that
36 * everything pulls out of the gkeyfile ok. And you need to add the lookup code.
38 * Other than that, this is a mostly generic version :) !!!
42 tilda_config_parse_integer (GKeyFile *keyfile,
43 const gchar *group_name,
49 debug_assert (G_IS_VALUE(value));
54 /* Try to get the value */
55 ret = g_key_file_get_integer (keyfile, group_name, key, &error);
60 g_propagate_error (user_error, error);
64 /* We successfully parsed the int, so set it in the GValue */
65 g_value_set_int (value, ret);
71 tilda_config_parse_boolean (GKeyFile *keyfile,
72 const gchar *group_name,
78 debug_assert (G_IS_VALUE(value));
83 /* Try to get the value */
84 ret = g_key_file_get_boolean (keyfile, group_name, key, &error);
89 g_propagate_error (user_error, error);
94 g_value_set_boolean (value, ret);
100 tilda_config_parse_string (GKeyFile *keyfile,
101 const gchar *group_name,
107 debug_assert (G_IS_VALUE(value));
109 GError *error = NULL;
112 /* Try to get the value */
113 ret = g_key_file_get_string (keyfile, group_name, key, &error);
115 /* Check for error */
118 g_propagate_error (user_error, error);
123 g_value_set_string (value, ret);
128 #define key_is(STR) (g_ascii_strcasecmp(key,(STR)) == 0)
131 tilda_config_parse_enum (GKeyFile *keyfile,
132 const gchar *group_name,
138 GError *error = NULL;
139 GEnumClass *enum_class;
140 GEnumValue *enum_value;
142 if (key_is("backspace-binding") || key_is("delete-binding"))
143 enum_class = g_type_class_peek (vte_terminal_erase_binding_get_type());
144 else if (key_is("dynamic-title"))
145 enum_class = g_type_class_peek (tilda_dynamic_title_get_type());
146 else if (key_is("exit-action"))
147 enum_class = g_type_class_peek (tilda_child_exit_action_get_type());
148 else if (key_is("scrollbar-position"))
149 enum_class = g_type_class_peek (tilda_scrollbar_position_get_type());
150 else if (key_is("animation-orientation") || key_is("tab-position"))
151 enum_class = g_type_class_peek (gtk_position_type_get_type());
154 g_critical ("FIXME: developer error -- unknown enum key used: %s\n", key);
159 /* Get the value from the config as a string */
160 ret = g_key_file_get_string (keyfile, group_name, key, &error);
164 g_propagate_error (user_error, error);
168 enum_value = g_enum_get_value_by_nick (enum_class, ret);
172 /* This is exactly the same error that is returned by g_key_file_get_integer()
173 * when it cannot correctly parse the value. */
174 g_set_error (user_error,
176 G_KEY_FILE_ERROR_INVALID_VALUE,
177 _("Key file contains key '%s' in group '%s' which has value that cannot be interpreted."), key, group_name);
181 /* All was successful, let's set it */
182 g_value_set_enum (value, enum_value->value);
187 tilda_window_set_property_from_config (TildaWindow *self, const gchar *property)
190 debug_assert (TILDA_IS_WINDOW(self));
193 GError *error = NULL;
197 GValue *value = g_malloc0(sizeof(GValue));
198 gboolean (*parse_func) (GKeyFile *keyfile, const gchar *group_name, const gchar *key, GValue *value, GError **error);
200 /* Get the pspec for this property */
201 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS(self), property);
203 /* Make sure that this property exists */
206 g_critical ("FIXME: developer error -- unable to find property: %s\n", property);
210 /* Initialize the GValue that is going to hold the returned value */
211 g_value_init (value, pspec->value_type);
213 /* Set the correct function to do the parsing */
214 if (g_type_is_a (pspec->value_type, G_TYPE_INT))
215 parse_func = tilda_config_parse_integer;
216 else if (g_type_is_a (pspec->value_type, G_TYPE_BOOLEAN))
217 parse_func = tilda_config_parse_boolean;
218 else if (g_type_is_a (pspec->value_type, G_TYPE_STRING))
219 parse_func = tilda_config_parse_string;
220 else if (g_type_is_a (pspec->value_type, G_TYPE_ENUM))
221 parse_func = tilda_config_parse_enum;
224 g_critical ("FIXME: developer error -- unknown property type: %s\n", g_type_name(pspec->value_type));
228 /* Do the [Window] lookup */
229 group_name = g_strdup_printf ("Window%d", self->number);
230 ret = parse_func (config_userprefs, group_name, property, value, &error);
235 if (error->code == G_KEY_FILE_ERROR_INVALID_VALUE)
236 g_warning (error->message);
238 g_clear_error (&error);
243 /* Do the [Global] lookup */
244 ret = parse_func (config_userprefs, "Global", property, value, &error);
248 if (error->code == G_KEY_FILE_ERROR_INVALID_VALUE)
249 g_warning (error->message);
251 g_clear_error (&error);
256 /* Do the [window-defaults] lookup */
257 ret = parse_func (config_defaults, "window-defaults", property, value, &error);
261 if (error->code == G_KEY_FILE_ERROR_INVALID_VALUE)
262 g_warning (error->message);
264 g_clear_error (&error);
266 /* This is somewhat of a nasty hack, but I really do want to just set the property to
267 * NULL if there is no default, but ONLY for strings. */
268 if (parse_func == tilda_config_parse_string)
270 g_value_set_string (value, NULL);
278 g_critical (_("Unable to find a value for window property: %s\n"), property);
282 g_object_set_property (G_OBJECT(self), property, value);
283 g_value_unset (value);
289 tilda_terminal_set_property_from_config (TildaTerminal *self, const gchar *property)
292 debug_assert (TILDA_IS_TERMINAL(self));
294 TildaWindow *parent_window = TILDA_WINDOW(self->parent_window);
296 GError *error = NULL;
300 GValue *value = g_malloc0(sizeof(GValue));
301 gboolean (*parse_func) (GKeyFile *keyfile, const gchar *group_name, const gchar *key, GValue *value, GError **error);
303 /* Get the pspec for this property */
304 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS(self), property);
306 /* Make sure that this property exists */
309 g_critical ("FIXME: developer error -- unable to find property: %s\n", property);
313 /* Initialize the GValue that is going to hold the returned value */
314 g_value_init (value, pspec->value_type);
316 /* Set the correct function to do the parsing */
317 if (g_type_is_a (pspec->value_type, G_TYPE_INT))
318 parse_func = tilda_config_parse_integer;
319 else if (g_type_is_a (pspec->value_type, G_TYPE_BOOLEAN))
320 parse_func = tilda_config_parse_boolean;
321 else if (g_type_is_a (pspec->value_type, G_TYPE_STRING))
322 parse_func = tilda_config_parse_string;
323 else if (g_type_is_a (pspec->value_type, G_TYPE_ENUM))
324 parse_func = tilda_config_parse_enum;
327 g_critical ("FIXME: developer error -- unknown property type: %s\n", g_type_name(pspec->value_type));
331 /* Do the [Window/Terminal] lookup */
332 group_name = g_strdup_printf ("Window%d/Terminal%d", parent_window->number, self->number);
333 ret = parse_func (config_userprefs, group_name, property, value, &error);
338 if (error->code == G_KEY_FILE_ERROR_INVALID_VALUE)
339 g_warning (error->message);
341 g_clear_error (&error);
346 /* Do the [Window] lookup */
347 group_name = g_strdup_printf ("Window%d", parent_window->number);
348 ret = parse_func (config_userprefs, group_name, property, value, &error);
353 if (error->code == G_KEY_FILE_ERROR_INVALID_VALUE)
354 g_warning (error->message);
356 g_clear_error (&error);
361 /* Do the [Global] lookup */
362 ret = parse_func (config_userprefs, "Global", property, value, &error);
366 if (error->code == G_KEY_FILE_ERROR_INVALID_VALUE)
367 g_warning (error->message);
369 g_clear_error (&error);
374 /* Do the [terminal-defaults] lookup */
375 ret = parse_func (config_defaults, "terminal-defaults", property, value, &error);
379 if (error->code == G_KEY_FILE_ERROR_INVALID_VALUE)
380 g_warning (error->message);
382 g_clear_error (&error);
384 /* This is somewhat of a nasty hack, but I really do want to just set the property to
385 * NULL if there is no default, but ONLY for strings. */
386 if (parse_func == tilda_config_parse_string)
388 g_value_set_string (value, NULL);
396 g_critical (_("Unable to find a value for terminal property: %s\n"), property);
400 g_object_set_property (G_OBJECT(self), property, value);
401 g_value_unset (value);
407 tilda_config_init (const gchar *userprefs_filename)
409 gchar *defaults_filename;
410 GError *error = NULL;
412 /* Call g_type_class_ref() on all enum types that are being used */
413 g_type_class_ref (vte_terminal_erase_binding_get_type());
414 g_type_class_ref (tilda_dynamic_title_get_type());
415 g_type_class_ref (tilda_child_exit_action_get_type());
416 g_type_class_ref (tilda_scrollbar_position_get_type());
417 g_type_class_ref (gtk_position_type_get_type());
419 /* Create the defaults file's path */
420 defaults_filename = g_build_filename ("share-tilda.conf", NULL); // FIXME: use /usr/share/tilda
422 /* Create the keyfiles */
423 config_defaults = g_key_file_new ();
424 config_userprefs = g_key_file_new ();
426 /* Check if the defaults exist, and load them */
427 if (!g_file_test (defaults_filename, G_FILE_TEST_EXISTS))
429 g_critical (_("No configuration defaults file found. Tilda may not work.\n"));
433 if (!g_key_file_load_from_file (config_defaults, defaults_filename, G_KEY_FILE_NONE, &error))
435 g_critical (_("Error reading configuration defaults: %s\n"), error->message);
436 g_clear_error (&error);
440 /* Check if the user's config exists, and load it */
441 if (!g_file_test (userprefs_filename, G_FILE_TEST_EXISTS))
443 g_warning (_("No user configuration file found, using defaults\n"));
447 if (!g_key_file_load_from_file (config_userprefs, userprefs_filename, G_KEY_FILE_NONE, &error))
449 g_warning (_("Error reading user configuration: %s\n"), error->message);
450 g_clear_error (&error);
454 /* This is just here for the future. Currently, it is acceptable to run without
455 * a configuration, though Tilda may not work very well. */
460 * Since we DO NOT allow writing to the configuration file from a Tilda
461 * process (only from the wizard), this does nothing more than free the
462 * defaults hashtable, and free the opened keyfile.
467 /* Since we never write the config file from within Tilda,
468 * we can just close the files. */
469 g_key_file_free (config_defaults);
470 g_key_file_free (config_userprefs);
472 config_defaults = NULL;
473 config_userprefs = NULL;
478 /* vim: set ts=4 sts=4 sw=4 noet tw=112: */