]> git.street.me.uk Git - andy/viking.git/blame - src/vikgobjectbuilder.c
Remove OpenAerial
[andy/viking.git] / src / vikgobjectbuilder.c
CommitLineData
7bc5a5a9
GB
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2/*
3 * viking
4 * Copyright (C) Guilhem Bonnefille 2009 <guilhem.bonnefille@gmail.com>
5 *
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.
10 *
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.
15 *
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/>.
18 */
19
20#ifdef HAVE_CONFIG_H
21#include "config.h"
22#endif
23
24#include <stdio.h>
25#ifdef HAVE_STRING_H
26#include <string.h>
27#endif
28
29#include <glib.h>
30#include <glib/gstdio.h>
31
32#include <gtk/gtkbuilder.h>
33
34#include "vikgobjectbuilder.h"
35
36/* FIXME use private fields */
37static gchar *class_name = NULL;
38GType gtype = 0;
39gchar *property_name = NULL;
40GParameter *parameters = NULL;
41gint nb_parameters = 0;
42
43/* signals */
44enum
45{
46 NEW_OBJECT,
47
48 LAST_SIGNAL
49};
50
51
52static guint gobject_builder_signals[LAST_SIGNAL] = { 0 };
53
54G_DEFINE_TYPE (VikGobjectBuilder, vik_gobject_builder, G_TYPE_OBJECT);
55
56static void
57vik_gobject_builder_init (VikGobjectBuilder *object)
58{
59 /* TODO: Add initialization code here */
60}
61
62static void
63vik_gobject_builder_finalize (GObject *object)
64{
65 /* TODO: Add deinitalization code here */
66
67 G_OBJECT_CLASS (vik_gobject_builder_parent_class)->finalize (object);
68}
69
70static void
71vik_gobject_builder_new_object (VikGobjectBuilder *self, GObject *object)
72{
73 /* TODO: Add default signal handler implementation here */
74}
75
76static void
77vik_gobject_builder_class_init (VikGobjectBuilderClass *klass)
78{
79 GObjectClass* object_class = G_OBJECT_CLASS (klass);
80 GObjectClass* parent_class = G_OBJECT_CLASS (klass);
81
82 object_class->finalize = vik_gobject_builder_finalize;
83
84 klass->new_object = vik_gobject_builder_new_object;
85
86 gobject_builder_signals[NEW_OBJECT] =
87 g_signal_new ("new-object",
88 G_OBJECT_CLASS_TYPE (klass),
89 0,
90 G_STRUCT_OFFSET (VikGobjectBuilderClass, new_object),
91 NULL, NULL,
92 g_cclosure_marshal_VOID__OBJECT,
93 G_TYPE_NONE, 1,
94 G_TYPE_OBJECT);
95}
96
97/* Called for open tags <foo bar="baz"> */
98static void
99_start_element (GMarkupParseContext *context,
100 const gchar *element_name,
101 const gchar **attribute_names,
102 const gchar **attribute_values,
103 gpointer user_data,
104 GError **error)
105{
106 if (strcmp(element_name, "object") == 0)
107 {
108 class_name = g_strdup(attribute_values[0]);
109 gtype = g_type_from_name (class_name);
110 }
111 if (strcmp(element_name, "property") == 0 && gtype != 0)
112 {
113 int i=0;
114 while (attribute_names[i] != NULL)
115 {
116 if (strcmp (attribute_names[i], "name") == 0)
117 {
118 g_free (property_name);
119 property_name = g_strdup (attribute_values[i]);
120 }
121 i++;
122 }
123 }
124}
125
126/* Called for close tags </foo> */
127static void
128_end_element (GMarkupParseContext *context,
129 const gchar *element_name,
130 gpointer user_data,
131 GError **error)
132{
133 VikGobjectBuilder *self = VIK_GOBJECT_BUILDER (user_data);
134 gpointer object = NULL;
135 if (strcmp(element_name, "object") == 0 && gtype != 0)
136 {
137 object = g_object_newv(gtype, nb_parameters, parameters);
138 if (object != NULL)
139 {
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);
143 }
144 /* Free memory */
145 int i = 0;
146 for (i = 0 ; i < nb_parameters ; i++)
147 {
148 g_free (parameters[i].name);
149 g_value_unset (&(parameters[i].value));
150 }
151 g_free (parameters);
152 parameters = NULL;
153 nb_parameters = 0;
154 gtype = 0;
155 }
156 if (strcmp(element_name, "property") == 0)
157 {
158 g_free (property_name);
159 property_name = NULL;
160 }
161}
162
163/* Called for character data */
164/* text is not nul-terminated */
165static void
166_text (GMarkupParseContext *context,
167 const gchar *text,
168 gsize text_len,
169 gpointer user_data,
170 GError **error)
171{
172 if (strcmp (g_markup_parse_context_get_element (context), "property") == 0)
173 {
174 GValue gvalue = {0};
175 gboolean found = FALSE;
176 if (gtype != 0 && property_name != NULL)
177 {
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);
184 GParamSpec *pspec;
185 pspec = g_object_class_find_property (G_OBJECT_CLASS (oclass), property_name);
186 if (!pspec)
187 {
188 g_warning ("Unknown property: %s.%s", g_type_name (gtype), property_name);
189 return;
190 }
191 gchar *value = g_strndup (text, text_len);
192 found = gtk_builder_value_from_string_type(NULL, pspec->value_type, value, &gvalue, NULL);
193 g_free (value);
194 }
195 if (G_IS_VALUE (&gvalue) && found == TRUE)
196 {
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);
200 nb_parameters++;
201 parameters = g_realloc(parameters, sizeof(GParameter)*nb_parameters);
202 /* parameter name */
203 parameters[nb_parameters-1].name = g_strdup(property_name);
204 /* parameter value */
205 parameters[nb_parameters-1].value = gvalue;
206 }
207 }
208}
209
210VikGobjectBuilder *
211vik_gobject_builder_new (void)
212{
213 return g_object_new (VIK_TYPE_GOBJECT_BUILDER, NULL);
214}
215
216void
217vik_gobject_builder_parse (VikGobjectBuilder *self, const gchar *filename)
218{
219 GMarkupParser xml_parser;
220 GMarkupParseContext *xml_context;
221 GError *error;
222
223 FILE *file = g_fopen (filename, "r");
224 if (file == NULL)
225 /* TODO emit warning */
226 return;
227
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;
234
235 xml_context = g_markup_parse_context_new(&xml_parser, 0, self, NULL);
236
237 gchar buff[BUFSIZ];
238 size_t nb;
239 while ((nb = fread (buff, sizeof(gchar), BUFSIZ, file)) > 0)
240 {
241 if (!g_markup_parse_context_parse(xml_context, buff, nb, &error))
242 printf("read_xml() : parsing error.\n");
243 }
244 /* cleanup */
245 if (!g_markup_parse_context_end_parse(xml_context, &error))
246 printf("read_xml() : errors occurred reading file.\n");
247
248 g_markup_parse_context_free(xml_context);
249 fclose (file);
250}