]> git.street.me.uk Git - andy/viking.git/blame - src/vikgobjectbuilder.c
Set the generate image file filter according to the file type selected.
[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
a482007a 4 * Copyright (C) 2009, Guilhem Bonnefille <guilhem.bonnefille@gmail.com>
7bc5a5a9
GB
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
d156fff5 32#include <gtk/gtk.h>
7bc5a5a9
GB
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);
7bc5a5a9
GB
80
81 object_class->finalize = vik_gobject_builder_finalize;
82
83 klass->new_object = vik_gobject_builder_new_object;
84
85 gobject_builder_signals[NEW_OBJECT] =
86 g_signal_new ("new-object",
87 G_OBJECT_CLASS_TYPE (klass),
88 0,
89 G_STRUCT_OFFSET (VikGobjectBuilderClass, new_object),
90 NULL, NULL,
91 g_cclosure_marshal_VOID__OBJECT,
92 G_TYPE_NONE, 1,
93 G_TYPE_OBJECT);
94}
95
96/* Called for open tags <foo bar="baz"> */
97static void
98_start_element (GMarkupParseContext *context,
99 const gchar *element_name,
100 const gchar **attribute_names,
101 const gchar **attribute_values,
102 gpointer user_data,
103 GError **error)
104{
105 if (strcmp(element_name, "object") == 0)
106 {
107 class_name = g_strdup(attribute_values[0]);
108 gtype = g_type_from_name (class_name);
1487f9b6
GB
109 if (gtype == 0)
110 {
111 g_warning("Unknown GObject type '%s'", class_name);
112 return;
113 }
7bc5a5a9
GB
114 }
115 if (strcmp(element_name, "property") == 0 && gtype != 0)
116 {
117 int i=0;
118 while (attribute_names[i] != NULL)
119 {
120 if (strcmp (attribute_names[i], "name") == 0)
121 {
122 g_free (property_name);
123 property_name = g_strdup (attribute_values[i]);
124 }
125 i++;
126 }
127 }
128}
129
130/* Called for close tags </foo> */
131static void
132_end_element (GMarkupParseContext *context,
133 const gchar *element_name,
134 gpointer user_data,
135 GError **error)
136{
137 VikGobjectBuilder *self = VIK_GOBJECT_BUILDER (user_data);
138 gpointer object = NULL;
139 if (strcmp(element_name, "object") == 0 && gtype != 0)
140 {
141 object = g_object_newv(gtype, nb_parameters, parameters);
142 if (object != NULL)
143 {
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);
147 }
148 /* Free memory */
149 int i = 0;
150 for (i = 0 ; i < nb_parameters ; i++)
151 {
f83f478a 152 g_free ((gchar *)parameters[i].name);
7bc5a5a9
GB
153 g_value_unset (&(parameters[i].value));
154 }
155 g_free (parameters);
156 parameters = NULL;
157 nb_parameters = 0;
158 gtype = 0;
159 }
160 if (strcmp(element_name, "property") == 0)
161 {
162 g_free (property_name);
163 property_name = NULL;
164 }
165}
166
167/* Called for character data */
168/* text is not nul-terminated */
169static void
170_text (GMarkupParseContext *context,
171 const gchar *text,
172 gsize text_len,
173 gpointer user_data,
174 GError **error)
175{
176 if (strcmp (g_markup_parse_context_get_element (context), "property") == 0)
177 {
178 GValue gvalue = {0};
179 gboolean found = FALSE;
180 if (gtype != 0 && property_name != NULL)
181 {
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);
188 GParamSpec *pspec;
189 pspec = g_object_class_find_property (G_OBJECT_CLASS (oclass), property_name);
190 if (!pspec)
191 {
192 g_warning ("Unknown property: %s.%s", g_type_name (gtype), property_name);
193 return;
194 }
195 gchar *value = g_strndup (text, text_len);
196 found = gtk_builder_value_from_string_type(NULL, pspec->value_type, value, &gvalue, NULL);
197 g_free (value);
198 }
199 if (G_IS_VALUE (&gvalue) && found == TRUE)
200 {
201 /* store new parameter */
202 g_debug("VikGobjectBuilder: store new GParameter for %s: (%s)%s=%*s",
f83f478a 203 g_type_name(gtype), g_type_name(G_VALUE_TYPE(&gvalue)), property_name, (gint)text_len, text);
7bc5a5a9
GB
204 nb_parameters++;
205 parameters = g_realloc(parameters, sizeof(GParameter)*nb_parameters);
206 /* parameter name */
207 parameters[nb_parameters-1].name = g_strdup(property_name);
208 /* parameter value */
209 parameters[nb_parameters-1].value = gvalue;
210 }
211 }
212}
213
214VikGobjectBuilder *
215vik_gobject_builder_new (void)
216{
217 return g_object_new (VIK_TYPE_GOBJECT_BUILDER, NULL);
218}
219
220void
221vik_gobject_builder_parse (VikGobjectBuilder *self, const gchar *filename)
222{
223 GMarkupParser xml_parser;
224 GMarkupParseContext *xml_context;
705735aa 225 GError *error = NULL;
7bc5a5a9
GB
226
227 FILE *file = g_fopen (filename, "r");
228 if (file == NULL)
229 /* TODO emit warning */
230 return;
231
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;
238
239 xml_context = g_markup_parse_context_new(&xml_parser, 0, self, NULL);
240
241 gchar buff[BUFSIZ];
242 size_t nb;
243 while ((nb = fread (buff, sizeof(gchar), BUFSIZ, file)) > 0)
244 {
245 if (!g_markup_parse_context_parse(xml_context, buff, nb, &error))
705735aa
GB
246 g_warning("%s: parsing error: %s", __FUNCTION__,
247 error != NULL ? error->message : "???");
7bc5a5a9
GB
248 }
249 /* cleanup */
250 if (!g_markup_parse_context_end_parse(xml_context, &error))
705735aa
GB
251 g_warning("%s: errors occurred reading file '%s': %s", __FUNCTION__, filename,
252 error != NULL ? error->message : "???");
7bc5a5a9
GB
253
254 g_markup_parse_context_free(xml_context);
255 fclose (file);
256}