Merge remote branch 'XueWei/master'
[platform/upstream/ibus.git] / src / ibusfactory.c
1 /* vim:set et sts=4: */
2 /* ibus - The Input Bus
3  * Copyright (C) 2008-2009 Peng Huang <shawn.p.huang@gmail.com>
4  * Copyright (C) 2008-2009 Red Hat, Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #include "ibusfactory.h"
23 #include "ibusengine.h"
24 #include "ibusshare.h"
25 #include "ibusinternal.h"
26
27 #define IBUS_FACTORY_GET_PRIVATE(o)  \
28    (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_FACTORY, IBusFactoryPrivate))
29
30 enum {
31     LAST_SIGNAL,
32 };
33
34 /* IBusFactoryPriv */
35 struct _IBusFactoryPrivate {
36     guint id;
37     IBusConnection *connection;
38     GList          *engine_list;
39     GHashTable     *engine_table;
40 };
41 typedef struct _IBusFactoryPrivate IBusFactoryPrivate;
42
43 /* functions prototype */
44 static void     ibus_factory_class_init     (IBusFactoryClass   *klass);
45 static void     ibus_factory_init           (IBusFactory        *factory);
46 static void     ibus_factory_destroy        (IBusFactory        *factory);
47 static gboolean ibus_factory_ibus_message   (IBusFactory        *factory,
48                                              IBusConnection     *connection,
49                                              IBusMessage        *message);
50
51 static void     _engine_destroy_cb          (IBusEngine         *engine,
52                                              IBusFactory        *factory);
53 static void     ibus_factory_info_class_init(IBusFactoryInfoClass   *klass);
54 static void     ibus_factory_info_init      (IBusFactoryInfo        *info);
55 static void     ibus_factory_info_destroy   (IBusFactoryInfo        *info);
56 static gboolean ibus_factory_info_serialize (IBusFactoryInfo        *info,
57                                              IBusMessageIter        *iter);
58 static gboolean ibus_factory_info_deserialize
59                                             (IBusFactoryInfo        *info,
60                                              IBusMessageIter        *iter);
61 static gboolean ibus_factory_info_copy      (IBusFactoryInfo        *dest,
62                                              const IBusFactoryInfo  *src);
63
64 static IBusServiceClass *factory_parent_class = NULL;
65 static IBusSerializableClass *factory_info_parent_class = NULL;
66
67 GType
68 ibus_factory_get_type (void)
69 {
70     static GType type = 0;
71
72     static const GTypeInfo type_info = {
73         sizeof (IBusFactoryClass),
74         (GBaseInitFunc)     NULL,
75         (GBaseFinalizeFunc) NULL,
76         (GClassInitFunc)    ibus_factory_class_init,
77         NULL,               /* class finalize */
78         NULL,               /* class data */
79         sizeof (IBusFactory),
80         0,
81         (GInstanceInitFunc) ibus_factory_init,
82     };
83
84     if (type == 0) {
85         type = g_type_register_static (IBUS_TYPE_SERVICE,
86                     "IBusFactory",
87                     &type_info,
88                     (GTypeFlags) 0);
89     }
90     return type;
91 }
92
93 IBusFactory *
94 ibus_factory_new (IBusConnection *connection)
95 {
96     g_assert (IBUS_IS_CONNECTION (connection));
97
98     IBusFactory *factory;
99     IBusFactoryPrivate *priv;
100
101     factory = (IBusFactory *) g_object_new (IBUS_TYPE_FACTORY,
102                                             "path", IBUS_PATH_FACTORY,
103                                             NULL);
104     priv = IBUS_FACTORY_GET_PRIVATE (factory);
105
106     priv->connection = g_object_ref (connection);
107     ibus_service_add_to_connection ((IBusService *)factory, connection);
108
109     return factory;
110 }
111
112 static void
113 ibus_factory_class_init (IBusFactoryClass *klass)
114 {
115     // GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
116     IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass);
117
118     factory_parent_class = (IBusServiceClass *) g_type_class_peek_parent (klass);
119
120     g_type_class_add_private (klass, sizeof (IBusFactoryPrivate));
121
122     ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_factory_destroy;
123
124     IBUS_SERVICE_CLASS (klass)->ibus_message = (ServiceIBusMessageFunc) ibus_factory_ibus_message;
125
126 }
127
128 static void
129 ibus_factory_init (IBusFactory *factory)
130 {
131     IBusFactoryPrivate *priv;
132     priv = IBUS_FACTORY_GET_PRIVATE (factory);
133
134     priv->id = 0;
135     priv->connection = NULL;
136     priv->engine_table = g_hash_table_new_full (g_str_hash,
137                                                 g_str_equal,
138                                                 g_free,
139                                                 NULL);
140     priv->engine_list =  NULL;
141 }
142
143 static void
144 ibus_factory_destroy (IBusFactory *factory)
145 {
146     GList *list;
147     IBusFactoryPrivate *priv;
148     priv = IBUS_FACTORY_GET_PRIVATE (factory);
149
150     list = g_list_copy (priv->engine_list);
151     g_list_foreach (list, (GFunc) ibus_object_destroy, NULL);
152     g_list_free (priv->engine_list);
153     g_list_free (list);
154     priv->engine_list = NULL;
155
156     if (priv->engine_table) {
157         g_hash_table_destroy (priv->engine_table);
158     }
159
160     if (priv->connection) {
161         ibus_service_remove_from_connection ((IBusService *)factory,
162                                              priv->connection);
163         g_object_unref (priv->connection);
164     }
165
166     IBUS_OBJECT_CLASS(factory_parent_class)->destroy (IBUS_OBJECT (factory));
167 }
168
169 static void
170 _engine_destroy_cb (IBusEngine  *engine,
171                     IBusFactory *factory)
172 {
173     IBusFactoryPrivate *priv;
174     priv = IBUS_FACTORY_GET_PRIVATE (factory);
175
176     priv->engine_list = g_list_remove (priv->engine_list, engine);
177     g_object_unref (engine);
178 }
179
180 static gboolean
181 ibus_factory_ibus_message (IBusFactory    *factory,
182                            IBusConnection *connection,
183                            IBusMessage    *message)
184 {
185     g_assert (IBUS_IS_FACTORY (factory));
186     g_assert (IBUS_IS_CONNECTION (connection));
187     g_assert (message != NULL);
188
189     IBusMessage *reply_message;
190     IBusFactoryPrivate *priv;
191     priv = IBUS_FACTORY_GET_PRIVATE (factory);
192
193     g_assert (priv->connection == connection);
194
195     if (ibus_message_is_method_call (message,
196                                      IBUS_INTERFACE_FACTORY,
197                                      "CreateEngine")) {
198         gchar *engine_name;
199         gchar *path;
200         IBusError *error;
201         IBusEngine *engine;
202         gboolean retval;
203         GType engine_type;
204
205         retval = ibus_message_get_args (message,
206                                         &error,
207                                         G_TYPE_STRING, &engine_name,
208                                         G_TYPE_INVALID);
209
210         if (!retval) {
211             reply_message = ibus_message_new_error_printf (message,
212                                         DBUS_ERROR_INVALID_ARGS,
213                                         "The 1st arg should be engine name");
214             ibus_connection_send (connection, reply_message);
215             ibus_message_unref (reply_message);
216             return TRUE;
217         }
218
219         engine_type = (GType )g_hash_table_lookup (priv->engine_table, engine_name);
220
221         if (engine_type == G_TYPE_INVALID) {
222              reply_message = ibus_message_new_error_printf (message,
223                                         DBUS_ERROR_FAILED,
224                                         "Can not create engine %s", engine_name);
225             ibus_connection_send (connection, reply_message);
226             ibus_message_unref (reply_message);
227             return TRUE;
228
229         }
230
231         path = g_strdup_printf ("/org/freedesktop/IBus/Engine/%d", ++priv->id);
232
233         engine = g_object_new (engine_type,
234                                "name", engine_name,
235                                "path", path,
236                                "connection", priv->connection,
237                                NULL);
238
239         priv->engine_list = g_list_append (priv->engine_list, engine);
240         g_signal_connect (engine,
241                           "destroy",
242                           G_CALLBACK (_engine_destroy_cb),
243                           factory);
244
245         reply_message = ibus_message_new_method_return (message);
246         ibus_message_append_args (reply_message,
247                                   IBUS_TYPE_OBJECT_PATH, &path,
248                                   G_TYPE_INVALID);
249         g_free (path);
250         ibus_connection_send (connection, reply_message);
251         ibus_message_unref (reply_message);
252         return TRUE;
253     }
254
255     return factory_parent_class->ibus_message ((IBusService *)factory,
256                                                connection,
257                                                message);
258 }
259
260 void
261 ibus_factory_add_engine (IBusFactory *factory,
262                          const gchar *engine_name,
263                          GType        engine_type)
264 {
265     g_assert (IBUS_IS_FACTORY (factory));
266     g_assert (engine_name);
267     g_assert (g_type_is_a (engine_type, IBUS_TYPE_ENGINE));
268
269     IBusFactoryPrivate *priv;
270     priv = IBUS_FACTORY_GET_PRIVATE (factory);
271
272     g_hash_table_insert (priv->engine_table, g_strdup (engine_name), (gpointer) engine_type);
273 }
274
275 #if 0
276 IBusFactoryInfo *
277 ibus_factory_get_info (IBusFactory *factory)
278 {
279     IBusFactoryPrivate *priv;
280     priv = IBUS_FACTORY_GET_PRIVATE (factory);
281
282     return priv->info;
283 }
284 #endif
285
286 GType
287 ibus_factory_info_get_type (void)
288 {
289     static GType type = 0;
290
291     static const GTypeInfo type_info = {
292         sizeof (IBusFactoryInfoClass),
293         (GBaseInitFunc)     NULL,
294         (GBaseFinalizeFunc) NULL,
295         (GClassInitFunc)    ibus_factory_info_class_init,
296         NULL,               /* class finialize */
297         NULL,               /* class data */
298         sizeof (IBusFactoryInfo),
299         0,
300         (GInstanceInitFunc) ibus_factory_info_init,
301     };
302
303     if (type == 0) {
304         type = g_type_register_static (IBUS_TYPE_SERIALIZABLE,
305                                        "IBusFactoryInfo",
306                                        &type_info,
307                                        0);
308     }
309
310     return type;
311 }
312
313 static void
314 ibus_factory_info_class_init (IBusFactoryInfoClass *klass)
315 {
316     IBusObjectClass *object_class = IBUS_OBJECT_CLASS (klass);
317     IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (klass);
318
319     factory_info_parent_class = (IBusSerializableClass *) g_type_class_peek_parent (klass);
320
321     object_class->destroy = (IBusObjectDestroyFunc) ibus_factory_info_destroy;
322
323     serializable_class->serialize   = (IBusSerializableSerializeFunc) ibus_factory_info_serialize;
324     serializable_class->deserialize = (IBusSerializableDeserializeFunc) ibus_factory_info_deserialize;
325     serializable_class->copy        = (IBusSerializableCopyFunc) ibus_factory_info_copy;
326
327     g_string_append (serializable_class->signature, "osssss");
328 }
329
330 static void
331 ibus_factory_info_init (IBusFactoryInfo *info)
332 {
333     info->path = NULL;
334     info->name = NULL;
335     info->lang = NULL;
336     info->icon = NULL;
337     info->authors = NULL;
338     info->credits = NULL;
339 }
340
341 static void
342 ibus_factory_info_destroy (IBusFactoryInfo *info)
343 {
344     g_free (info->path);
345     g_free (info->name);
346     g_free (info->lang);
347     g_free (info->icon);
348     g_free (info->authors);
349     g_free (info->credits);
350
351     info->path = NULL;
352     info->lang = NULL;
353     info->name = NULL;
354     info->icon = NULL;
355     info->authors = NULL;
356     info->credits = NULL;
357
358     IBUS_OBJECT_CLASS (factory_info_parent_class)->destroy ((IBusObject *)info);
359 }
360
361 static gboolean
362 ibus_factory_info_serialize (IBusFactoryInfo *info,
363                              IBusMessageIter *iter)
364 {
365     gboolean retval;
366
367     retval = factory_info_parent_class->serialize ((IBusSerializable *)info, iter);
368     g_return_val_if_fail (retval, FALSE);
369
370     retval = ibus_message_iter_append (iter, IBUS_TYPE_OBJECT_PATH, &info->path);
371     g_return_val_if_fail (retval, FALSE);
372
373     retval = ibus_message_iter_append (iter, G_TYPE_STRING, &info->name);
374     g_return_val_if_fail (retval, FALSE);
375
376     retval = ibus_message_iter_append (iter, G_TYPE_STRING, &info->lang);
377     g_return_val_if_fail (retval, FALSE);
378
379     retval = ibus_message_iter_append (iter, G_TYPE_STRING, &info->icon);
380     g_return_val_if_fail (retval, FALSE);
381
382     retval = ibus_message_iter_append (iter, G_TYPE_STRING, &info->authors);
383     g_return_val_if_fail (retval, FALSE);
384
385     retval = ibus_message_iter_append (iter, G_TYPE_STRING, &info->credits);
386     g_return_val_if_fail (retval, FALSE);
387
388     return TRUE;
389 }
390
391 static gboolean
392 ibus_factory_info_deserialize (IBusFactoryInfo *info,
393                                IBusMessageIter *iter)
394 {
395     gboolean retval;
396
397     retval = factory_info_parent_class->deserialize ((IBusSerializable *)info, iter);
398     g_return_val_if_fail (retval, FALSE);
399
400     retval = ibus_message_iter_get (iter, IBUS_TYPE_OBJECT_PATH, &info->path);
401     g_return_val_if_fail (retval, FALSE);
402     ibus_message_iter_next (iter);
403     info->path = g_strdup (info->path);
404
405     retval = ibus_message_iter_get (iter, G_TYPE_STRING, &info->name);
406     g_return_val_if_fail (retval, FALSE);
407     ibus_message_iter_next (iter);
408     info->name = g_strdup (info->name);
409
410     retval = ibus_message_iter_get (iter, G_TYPE_STRING, &info->lang);
411     g_return_val_if_fail (retval, FALSE);
412     ibus_message_iter_next (iter);
413     info->lang = g_strdup (info->lang);
414
415     retval = ibus_message_iter_get (iter, G_TYPE_STRING, &info->icon);
416     g_return_val_if_fail (retval, FALSE);
417     ibus_message_iter_next (iter);
418     info->icon = g_strdup (info->icon);
419
420     retval = ibus_message_iter_get (iter, G_TYPE_STRING, &info->authors);
421     g_return_val_if_fail (retval, FALSE);
422     ibus_message_iter_next (iter);
423     info->authors = g_strdup (info->authors);
424
425     retval = ibus_message_iter_get (iter, G_TYPE_STRING, &info->credits);
426     g_return_val_if_fail (retval, FALSE);
427     ibus_message_iter_next (iter);
428     info->credits = g_strdup (info->credits);
429
430     return TRUE;
431 }
432
433 static gboolean
434 ibus_factory_info_copy (IBusFactoryInfo       *dest,
435                         const IBusFactoryInfo *src)
436 {
437     gboolean retval;
438
439     retval = factory_info_parent_class->copy ((IBusSerializable *)dest,
440                                               (IBusSerializable *)src);
441     g_return_val_if_fail (retval, FALSE);
442
443     g_return_val_if_fail (IBUS_IS_FACTORY_INFO (dest), FALSE);
444     g_return_val_if_fail (IBUS_IS_FACTORY_INFO (src), FALSE);
445
446     dest->path = g_strdup (src->path);
447     dest->name = g_strdup (src->name);
448     dest->lang = g_strdup (src->lang);
449     dest->icon = g_strdup (src->icon);
450     dest->authors = g_strdup (src->authors);
451     dest->credits = g_strdup (src->credits);
452
453     return TRUE;
454 }
455
456 IBusFactoryInfo *
457 ibus_factory_info_new (const gchar *path,
458                        const gchar *name,
459                        const gchar *lang,
460                        const gchar *icon,
461                        const gchar *authors,
462                        const gchar *credits)
463 {
464     g_assert (path);
465     g_assert (name);
466     g_assert (lang);
467     g_assert (icon);
468     g_assert (authors);
469     g_assert (credits);
470
471     IBusFactoryInfo *info;
472
473     info = (IBusFactoryInfo *) g_object_new (IBUS_TYPE_FACTORY_INFO, NULL);
474
475     info->path = g_strdup (path);
476     info->name = g_strdup (name);
477     info->lang = g_strdup (lang);
478     info->icon = g_strdup (icon);
479     info->authors = g_strdup (authors);
480     info->credits = g_strdup (credits);
481
482     return info;
483 }
484
485