1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) 2009, Guilhem Bonnefille <guilhem.bonnefille@gmail.com>
6 * viking is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * viking is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
30 #include <glib/gstdio.h>
34 #include "vikgobjectbuilder.h"
36 /* FIXME use private fields */
37 static gchar *class_name = NULL;
39 gchar *property_name = NULL;
40 GParameter *parameters = NULL;
41 gint nb_parameters = 0;
52 static guint gobject_builder_signals[LAST_SIGNAL] = { 0 };
54 G_DEFINE_TYPE (VikGobjectBuilder, vik_gobject_builder, G_TYPE_OBJECT);
57 vik_gobject_builder_init (VikGobjectBuilder *object)
59 /* TODO: Add initialization code here */
63 vik_gobject_builder_finalize (GObject *object)
65 /* TODO: Add deinitalization code here */
67 G_OBJECT_CLASS (vik_gobject_builder_parent_class)->finalize (object);
71 vik_gobject_builder_new_object (VikGobjectBuilder *self, GObject *object)
73 /* TODO: Add default signal handler implementation here */
77 vik_gobject_builder_class_init (VikGobjectBuilderClass *klass)
79 GObjectClass* object_class = G_OBJECT_CLASS (klass);
81 object_class->finalize = vik_gobject_builder_finalize;
83 klass->new_object = vik_gobject_builder_new_object;
85 gobject_builder_signals[NEW_OBJECT] =
86 g_signal_new ("new-object",
87 G_OBJECT_CLASS_TYPE (klass),
89 G_STRUCT_OFFSET (VikGobjectBuilderClass, new_object),
91 g_cclosure_marshal_VOID__OBJECT,
96 /* Called for open tags <foo bar="baz"> */
98 _start_element (GMarkupParseContext *context,
99 const gchar *element_name,
100 const gchar **attribute_names,
101 const gchar **attribute_values,
105 if (strcmp(element_name, "object") == 0)
107 class_name = g_strdup(attribute_values[0]);
108 gtype = g_type_from_name (class_name);
111 g_warning("Unknown GObject type '%s'", class_name);
115 if (strcmp(element_name, "property") == 0 && gtype != 0)
118 while (attribute_names[i] != NULL)
120 if (strcmp (attribute_names[i], "name") == 0)
122 g_free (property_name);
123 property_name = g_strdup (attribute_values[i]);
130 /* Called for close tags </foo> */
132 _end_element (GMarkupParseContext *context,
133 const gchar *element_name,
137 VikGobjectBuilder *self = VIK_GOBJECT_BUILDER (user_data);
138 gpointer object = NULL;
139 if (strcmp(element_name, "object") == 0 && gtype != 0)
141 object = g_object_newv(gtype, nb_parameters, parameters);
144 g_debug("VikGobjectBuilder: new GObject of type %s", g_type_name(gtype));
145 g_signal_emit ( G_OBJECT(self), gobject_builder_signals[NEW_OBJECT], 0, object );
146 g_object_unref (object);
150 for (i = 0 ; i < nb_parameters ; i++)
152 g_free ((gchar *)parameters[i].name);
153 g_value_unset (&(parameters[i].value));
160 if (strcmp(element_name, "property") == 0)
162 g_free (property_name);
163 property_name = NULL;
167 /* Called for character data */
168 /* text is not nul-terminated */
170 _text (GMarkupParseContext *context,
176 if (strcmp (g_markup_parse_context_get_element (context), "property") == 0)
179 gboolean found = FALSE;
180 if (gtype != 0 && property_name != NULL)
182 /* parameter value */
183 /* We have to retrieve the expected type of the value
184 * in order to do the correct transformation */
185 GObjectClass *oclass;
186 oclass = g_type_class_ref (gtype);
187 g_assert (oclass != NULL);
189 pspec = g_object_class_find_property (G_OBJECT_CLASS (oclass), property_name);
192 g_warning ("Unknown property: %s.%s", g_type_name (gtype), property_name);
195 gchar *value = g_strndup (text, text_len);
196 found = gtk_builder_value_from_string_type(NULL, pspec->value_type, value, &gvalue, NULL);
199 if (G_IS_VALUE (&gvalue) && found == TRUE)
201 /* store new parameter */
202 g_debug("VikGobjectBuilder: store new GParameter for %s: (%s)%s=%*s",
203 g_type_name(gtype), g_type_name(G_VALUE_TYPE(&gvalue)), property_name, (gint)text_len, text);
205 parameters = g_realloc(parameters, sizeof(GParameter)*nb_parameters);
207 parameters[nb_parameters-1].name = g_strdup(property_name);
208 /* parameter value */
209 parameters[nb_parameters-1].value = gvalue;
215 vik_gobject_builder_new (void)
217 return g_object_new (VIK_TYPE_GOBJECT_BUILDER, NULL);
221 vik_gobject_builder_parse (VikGobjectBuilder *self, const gchar *filename)
223 GMarkupParser xml_parser;
224 GMarkupParseContext *xml_context;
225 GError *error = NULL;
227 FILE *file = g_fopen (filename, "r");
229 /* TODO emit warning */
232 /* setup context parse (ie callbacks) */
233 xml_parser.start_element = &_start_element;
234 xml_parser.end_element = &_end_element;
235 xml_parser.text = &_text;
236 xml_parser.passthrough = NULL;
237 xml_parser.error = NULL;
239 xml_context = g_markup_parse_context_new(&xml_parser, 0, self, NULL);
243 while ((nb = fread (buff, sizeof(gchar), BUFSIZ, file)) > 0)
245 if (!g_markup_parse_context_parse(xml_context, buff, nb, &error))
246 g_warning("%s: parsing error: %s", __FUNCTION__,
247 error != NULL ? error->message : "???");
250 if (!g_markup_parse_context_end_parse(xml_context, &error))
251 g_warning("%s: errors occurred reading file '%s': %s", __FUNCTION__, filename,
252 error != NULL ? error->message : "???");
254 g_markup_parse_context_free(xml_context);