Use G_DEFINE_TYPE to simplify code.
[platform/upstream/ibus.git] / src / ibusfactory.c
1 /* vim:set et sts=4: */
2 /* ibus - The Input Bus
3  * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
4  * Copyright (C) 2008-2010 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_destroy        (IBusFactory        *factory);
45 static gboolean ibus_factory_ibus_message   (IBusFactory        *factory,
46                                              IBusConnection     *connection,
47                                              IBusMessage        *message);
48
49 static void     _engine_destroy_cb          (IBusEngine         *engine,
50                                              IBusFactory        *factory);
51
52 G_DEFINE_TYPE (IBusFactory, ibus_factory, IBUS_TYPE_SERVICE)
53
54 IBusFactory *
55 ibus_factory_new (IBusConnection *connection)
56 {
57     g_assert (IBUS_IS_CONNECTION (connection));
58
59     IBusFactory *factory;
60     IBusFactoryPrivate *priv;
61
62     factory = (IBusFactory *) g_object_new (IBUS_TYPE_FACTORY,
63                                             "path", IBUS_PATH_FACTORY,
64                                             NULL);
65     priv = IBUS_FACTORY_GET_PRIVATE (factory);
66
67     priv->connection = g_object_ref_sink (connection);
68     ibus_service_add_to_connection ((IBusService *)factory, connection);
69
70     return factory;
71 }
72
73 static void
74 ibus_factory_class_init (IBusFactoryClass *klass)
75 {
76     // GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
77     IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass);
78
79     g_type_class_add_private (klass, sizeof (IBusFactoryPrivate));
80
81     ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_factory_destroy;
82
83     IBUS_SERVICE_CLASS (klass)->ibus_message = (ServiceIBusMessageFunc) ibus_factory_ibus_message;
84
85 }
86
87 static void
88 ibus_factory_init (IBusFactory *factory)
89 {
90     IBusFactoryPrivate *priv;
91     priv = IBUS_FACTORY_GET_PRIVATE (factory);
92
93     priv->id = 0;
94     priv->connection = NULL;
95     priv->engine_table = g_hash_table_new_full (g_str_hash,
96                                                 g_str_equal,
97                                                 g_free,
98                                                 NULL);
99     priv->engine_list =  NULL;
100 }
101
102 static void
103 ibus_factory_destroy (IBusFactory *factory)
104 {
105     GList *list;
106     IBusFactoryPrivate *priv;
107     priv = IBUS_FACTORY_GET_PRIVATE (factory);
108
109     list = g_list_copy (priv->engine_list);
110     g_list_foreach (list, (GFunc) ibus_object_destroy, NULL);
111     g_list_free (priv->engine_list);
112     g_list_free (list);
113     priv->engine_list = NULL;
114
115     if (priv->engine_table) {
116         g_hash_table_destroy (priv->engine_table);
117     }
118
119     if (priv->connection) {
120         ibus_service_remove_from_connection ((IBusService *)factory,
121                                              priv->connection);
122         g_object_unref (priv->connection);
123     }
124
125     IBUS_OBJECT_CLASS(ibus_factory_parent_class)->destroy (IBUS_OBJECT (factory));
126 }
127
128 static void
129 _engine_destroy_cb (IBusEngine  *engine,
130                     IBusFactory *factory)
131 {
132     IBusFactoryPrivate *priv;
133     priv = IBUS_FACTORY_GET_PRIVATE (factory);
134
135     priv->engine_list = g_list_remove (priv->engine_list, engine);
136     g_object_unref (engine);
137 }
138
139 static gboolean
140 ibus_factory_ibus_message (IBusFactory    *factory,
141                            IBusConnection *connection,
142                            IBusMessage    *message)
143 {
144     g_assert (IBUS_IS_FACTORY (factory));
145     g_assert (IBUS_IS_CONNECTION (connection));
146     g_assert (message != NULL);
147
148     IBusMessage *reply_message;
149     IBusFactoryPrivate *priv;
150     priv = IBUS_FACTORY_GET_PRIVATE (factory);
151
152     g_assert (priv->connection == connection);
153
154     if (ibus_message_is_method_call (message,
155                                      IBUS_INTERFACE_FACTORY,
156                                      "CreateEngine")) {
157         gchar *engine_name;
158         gchar *path;
159         IBusError *error;
160         IBusEngine *engine;
161         gboolean retval;
162         GType engine_type;
163
164         retval = ibus_message_get_args (message,
165                                         &error,
166                                         G_TYPE_STRING, &engine_name,
167                                         G_TYPE_INVALID);
168
169         if (!retval) {
170             reply_message = ibus_message_new_error_printf (message,
171                                         DBUS_ERROR_INVALID_ARGS,
172                                         "The 1st arg should be engine name");
173             ibus_connection_send (connection, reply_message);
174             ibus_message_unref (reply_message);
175             return TRUE;
176         }
177
178         engine_type = (GType )g_hash_table_lookup (priv->engine_table, engine_name);
179
180         if (engine_type == G_TYPE_INVALID) {
181              reply_message = ibus_message_new_error_printf (message,
182                                         DBUS_ERROR_FAILED,
183                                         "Can not create engine %s", engine_name);
184             ibus_connection_send (connection, reply_message);
185             ibus_message_unref (reply_message);
186             return TRUE;
187
188         }
189
190         path = g_strdup_printf ("/org/freedesktop/IBus/Engine/%d", ++priv->id);
191
192         engine = g_object_new (engine_type,
193                                "name", engine_name,
194                                "path", path,
195                                "connection", priv->connection,
196                                NULL);
197
198         priv->engine_list = g_list_append (priv->engine_list, engine);
199         g_signal_connect (engine,
200                           "destroy",
201                           G_CALLBACK (_engine_destroy_cb),
202                           factory);
203
204         reply_message = ibus_message_new_method_return (message);
205         ibus_message_append_args (reply_message,
206                                   IBUS_TYPE_OBJECT_PATH, &path,
207                                   G_TYPE_INVALID);
208         g_free (path);
209         ibus_connection_send (connection, reply_message);
210         ibus_message_unref (reply_message);
211         return TRUE;
212     }
213
214     return IBUS_SERVICE_CLASS (ibus_factory_parent_class)->ibus_message (
215                                 (IBusService *)factory,
216                                 connection,
217                                 message);
218 }
219
220 void
221 ibus_factory_add_engine (IBusFactory *factory,
222                          const gchar *engine_name,
223                          GType        engine_type)
224 {
225     g_assert (IBUS_IS_FACTORY (factory));
226     g_assert (engine_name);
227     g_assert (g_type_is_a (engine_type, IBUS_TYPE_ENGINE));
228
229     IBusFactoryPrivate *priv;
230     priv = IBUS_FACTORY_GET_PRIVATE (factory);
231
232     g_hash_table_insert (priv->engine_table, g_strdup (engine_name), (gpointer) engine_type);
233 }