Fix make rpm errors due to ibus-dconf and pygobject override
[platform/upstream/ibus.git] / src / ibusserializable.c
1 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
2 /* vim:set et sts=4: */
3 /* ibus - The Input Bus
4  * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
5  * Copyright (C) 2008-2010 Red Hat, Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22 #include "ibusinternal.h"
23 #include "ibusserializable.h"
24
25 #define IBUS_SERIALIZABLE_GET_PRIVATE(o)  \
26    (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_SERIALIZABLE, IBusSerializablePrivate))
27
28 enum {
29     LAST_SIGNAL,
30 };
31
32 struct _IBusSerializablePrivate {
33     GData   *attachments;
34 };
35
36 // static guint    object_signals[LAST_SIGNAL] = { 0 };
37
38 /* functions prototype */
39 static void      ibus_serializable_base_init        (IBusSerializableClass  *class);
40 static void      ibus_serializable_base_fini        (IBusSerializableClass  *class);
41 static void      ibus_serializable_class_init       (IBusSerializableClass  *class);
42 static void      ibus_serializable_init             (IBusSerializable       *object);
43 static void      ibus_serializable_destroy          (IBusSerializable       *object);
44 static gboolean  ibus_serializable_real_serialize   (IBusSerializable       *object,
45                                                      GVariantBuilder        *builder);
46 static gint      ibus_serializable_real_deserialize (IBusSerializable       *object,
47                                                      GVariant               *variant);
48 static gboolean  ibus_serializable_real_copy        (IBusSerializable       *dest,
49                                                      const IBusSerializable *src);
50
51 static IBusObjectClass *parent_class = NULL;
52
53 GType
54 ibus_serializable_get_type (void)
55 {
56     static GType type = 0;
57
58     static const GTypeInfo type_info = {
59         sizeof (IBusSerializableClass),
60         (GBaseInitFunc)     ibus_serializable_base_init,
61         (GBaseFinalizeFunc) ibus_serializable_base_fini,
62         (GClassInitFunc)    ibus_serializable_class_init,
63         NULL,               /* class finialize */
64         NULL,               /* class data */
65         sizeof (IBusSerializable),
66         0,
67         (GInstanceInitFunc) ibus_serializable_init,
68     };
69
70     if (type == 0) {
71         type = g_type_register_static (IBUS_TYPE_OBJECT,
72                                        "IBusSerializable",
73                                        &type_info,
74                                        0);
75     }
76
77     return type;
78 }
79
80 IBusSerializable *
81 ibus_serializable_new (void)
82 {
83     return IBUS_SERIALIZABLE (g_object_new (IBUS_TYPE_SERIALIZABLE, NULL));
84 }
85
86 static void
87 ibus_serializable_base_init     (IBusSerializableClass *class)
88 {
89 }
90
91 static void
92 ibus_serializable_base_fini     (IBusSerializableClass *class)
93 {
94 }
95
96 static void
97 ibus_serializable_class_init     (IBusSerializableClass *class)
98 {
99     IBusObjectClass *object_class = IBUS_OBJECT_CLASS (class);
100
101     parent_class = (IBusObjectClass *) g_type_class_peek_parent (class);
102
103     g_type_class_add_private (class, sizeof (IBusSerializablePrivate));
104
105     object_class->destroy = (IBusObjectDestroyFunc) ibus_serializable_destroy;
106
107     class->serialize = ibus_serializable_real_serialize;
108     class->deserialize = ibus_serializable_real_deserialize;
109     class->copy = ibus_serializable_real_copy;
110 }
111
112 static void
113 ibus_serializable_init (IBusSerializable *serializable)
114 {
115     serializable->priv = IBUS_SERIALIZABLE_GET_PRIVATE (serializable);
116     serializable->priv->attachments = NULL;
117     g_datalist_init (&serializable->priv->attachments);
118 }
119
120 static void
121 ibus_serializable_destroy (IBusSerializable *serializable)
122 {
123     g_datalist_clear (&serializable->priv->attachments);
124     parent_class->destroy (IBUS_OBJECT (serializable));
125 }
126
127 static void
128 _serialize_cb (GQuark           key,
129                GVariant        *value,
130                GVariantBuilder *array)
131 {
132     g_variant_builder_add (array, "{sv}",
133                 g_quark_to_string (key), g_variant_new_variant (value));
134 }
135
136 static gboolean
137 ibus_serializable_real_serialize (IBusSerializable *serializable,
138                                   GVariantBuilder  *builder)
139 {
140     GVariantBuilder array;
141     g_variant_builder_init (&array, G_VARIANT_TYPE ("a{sv}"));
142
143     g_datalist_foreach (&serializable->priv->attachments,
144                         (GDataForeachFunc) _serialize_cb,
145                         &array);
146     g_variant_builder_add (builder, "a{sv}", &array);
147     return TRUE;
148 }
149
150 static gint
151 ibus_serializable_real_deserialize (IBusSerializable *object,
152                                     GVariant         *variant)
153 {
154     const gchar *key;
155     GVariant *value;
156     GVariantIter *iter = NULL;
157     g_variant_get_child (variant, 1, "a{sv}", &iter);
158     while (g_variant_iter_loop (iter, "{&sv}", &key, &value)) {
159         GVariant *attachment = g_variant_get_variant (value);
160         ibus_serializable_set_attachment (object,
161                                           key,
162                                           attachment);
163         g_variant_unref (attachment);
164     }
165     g_variant_iter_free (iter);
166     return 2;
167 }
168
169 static void
170 _copy_cb (GQuark     key,
171           GVariant  *value,
172           GData    **datalist)
173 {
174     g_datalist_id_set_data_full (datalist,
175                                  key,
176                                  g_variant_ref (value),
177                                  (GDestroyNotify) g_variant_unref);
178 }
179
180 static gboolean
181 ibus_serializable_real_copy (IBusSerializable *dest,
182                              const IBusSerializable *src)
183 {
184     IBusSerializablePrivate *src_priv;
185     IBusSerializablePrivate *dest_priv;
186     src_priv = IBUS_SERIALIZABLE_GET_PRIVATE (src);
187     dest_priv = IBUS_SERIALIZABLE_GET_PRIVATE (dest);
188
189     g_datalist_foreach (&src_priv->attachments,
190                         (GDataForeachFunc) _copy_cb,
191                         &dest_priv->attachments);
192     return TRUE;
193 }
194
195 void
196 ibus_serializable_set_qattachment (IBusSerializable *serializable,
197                                    GQuark            key,
198                                    GVariant         *value)
199 {
200     g_return_if_fail (IBUS_IS_SERIALIZABLE (serializable));
201     g_return_if_fail (key != 0);
202
203     g_datalist_id_set_data_full (&serializable->priv->attachments,
204                                  key,
205                                  value ? g_variant_ref_sink (value) : NULL,
206                                  (GDestroyNotify) g_variant_unref);
207 }
208
209 GVariant *
210 ibus_serializable_get_qattachment (IBusSerializable *serializable,
211                                    GQuark            key)
212 {
213
214     g_return_val_if_fail (IBUS_IS_SERIALIZABLE (serializable), NULL);
215     g_return_val_if_fail (key != 0, NULL);
216
217     return (GVariant *) g_datalist_id_get_data (
218             &serializable->priv->attachments, key);
219 }
220
221 void
222 ibus_serializable_remove_qattachment (IBusSerializable *serializable,
223                                       GQuark            key)
224 {
225
226     g_return_if_fail (IBUS_IS_SERIALIZABLE (serializable));
227     g_return_if_fail (key != 0);
228
229     g_datalist_id_set_data (&serializable->priv->attachments, key, NULL);
230 }
231
232 IBusSerializable *
233 ibus_serializable_copy (IBusSerializable *object)
234 {
235     g_return_val_if_fail (IBUS_IS_SERIALIZABLE (object), NULL);
236
237     GType type;
238     IBusSerializable *new_object;
239
240     type = G_OBJECT_TYPE (object);
241
242     new_object = g_object_new (type, NULL);
243     g_return_val_if_fail (new_object != NULL, NULL);
244
245     if (IBUS_SERIALIZABLE_GET_CLASS (new_object)->copy (new_object, object)) {
246         return new_object;
247     }
248
249     g_object_unref (new_object);
250     g_return_val_if_reached (NULL);
251 }
252
253 GVariant *
254 ibus_serializable_serialize (IBusSerializable *object)
255 {
256     g_return_val_if_fail (IBUS_IS_SERIALIZABLE (object), FALSE);
257     gboolean retval;
258
259     GVariantBuilder builder;
260     g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
261
262     g_variant_builder_add (&builder, "s", g_type_name (G_OBJECT_TYPE (object)));
263     retval = IBUS_SERIALIZABLE_GET_CLASS (object)->serialize (object, &builder);
264     g_assert (retval);
265
266     return g_variant_builder_end (&builder);
267 }
268
269 IBusSerializable *
270 ibus_serializable_deserialize (GVariant *variant)
271 {
272     g_return_val_if_fail (variant != NULL, NULL);
273
274     GVariant *var = NULL;
275     switch (g_variant_classify (variant)) {
276     case G_VARIANT_CLASS_VARIANT:
277         var = g_variant_get_variant (variant);
278         break;
279     case G_VARIANT_CLASS_TUPLE:
280         var = g_variant_ref (variant);
281         break;
282     default:
283         g_return_val_if_reached (NULL);
284     }
285
286     gchar *type_name = NULL;
287     g_variant_get_child (var, 0, "&s", &type_name);
288     GType type = g_type_from_name (type_name);
289
290     g_return_val_if_fail (g_type_is_a (type, IBUS_TYPE_SERIALIZABLE), NULL);
291
292     IBusSerializable *object = g_object_new (type, NULL);
293
294     gint retval = IBUS_SERIALIZABLE_GET_CLASS (object)->deserialize (object, var);
295     g_variant_unref (var);
296     if (retval)
297         return object;
298
299     g_object_unref (object);
300     g_return_val_if_reached (NULL);
301 }
302