1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) Guilhem Bonnefille 2009 <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>
32 #include <gtk/gtkbuilder.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);
80 GObjectClass* parent_class = G_OBJECT_CLASS (klass);
82 object_class->finalize = vik_gobject_builder_finalize;
84 klass->new_object = vik_gobject_builder_new_object;
86 gobject_builder_signals[NEW_OBJECT] =
87 g_signal_new ("new-object",
88 G_OBJECT_CLASS_TYPE (klass),
90 G_STRUCT_OFFSET (VikGobjectBuilderClass, new_object),
92 g_cclosure_marshal_VOID__OBJECT,
97 /* Called for open tags <foo bar="baz"> */
99 _start_element (GMarkupParseContext *context,
100 const gchar *element_name,
101 const gchar **attribute_names,
102 const gchar **attribute_values,
106 if (strcmp(element_name, "object") == 0)
108 class_name = g_strdup(attribute_values[0]);
109 gtype = g_type_from_name (class_name);
111 if (strcmp(element_name, "property") == 0 && gtype != 0)
114 while (attribute_names[i] != NULL)
116 if (strcmp (attribute_names[i], "name") == 0)
118 g_free (property_name);
119 property_name = g_strdup (attribute_values[i]);
126 /* Called for close tags </foo> */
128 _end_element (GMarkupParseContext *context,
129 const gchar *element_name,
133 VikGobjectBuilder *self = VIK_GOBJECT_BUILDER (user_data);
134 gpointer object = NULL;
135 if (strcmp(element_name, "object") == 0 && gtype != 0)
137 object = g_object_newv(gtype, nb_parameters, parameters);
140 g_debug("VikGobjectBuilder: new GObject of type %s", g_type_name(gtype));
141 g_signal_emit ( G_OBJECT(self), gobject_builder_signals[NEW_OBJECT], 0, object );
142 g_object_unref (object);
146 for (i = 0 ; i < nb_parameters ; i++)
148 g_free (parameters[i].name);
149 g_value_unset (&(parameters[i].value));
156 if (strcmp(element_name, "property") == 0)
158 g_free (property_name);
159 property_name = NULL;
163 /* Called for character data */
164 /* text is not nul-terminated */
166 _text (GMarkupParseContext *context,
172 if (strcmp (g_markup_parse_context_get_element (context), "property") == 0)
175 gboolean found = FALSE;
176 if (gtype != 0 && property_name != NULL)
178 /* parameter value */
179 /* We have to retrieve the expected type of the value
180 * in order to do the correct transformation */
181 GObjectClass *oclass;
182 oclass = g_type_class_ref (gtype);
183 g_assert (oclass != NULL);
185 pspec = g_object_class_find_property (G_OBJECT_CLASS (oclass), property_name);
188 g_warning ("Unknown property: %s.%s", g_type_name (gtype), property_name);
191 gchar *value = g_strndup (text, text_len);
192 found = gtk_builder_value_from_string_type(NULL, pspec->value_type, value, &gvalue, NULL);
195 if (G_IS_VALUE (&gvalue) && found == TRUE)
197 /* store new parameter */
198 g_debug("VikGobjectBuilder: store new GParameter for %s: (%s)%s=%*s",
199 g_type_name(gtype), g_type_name(G_VALUE_TYPE(&gvalue)), property_name, text_len, text);
201 parameters = g_realloc(parameters, sizeof(GParameter)*nb_parameters);
203 parameters[nb_parameters-1].name = g_strdup(property_name);
204 /* parameter value */
205 parameters[nb_parameters-1].value = gvalue;
211 vik_gobject_builder_new (void)
213 return g_object_new (VIK_TYPE_GOBJECT_BUILDER, NULL);
217 vik_gobject_builder_parse (VikGobjectBuilder *self, const gchar *filename)
219 GMarkupParser xml_parser;
220 GMarkupParseContext *xml_context;
223 FILE *file = g_fopen (filename, "r");
225 /* TODO emit warning */
228 /* setup context parse (ie callbacks) */
229 xml_parser.start_element = &_start_element;
230 xml_parser.end_element = &_end_element;
231 xml_parser.text = &_text;
232 xml_parser.passthrough = NULL;
233 xml_parser.error = NULL;
235 xml_context = g_markup_parse_context_new(&xml_parser, 0, self, NULL);
239 while ((nb = fread (buff, sizeof(gchar), BUFSIZ, file)) > 0)
241 if (!g_markup_parse_context_parse(xml_context, buff, nb, &error))
242 printf("read_xml() : parsing error.\n");
245 if (!g_markup_parse_context_end_parse(xml_context, &error))
246 printf("read_xml() : errors occurred reading file.\n");
248 g_markup_parse_context_free(xml_context);