From 29ef9fe856a332fb9dc586bcddca8bc54bb4cdd0 Mon Sep 17 00:00:00 2001 From: "Ira W. Snyder" Date: Mon, 28 Jan 2008 15:13:06 -0800 Subject: [PATCH] [Controller] Add initial-windows property This adds the initial-windows property, which can be used to make Tilda start more than one window when the program is started. This is another frequent feature request. Note that there was a bad bug in tilda_controller_set_property(), which has been fixed. There was a bad cast to the self pointer at the very beginning of the function. --- tilda-config.c | 146 +++++++++++++++++++++++++++++++++++++-------- tilda-config.h | 5 +- tilda-controller.c | 48 +++++++++++++-- tilda-controller.h | 4 +- 4 files changed, 170 insertions(+), 33 deletions(-) diff --git a/tilda-config.c b/tilda-config.c index 8732793..6563312 100644 --- a/tilda-config.c +++ b/tilda-config.c @@ -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 -#include +#include "debug.h" +#include "translation.h" + +#include /* for GType */ +#include /* 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,105 @@ 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_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) { diff --git a/tilda-config.h b/tilda-config.h index ba12de6..d930dd1 100644 --- a/tilda-config.h +++ b/tilda-config.h @@ -1,6 +1,8 @@ #ifndef TILDA_CONFIG_H #define TILDA_CONFIG_H +#include "tilda-controller.h" +#include "tilda-window.h" #include "tilda-terminal.h" #include @@ -13,8 +15,9 @@ gboolean tilda_config_init (const gchar *filename); gboolean tilda_config_free (); /* API */ -gboolean tilda_terminal_set_property_from_config (TildaTerminal *self, const gchar *property); +gboolean tilda_controller_set_property_from_config (TildaController *self, const gchar *property); gboolean tilda_window_set_property_from_config (TildaWindow *self, const gchar *property); +gboolean tilda_terminal_set_property_from_config (TildaTerminal *self, const gchar *property); #endif /* TILDA_CONFIG_H */ diff --git a/tilda-controller.c b/tilda-controller.c index 613bedb..a3d6f67 100644 --- a/tilda-controller.c +++ b/tilda-controller.c @@ -1,4 +1,5 @@ #include "tilda.h" +#include "tilda-config.h" #include "tilda-controller.h" #include "tilda-controller-dbus-glue.h" #include "tilda-window.h" @@ -158,6 +159,10 @@ tilda_controller_quit (TildaController *self, GError **error) 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) @@ -168,6 +173,7 @@ tilda_controller_instance_init (GTypeInstance *instance, self->dispose_has_run = FALSE; self->windows = g_ptr_array_new (); + self->initial_windows = 1; } static void @@ -176,10 +182,17 @@ tilda_controller_set_property (GObject *object, 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); @@ -193,10 +206,16 @@ tilda_controller_get_property (GObject *object, 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); @@ -212,25 +231,31 @@ tilda_controller_constructor (GType type, 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; iinitial_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; } @@ -278,7 +303,7 @@ tilda_controller_finalize (GObject *obj) static void tilda_controller_class_init (gpointer g_class, - gpointer g_class_data) + gpointer g_class_data) { debug_enter (); @@ -295,6 +320,17 @@ tilda_controller_class_init (gpointer g_class, 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(), diff --git a/tilda-controller.h b/tilda-controller.h index 6645436..a0a5ff1 100644 --- a/tilda-controller.h +++ b/tilda-controller.h @@ -1,7 +1,7 @@ #ifndef TILDA_CONTROLLER_H #define TILDA_CONTROLLER_H -#include +#include #define TILDA_TYPE_CONTROLLER (tilda_controller_get_type ()) #define TILDA_CONTROLLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TILDA_TYPE_CONTROLLER, TildaController)) @@ -19,6 +19,8 @@ struct _TildaController { /* instance members */ GPtrArray *windows; + + gint initial_windows; }; struct _TildaControllerClass { -- 2.34.1