]> git.street.me.uk Git - andy/viking.git/blame - src/vikgobjectbuilder.c
Clarify text on map layer menu
[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);
1487f9b6
GB
110 if (gtype == 0)
111 {
112 g_warning("Unknown GObject type '%s'", class_name);
113 return;
114 }
7bc5a5a9
GB
115 }
116 if (strcmp(element_name, "property") == 0 && gtype != 0)
117 {
118 int i=0;
119 while (attribute_names[i] != NULL)
120 {
121 if (strcmp (attribute_names[i], "name") == 0)
122 {
123 g_free (property_name);
124 property_name = g_strdup (attribute_values[i]);
125 }
126 i++;
127 }
128 }
129}
130
131/* Called for close tags </foo> */
132static void
133_end_element (GMarkupParseContext *context,
134 const gchar *element_name,
135 gpointer user_data,
136 GError **error)
137{
138 VikGobjectBuilder *self = VIK_GOBJECT_BUILDER (user_data);
139 gpointer object = NULL;
140 if (strcmp(element_name, "object") == 0 && gtype != 0)
141 {
142 object = g_object_newv(gtype, nb_parameters, parameters);
143 if (object != NULL)
144 {
145 g_debug("VikGobjectBuilder: new GObject of type %s", g_type_name(gtype));
146 g_signal_emit ( G_OBJECT(self), gobject_builder_signals[NEW_OBJECT], 0, object );
147 g_object_unref (object);
148 }
149 /* Free memory */
150 int i = 0;
151 for (i = 0 ; i < nb_parameters ; i++)
152 {
153 g_free (parameters[i].name);
154 g_value_unset (&(parameters[i].value));
155 }
156 g_free (parameters);
157 parameters = NULL;
158 nb_parameters = 0;
159 gtype = 0;
160 }
161 if (strcmp(element_name, "property") == 0)
162 {
163 g_free (property_name);
164 property_name = NULL;
165 }
166}
167
168/* Called for character data */
169/* text is not nul-terminated */
170static void
171_text (GMarkupParseContext *context,
172 const gchar *text,
173 gsize text_len,
174 gpointer user_data,
175 GError **error)
176{
177 if (strcmp (g_markup_parse_context_get_element (context), "property") == 0)
178 {
179 GValue gvalue = {0};
180 gboolean found = FALSE;
181 if (gtype != 0 && property_name != NULL)
182 {
183 /* parameter value */
184 /* We have to retrieve the expected type of the value
185 * in order to do the correct transformation */
186 GObjectClass *oclass;
187 oclass = g_type_class_ref (gtype);
188 g_assert (oclass != NULL);
189 GParamSpec *pspec;
190 pspec = g_object_class_find_property (G_OBJECT_CLASS (oclass), property_name);
191 if (!pspec)
192 {
193 g_warning ("Unknown property: %s.%s", g_type_name (gtype), property_name);
194 return;
195 }
196 gchar *value = g_strndup (text, text_len);
197 found = gtk_builder_value_from_string_type(NULL, pspec->value_type, value, &gvalue, NULL);
198 g_free (value);
199 }
200 if (G_IS_VALUE (&gvalue) && found == TRUE)
201 {
202 /* store new parameter */
203 g_debug("VikGobjectBuilder: store new GParameter for %s: (%s)%s=%*s",
204 g_type_name(gtype), g_type_name(G_VALUE_TYPE(&gvalue)), property_name, text_len, text);
205 nb_parameters++;
206 parameters = g_realloc(parameters, sizeof(GParameter)*nb_parameters);
207 /* parameter name */
208 parameters[nb_parameters-1].name = g_strdup(property_name);
209 /* parameter value */
210 parameters[nb_parameters-1].value = gvalue;
211 }
212 }
213}
214
215VikGobjectBuilder *
216vik_gobject_builder_new (void)
217{
218 return g_object_new (VIK_TYPE_GOBJECT_BUILDER, NULL);
219}
220
221void
222vik_gobject_builder_parse (VikGobjectBuilder *self, const gchar *filename)
223{
224 GMarkupParser xml_parser;
225 GMarkupParseContext *xml_context;
226 GError *error;
227
228 FILE *file = g_fopen (filename, "r");
229 if (file == NULL)
230 /* TODO emit warning */
231 return;
232
233 /* setup context parse (ie callbacks) */
234 xml_parser.start_element = &_start_element;
235 xml_parser.end_element = &_end_element;
236 xml_parser.text = &_text;
237 xml_parser.passthrough = NULL;
238 xml_parser.error = NULL;
239
240 xml_context = g_markup_parse_context_new(&xml_parser, 0, self, NULL);
241
242 gchar buff[BUFSIZ];
243 size_t nb;
244 while ((nb = fread (buff, sizeof(gchar), BUFSIZ, file)) > 0)
245 {
246 if (!g_markup_parse_context_parse(xml_context, buff, nb, &error))
247 printf("read_xml() : parsing error.\n");
248 }
249 /* cleanup */
250 if (!g_markup_parse_context_end_parse(xml_context, &error))
251 printf("read_xml() : errors occurred reading file.\n");
252
253 g_markup_parse_context_free(xml_context);
254 fclose (file);
255}