Add Emacs modeline for .c and .h files.
[platform/upstream/ibus.git] / src / ibusfactory.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 <dbus/dbus.h>
23 #include "ibusfactory.h"
24 #include "ibusengine.h"
25 #include "ibusshare.h"
26 #include "ibusinternal.h"
27
28 #define IBUS_FACTORY_GET_PRIVATE(o)  \
29    (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_FACTORY, IBusFactoryPrivate))
30
31 enum {
32     LAST_SIGNAL,
33 };
34
35 enum {
36     PROP_0,
37     PROP_CONNECTION,
38 };
39
40 /* IBusFactoryPriv */
41 struct _IBusFactoryPrivate {
42     guint id;
43     IBusConnection *connection;
44     GList          *engine_list;
45     GHashTable     *engine_table;
46 };
47 typedef struct _IBusFactoryPrivate IBusFactoryPrivate;
48
49 /* functions prototype */
50 static void     ibus_factory_destroy        (IBusFactory        *factory);
51 static void     ibus_factory_set_property   (IBusFactory        *engine,
52                                              guint               prop_id,
53                                              const GValue       *value,
54                                              GParamSpec         *pspec);
55 static void     ibus_factory_get_property   (IBusFactory        *factory,
56                                              guint               prop_id,
57                                              GValue             *value,
58                                              GParamSpec         *pspec);
59
60 static gboolean ibus_factory_ibus_message   (IBusFactory        *factory,
61                                              IBusConnection     *connection,
62                                              IBusMessage        *message);
63
64 static void     _engine_destroy_cb          (IBusEngine         *engine,
65                                              IBusFactory        *factory);
66
67 G_DEFINE_TYPE (IBusFactory, ibus_factory, IBUS_TYPE_SERVICE)
68
69 IBusFactory *
70 ibus_factory_new (IBusConnection *connection)
71 {
72     g_assert (IBUS_IS_CONNECTION (connection));
73
74     IBusFactory *factory;
75     IBusFactoryPrivate *priv;
76
77     factory = (IBusFactory *) g_object_new (IBUS_TYPE_FACTORY,
78                                             "path", IBUS_PATH_FACTORY,
79                                             "connection", connection,
80                                             NULL);
81     priv = IBUS_FACTORY_GET_PRIVATE (factory);
82
83     return factory;
84 }
85
86 static void
87 ibus_factory_class_init (IBusFactoryClass *klass)
88 {
89     GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
90     IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass);
91
92     g_type_class_add_private (klass, sizeof (IBusFactoryPrivate));
93
94     gobject_class->set_property = (GObjectSetPropertyFunc) ibus_factory_set_property;
95     gobject_class->get_property = (GObjectGetPropertyFunc) ibus_factory_get_property;
96
97
98     ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_factory_destroy;
99
100     IBUS_SERVICE_CLASS (klass)->ibus_message = (ServiceIBusMessageFunc) ibus_factory_ibus_message;
101
102     /**
103      * IBusFactory:connection:
104      *
105      * Connection of this IBusFactory.
106      **/
107     g_object_class_install_property (gobject_class,
108                 PROP_CONNECTION,
109                 g_param_spec_object ("connection",
110                 "connection",
111                 "The connection of factory object",
112                 IBUS_TYPE_CONNECTION,
113                 G_PARAM_READWRITE |  G_PARAM_CONSTRUCT_ONLY));
114
115
116 }
117
118 static void
119 ibus_factory_init (IBusFactory *factory)
120 {
121     IBusFactoryPrivate *priv;
122     priv = IBUS_FACTORY_GET_PRIVATE (factory);
123
124     priv->id = 0;
125     priv->connection = NULL;
126     priv->engine_table = g_hash_table_new_full (g_str_hash,
127                                                 g_str_equal,
128                                                 g_free,
129                                                 NULL);
130     priv->engine_list =  NULL;
131 }
132
133 static void
134 ibus_factory_destroy (IBusFactory *factory)
135 {
136     GList *list;
137     IBusFactoryPrivate *priv;
138     priv = IBUS_FACTORY_GET_PRIVATE (factory);
139
140     list = g_list_copy (priv->engine_list);
141     g_list_foreach (list, (GFunc) ibus_object_destroy, NULL);
142     g_list_free (priv->engine_list);
143     g_list_free (list);
144     priv->engine_list = NULL;
145
146     if (priv->engine_table) {
147         g_hash_table_destroy (priv->engine_table);
148     }
149
150     if (priv->connection) {
151         g_object_unref (priv->connection);
152         priv->connection = NULL;
153     }
154
155     IBUS_OBJECT_CLASS(ibus_factory_parent_class)->destroy (IBUS_OBJECT (factory));
156 }
157
158 static void
159 ibus_factory_set_property (IBusFactory  *factory,
160                            guint         prop_id,
161                            const GValue *value,
162                            GParamSpec   *pspec)
163 {
164     IBusFactoryPrivate *priv;
165     priv = IBUS_FACTORY_GET_PRIVATE (factory);
166
167     switch (prop_id) {
168     case PROP_CONNECTION:
169         priv->connection = g_value_get_object (value);
170         g_object_ref_sink (priv->connection);
171         ibus_service_add_to_connection ((IBusService *) factory,
172                                         priv->connection);
173         break;
174
175     default:
176         G_OBJECT_WARN_INVALID_PROPERTY_ID (factory, prop_id, pspec);
177     }
178 }
179
180 static void
181 ibus_factory_get_property (IBusFactory *factory,
182                            guint        prop_id,
183                            GValue      *value,
184                            GParamSpec  *pspec)
185 {
186     IBusFactoryPrivate *priv;
187     priv = IBUS_FACTORY_GET_PRIVATE (factory);
188
189     switch (prop_id) {
190     case PROP_CONNECTION:
191         g_value_set_object (value, priv->connection);
192         break;
193
194     default:
195         G_OBJECT_WARN_INVALID_PROPERTY_ID (factory, prop_id, pspec);
196     }
197 }
198
199 static void
200 _engine_destroy_cb (IBusEngine  *engine,
201                     IBusFactory *factory)
202 {
203     IBusFactoryPrivate *priv;
204     priv = IBUS_FACTORY_GET_PRIVATE (factory);
205
206     priv->engine_list = g_list_remove (priv->engine_list, engine);
207     g_object_unref (engine);
208 }
209
210 static gboolean
211 ibus_factory_ibus_message (IBusFactory    *factory,
212                            IBusConnection *connection,
213                            IBusMessage    *message)
214 {
215     g_assert (IBUS_IS_FACTORY (factory));
216     g_assert (IBUS_IS_CONNECTION (connection));
217     g_assert (message != NULL);
218
219     IBusMessage *reply_message;
220     IBusFactoryPrivate *priv;
221     priv = IBUS_FACTORY_GET_PRIVATE (factory);
222
223     g_assert (priv->connection == connection);
224
225     if (ibus_message_is_method_call (message,
226                                      IBUS_INTERFACE_FACTORY,
227                                      "CreateEngine")) {
228         gchar *engine_name;
229         gchar *path;
230         IBusError *error;
231         IBusEngine *engine;
232         gboolean retval;
233         GType engine_type;
234
235         retval = ibus_message_get_args (message,
236                                         &error,
237                                         G_TYPE_STRING, &engine_name,
238                                         G_TYPE_INVALID);
239
240         if (!retval) {
241             reply_message = ibus_message_new_error_printf (message,
242                                         DBUS_ERROR_INVALID_ARGS,
243                                         "The 1st arg should be engine name");
244             ibus_connection_send (connection, reply_message);
245             ibus_message_unref (reply_message);
246             return TRUE;
247         }
248
249         engine_type = (GType )g_hash_table_lookup (priv->engine_table, engine_name);
250
251         if (engine_type == G_TYPE_INVALID) {
252              reply_message = ibus_message_new_error_printf (message,
253                                         DBUS_ERROR_FAILED,
254                                         "Can not create engine %s", engine_name);
255             ibus_connection_send (connection, reply_message);
256             ibus_message_unref (reply_message);
257             return TRUE;
258
259         }
260
261         path = g_strdup_printf ("/org/freedesktop/IBus/Engine/%d", ++priv->id);
262
263         engine = g_object_new (engine_type,
264                                "name", engine_name,
265                                "path", path,
266                                "connection", priv->connection,
267                                NULL);
268
269         priv->engine_list = g_list_append (priv->engine_list, engine);
270         g_signal_connect (engine,
271                           "destroy",
272                           G_CALLBACK (_engine_destroy_cb),
273                           factory);
274
275         reply_message = ibus_message_new_method_return (message);
276         ibus_message_append_args (reply_message,
277                                   IBUS_TYPE_OBJECT_PATH, &path,
278                                   G_TYPE_INVALID);
279         g_free (path);
280         ibus_connection_send (connection, reply_message);
281         ibus_message_unref (reply_message);
282         return TRUE;
283     }
284
285     return IBUS_SERVICE_CLASS (ibus_factory_parent_class)->ibus_message (
286                                 (IBusService *)factory,
287                                 connection,
288                                 message);
289 }
290
291 void
292 ibus_factory_add_engine (IBusFactory *factory,
293                          const gchar *engine_name,
294                          GType        engine_type)
295 {
296     g_assert (IBUS_IS_FACTORY (factory));
297     g_assert (engine_name);
298     g_assert (g_type_is_a (engine_type, IBUS_TYPE_ENGINE));
299
300     IBusFactoryPrivate *priv;
301     priv = IBUS_FACTORY_GET_PRIVATE (factory);
302
303     g_hash_table_insert (priv->engine_table, g_strdup (engine_name), (gpointer) engine_type);
304 }