-#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,
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_malloc0(sizeof(GValue));
+ 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);
+ 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)
{
#include "tilda.h"
+#include "tilda-config.h"
#include "tilda-controller.h"
#include "tilda-controller-dbus-glue.h"
#include "tilda-window.h"
static GObjectClass *parent_class = NULL;
+enum tilda_controller_properties {
+ TILDA_CONTROLLER_INITIAL_WINDOWS = 1,
+};
+
static void
tilda_controller_instance_init (GTypeInstance *instance,
gpointer g_class)
self->dispose_has_run = FALSE;
self->windows = g_ptr_array_new ();
+ self->initial_windows = 1;
}
static void
const GValue *value,
GParamSpec *pspec)
{
- TildaController *self = (TildaController *) self;
+ debug_enter ();
+
+ TildaController *self = (TildaController *) object;
switch (property_id)
{
+ case TILDA_CONTROLLER_INITIAL_WINDOWS:
+ self->initial_windows = g_value_get_int (value);
+ debug_printf ("tilda controller initial windows: %d\n", self->initial_windows);
+ break;
+
default:
/* We don't have any other properties */
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
GValue *value,
GParamSpec *pspec)
{
+ debug_enter ();
+
TildaController *self = (TildaController *) object;
switch (property_id)
{
+ case TILDA_CONTROLLER_INITIAL_WINDOWS:
+ g_value_set_int (value, self->initial_windows);
+ break;
+
default:
/* We don't have any other properties */
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
debug_enter ();
GObject *obj;
- TildaControllerClass *klass;
TildaController *self;
+ gint i;
/* Invoke the parent constructor */
+ TildaControllerClass *klass;
klass = TILDA_CONTROLLER_CLASS (g_type_class_peek (TILDA_TYPE_CONTROLLER));
obj = parent_class->constructor (type,
n_construct_properties,
construct_properties);
+ g_print ("%s all set up\n", __func__);
/* The object is ready, and all constructor-time properties have been set.
* Have fun! */
self = TILDA_CONTROLLER(obj);
+ /* Set all of the properties from the config */
+ tilda_controller_set_property_from_config (self, "initial-windows");
+
+ /* Add initial windows */
+ for (i=0; i<self->initial_windows; ++i)
+ tilda_controller_add_window (self);
+
/* Register this object with DBus */
tilda_controller_dbus_register_object (self);
- /* Add a window -- FIXME: the number should be configurable */
- tilda_controller_add_window (self);
-
return obj;
}
static void
tilda_controller_class_init (gpointer g_class,
- gpointer g_class_data)
+ gpointer g_class_data)
{
debug_enter ();
parent_class = g_type_class_peek_parent (klass);
/* Add properties here */
+ pspec = g_param_spec_int ("initial-windows",
+ _("The number of windows that will be opened on startup"),
+ NULL,
+ 1,
+ 100, /* Sane Limit */
+ 1,
+ G_PARAM_READWRITE);
+
+ g_object_class_install_property (gobject_class,
+ TILDA_CONTROLLER_INITIAL_WINDOWS,
+ pspec);
/* Hook the TildaController type into DBus */
dbus_g_object_type_install_info (tilda_controller_get_type(),