Add README
[tilda-gobject.git] / tilda-config.c
index 8732793..54a3d50 100644 (file)
@@ -1,43 +1,40 @@
-#include "debug.h"
-#include "translation.h"
 #include "tilda-config.h"
 
 #include "tilda.h"
 #include "tilda-types.h"
-#include "tilda-window.h"
-#include "tilda-terminal.h"
-#include <glib-object.h>
-#include <stdlib.h>
+#include "debug.h"
+#include "translation.h"
+
+#include <glib-object.h> /* for GType */
+#include <stdlib.h> /* for exit() */
 
 GKeyFile *config_defaults = NULL;
 GKeyFile *config_userprefs = NULL;
 
 /*
  * TODO:
- *
- * Add some capability to version the config file. Maybe a [meta] section.
- *
- * Make it possible to get the version number without firing up the config system
- * as a whole. Or maybe just add the migration here, in this file, upon startup.
- *
- * The whole idea of this is that each of the objects that accesses the config
- * system implements their own lookup engine.
- */
-
-/*
- * The main idea behind this configuration system is that each of the objects
- * that accesses the config system implements their own lookup scheme. Since
- * both TildaWindow and TildaTerminal need to lookup things different ways,
- * I thought this would be the most logical solution.
+ * 1) Configuration forward-migration, automatically, on startup.
  */
 
-/* NOTE NOTE NOTE:
- * This essentially works. You still need to feasibility-test it to make sure that
- * everything pulls out of the gkeyfile ok. And you need to add the lookup code.
+/* The main idea behind this configuration system is that each type of GObject
+ * that needs to use the system implements its own lookup scheme. I tried to
+ * do this as generically as possible, by using just the GObject property names,
+ * and then looking up their type and using that to use the correct parsing
+ * function.
  *
- * Other than that, this is a mostly generic version :) !!!
+ * It is basically function overloading (for example, from C++) but done in C.
+ * Rather complicated, if you ask me. Also a complete pain. But the result
+ * sure is nice.
  */
 
+static gchar *
+tilda_config_lookup_version (GKeyFile *keyfile, GError **error)
+{
+       debug_enter  ();
+
+       return g_key_file_get_string (keyfile, "Meta", "version", error);
+}
+
 static gboolean
 tilda_config_parse_integer (GKeyFile    *keyfile,
                                                        const gchar *group_name,
@@ -183,6 +180,106 @@ tilda_config_parse_enum (GKeyFile    *keyfile,
        return TRUE;
 }
 
+gboolean
+tilda_controller_set_property_from_config (TildaController *self, const gchar *property)
+{
+       debug_enter  ();
+       debug_assert (TILDA_IS_CONTROLLER(self));
+
+       GError *error = NULL;
+       gboolean ret;
+
+       GParamSpec *pspec;
+       GValue *value = g_new0 (GValue, 1);
+       gboolean (*parse_func) (GKeyFile *keyfile, const gchar *group_name, const gchar *key, GValue *value, GError **error);
+
+       /* Get the pspec for this property */
+       pspec = g_object_class_find_property (G_OBJECT_GET_CLASS(self), property);
+
+       /* Make sure that this property exists */
+       if (pspec == NULL)
+       {
+               g_critical ("FIXME: developer error -- unable to find property: %s\n", property);
+               exit (1);
+       }
+
+       /* Initialize the GValue that is going to hold the returned value */
+       g_value_init (value, pspec->value_type);
+
+       /* Set the correct function to do the parsing */
+       if      (g_type_is_a (pspec->value_type, G_TYPE_INT))
+               parse_func = tilda_config_parse_integer;
+       else if (g_type_is_a (pspec->value_type, G_TYPE_BOOLEAN))
+               parse_func = tilda_config_parse_boolean;
+       else if (g_type_is_a (pspec->value_type, G_TYPE_STRING))
+               parse_func = tilda_config_parse_string;
+       else if (g_type_is_a (pspec->value_type, G_TYPE_ENUM))
+               parse_func = tilda_config_parse_enum;
+       else
+       {
+               g_critical ("FIXME: developer error -- unknown property type: %s\n", g_type_name(pspec->value_type));
+               exit(1);
+       }
+
+       /* Do the [Controller] lookup */
+       ret = parse_func (config_userprefs, "Controller", property, value, &error);
+
+       if (error)
+       {
+               if (error->code == G_KEY_FILE_ERROR_INVALID_VALUE)
+                       g_warning (error->message);
+
+               g_clear_error (&error);
+       }
+       else
+               goto success;
+
+       /* Do the [Global] lookup */
+       ret = parse_func (config_userprefs, "Global", property, value, &error);
+
+       if (error)
+       {
+               if (error->code == G_KEY_FILE_ERROR_INVALID_VALUE)
+                       g_warning (error->message);
+
+               g_clear_error (&error);
+       }
+       else
+               goto success;
+
+       /* Do the [controller-defaults] lookup */
+       ret = parse_func (config_defaults, "controller-defaults", property, value, &error);
+
+       if (error)
+       {
+               if (error->code == G_KEY_FILE_ERROR_INVALID_VALUE)
+                       g_warning (error->message);
+
+               g_clear_error (&error);
+
+               /* This is somewhat of a nasty hack, but I really do want to just set the property to
+                * NULL if there is no default, but ONLY for strings. */
+               if (parse_func == tilda_config_parse_string)
+               {
+                       g_value_set_string (value, NULL);
+                       goto success;
+               }
+       }
+       else
+               goto success;
+
+//failure:
+       g_critical (_("Unable to find a value for controller property: %s\n"), property);
+       g_free (value);
+       return FALSE;
+
+success:
+       g_object_set_property (G_OBJECT(self), property, value);
+       g_value_unset (value);
+       g_free (value);
+       return TRUE;
+}
+
 gboolean
 tilda_window_set_property_from_config (TildaWindow *self, const gchar *property)
 {
@@ -194,7 +291,7 @@ tilda_window_set_property_from_config (TildaWindow *self, const gchar *property)
        gboolean ret;
 
        GParamSpec *pspec;
-       GValue *value = g_malloc0(sizeof(GValue));
+       GValue *value = g_new0(GValue, 1);
        gboolean (*parse_func) (GKeyFile *keyfile, const gchar *group_name, const gchar *key, GValue *value, GError **error);
 
        /* Get the pspec for this property */
@@ -276,6 +373,7 @@ tilda_window_set_property_from_config (TildaWindow *self, const gchar *property)
 
 //failure:
        g_critical (_("Unable to find a value for window property: %s\n"), property);
+       g_free (value);
        return FALSE;
 
 success:
@@ -297,7 +395,7 @@ tilda_terminal_set_property_from_config (TildaTerminal *self, const gchar *prope
        gboolean ret;
 
        GParamSpec *pspec;
-       GValue *value = g_malloc0(sizeof(GValue));
+       GValue *value = g_new0 (GValue, 1);
        gboolean (*parse_func) (GKeyFile *keyfile, const gchar *group_name, const gchar *key, GValue *value, GError **error);
 
        /* Get the pspec for this property */
@@ -394,6 +492,7 @@ tilda_terminal_set_property_from_config (TildaTerminal *self, const gchar *prope
 
 //failure:
        g_critical (_("Unable to find a value for terminal property: %s\n"), property);
+       g_free (value);
        return FALSE;
 
 success: