LEFT | RIGHT |
(Both sides are equal) |
1 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ | 1 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ |
2 /* vim:set et sts=4: */ | 2 /* vim:set et sts=4: */ |
3 /* ibus - The Input Bus | 3 /* ibus - The Input Bus |
4 * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com> | 4 * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com> |
5 * Copyright (C) 2011 Daiki Ueno <ueno@unixuser.org> | 5 * Copyright (C) 2011 Daiki Ueno <ueno@unixuser.org> |
6 * Copyright (C) 2008-2011 Red Hat, Inc. | 6 * Copyright (C) 2008-2011 Red Hat, Inc. |
7 * | 7 * |
8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
9 * modify it under the terms of the GNU Lesser General Public | 9 * modify it under the terms of the GNU Lesser General Public |
10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
11 * version 2 of the License, or (at your option) any later version. | 11 * version 2 of the License, or (at your option) any later version. |
12 * | 12 * |
13 * This library is distributed in the hope that it will be useful, | 13 * This library is distributed in the hope that it will be useful, |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 * Lesser General Public License for more details. | 16 * Lesser General Public License for more details. |
17 * | 17 * |
18 * You should have received a copy of the GNU Lesser General Public | 18 * You should have received a copy of the GNU Lesser General Public |
19 * License along with this library; if not, write to the | 19 * License along with this library; if not, write to the |
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
21 * Boston, MA 02111-1307, USA. | 21 * Boston, MA 02111-1307, USA. |
22 */ | 22 */ |
23 | 23 |
24 #include <string.h> | 24 #include <string.h> |
25 #include <ibus.h> | 25 #include <ibus.h> |
26 #include "config.h" | 26 #include "config.h" |
27 | 27 |
28 #define DCONF_PREFIX "/desktop/ibus" | 28 #define DCONF_PREFIX "/desktop/ibus" |
| 29 #define DCONF_PRESERVE_NAME_PREFIXES_KEY \ |
| 30 DCONF_PREFIX"/general/dconf-preserve-name-prefixes" |
29 | 31 |
30 struct _IBusConfigDConf { | 32 struct _IBusConfigDConf { |
31 IBusConfigService parent; | 33 IBusConfigService parent; |
32 DConfClient *client; | 34 DConfClient *client; |
| 35 |
| 36 /* if a dconf path matches one of preserve_name_prefixes, don't convert |
| 37 key names from/to GSettings key names (see _to_gsettings_name |
| 38 and _from_gsettings_name) */ |
| 39 GSList *preserve_name_prefixes; |
33 }; | 40 }; |
34 | 41 |
35 struct _IBusConfigDConfClass { | 42 struct _IBusConfigDConfClass { |
36 IBusConfigServiceClass parent; | 43 IBusConfigServiceClass parent; |
37 }; | 44 }; |
38 | 45 |
39 /* functions prototype */ | 46 /* functions prototype */ |
40 static void ibus_config_dconf_class_init (IBusConfigDConfClass *class); | 47 static void ibus_config_dconf_class_init (IBusConfigDConfClass *class); |
41 static void ibus_config_dconf_init (IBusConfigDConf *config); | 48 static void ibus_config_dconf_init (IBusConfigDConf *config); |
42 static void ibus_config_dconf_destroy (IBusConfigDConf *config); | 49 static void ibus_config_dconf_destroy (IBusConfigDConf *config); |
(...skipping 22 matching lines...) Expand all Loading... |
65 IBusObjectClass *object_class = IBUS_OBJECT_CLASS (class); | 72 IBusObjectClass *object_class = IBUS_OBJECT_CLASS (class); |
66 IBusConfigServiceClass *config_class = IBUS_CONFIG_SERVICE_CLASS (class); | 73 IBusConfigServiceClass *config_class = IBUS_CONFIG_SERVICE_CLASS (class); |
67 | 74 |
68 object_class->destroy = (IBusObjectDestroyFunc) ibus_config_dconf_destroy; | 75 object_class->destroy = (IBusObjectDestroyFunc) ibus_config_dconf_destroy; |
69 config_class->set_value = ibus_config_dconf_set_value; | 76 config_class->set_value = ibus_config_dconf_set_value; |
70 config_class->get_value = ibus_config_dconf_get_value; | 77 config_class->get_value = ibus_config_dconf_get_value; |
71 config_class->get_values = ibus_config_dconf_get_values; | 78 config_class->get_values = ibus_config_dconf_get_values; |
72 config_class->unset_value = ibus_config_dconf_unset_value; | 79 config_class->unset_value = ibus_config_dconf_unset_value; |
73 } | 80 } |
74 | 81 |
| 82 static gboolean |
| 83 _has_prefixes (const gchar *path, GSList *prefixes) |
| 84 { |
| 85 GSList *head = prefixes; |
| 86 for (; head; head = head->next) { |
| 87 if (g_str_has_prefix (path, head->data)) { |
| 88 return TRUE; |
| 89 } |
| 90 } |
| 91 return FALSE; |
| 92 } |
| 93 |
75 /* Convert key names from/to GSettings names. While GSettings only | 94 /* Convert key names from/to GSettings names. While GSettings only |
76 * accepts lowercase letters / numbers / and dash ('-'), IBus uses | 95 * accepts lowercase letters / numbers / and dash ('-'), IBus uses |
77 * underscore ('_') and some engines even use uppercase letters. | 96 * underscore ('_') and some engines even use uppercase letters. |
78 * | 97 * |
79 * To minimize the gap, we do the following conversion: | 98 * To minimize the gap, we do the following conversion: |
80 * | 99 * |
81 * - when converting from IBus names to GSettings names, first convert | 100 * - when converting from IBus names to GSettings names, first convert |
82 * all letters to lowercase and then replace underscores with dashes. | 101 * all letters to lowercase and then replace underscores with dashes. |
83 * - when converting from GSettings names to IBus names, simply | 102 * - when converting from GSettings names to IBus names, simply |
84 * replace dashes with underscores. | 103 * replace dashes with underscores. |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 gkeys[i] = g_strdup_printf ("%s/%s", gpath, gname); | 189 gkeys[i] = g_strdup_printf ("%s/%s", gpath, gname); |
171 g_free (gname); | 190 g_free (gname); |
172 } | 191 } |
173 } | 192 } |
174 | 193 |
175 for (i = 0; i < n_items; i++) { | 194 for (i = 0; i < n_items; i++) { |
176 gchar *gname, *path, *name; | 195 gchar *gname, *path, *name; |
177 GVariant *variant = dconf_client_read (config->client, gkeys[i]); | 196 GVariant *variant = dconf_client_read (config->client, gkeys[i]); |
178 | 197 |
179 if (variant == NULL) { | 198 if (variant == NULL) { |
180 /* Use a empty typle for a unset value */ | 199 /* Use a empty tuple for a unset value */ |
181 variant = g_variant_new_tuple (NULL, 0); | 200 variant = g_variant_new_tuple (NULL, 0); |
182 } | 201 } |
183 | 202 |
184 gname = strrchr (gkeys[i], '/'); | 203 gname = strrchr (gkeys[i], '/'); |
185 g_assert (gname); | 204 g_assert (gname); |
186 *gname++ = '\0'; | 205 *gname++ = '\0'; |
187 | 206 |
188 path = _from_gsettings_path (gkeys[i]); | 207 if (_has_prefixes (gkeys[i], config->preserve_name_prefixes)) { |
189 name = _from_gsettings_name (gname); | 208 path = gkeys[i]; |
| 209 name = gname; |
| 210 } else { |
| 211 path = _from_gsettings_path (gkeys[i]); |
| 212 name = _from_gsettings_name (gname); |
| 213 } |
190 | 214 |
191 ibus_config_service_value_changed ((IBusConfigService *) config, | 215 ibus_config_service_value_changed ((IBusConfigService *) config, |
192 path + sizeof (DCONF_PREFIX), | 216 path + sizeof (DCONF_PREFIX), |
193 name, | 217 name, |
194 variant); | 218 variant); |
195 g_free (path); | 219 if (path != gkeys[i]) { |
196 g_free (name); | 220 g_free (path); |
| 221 } |
| 222 if (name != gname) { |
| 223 g_free (name); |
| 224 } |
197 g_variant_unref (variant); | 225 g_variant_unref (variant); |
198 } | 226 } |
199 g_strfreev (gkeys); | 227 g_strfreev (gkeys); |
200 } | 228 } |
201 | 229 |
202 static void | 230 static void |
203 ibus_config_dconf_init (IBusConfigDConf *config) | 231 ibus_config_dconf_init (IBusConfigDConf *config) |
204 { | 232 { |
| 233 GVariant *variant; |
205 GError *error; | 234 GError *error; |
206 | 235 |
207 config->client = dconf_client_new ("ibus", | 236 config->client = dconf_client_new ("ibus", |
208 (DConfWatchFunc)_watch_func, | 237 (DConfWatchFunc)_watch_func, |
209 config, | 238 config, |
210 NULL); | 239 NULL); |
211 | 240 |
212 error = NULL; | 241 error = NULL; |
213 if (!dconf_client_watch (config->client, DCONF_PREFIX"/", NULL, &error)) | 242 if (!dconf_client_watch (config->client, DCONF_PREFIX"/", NULL, &error)) |
214 g_warning ("Can not watch dconf path %s", DCONF_PREFIX"/"); | 243 g_warning ("Can not watch dconf path %s", DCONF_PREFIX"/"); |
| 244 |
| 245 config->preserve_name_prefixes = NULL; |
| 246 variant = dconf_client_read (config->client, |
| 247 DCONF_PRESERVE_NAME_PREFIXES_KEY); |
| 248 if (variant != NULL) { |
| 249 GVariantIter iter; |
| 250 GVariant *child; |
| 251 |
| 252 g_variant_iter_init (&iter, variant); |
| 253 while ((child = g_variant_iter_next_value (&iter))) { |
| 254 char *prefix = g_variant_dup_string (child, NULL); |
| 255 config->preserve_name_prefixes = |
| 256 g_slist_prepend (config->preserve_name_prefixes, |
| 257 prefix); |
| 258 g_variant_unref (child); |
| 259 } |
| 260 g_variant_unref (variant); |
| 261 } |
215 } | 262 } |
216 | 263 |
217 static void | 264 static void |
218 ibus_config_dconf_destroy (IBusConfigDConf *config) | 265 ibus_config_dconf_destroy (IBusConfigDConf *config) |
219 { | 266 { |
220 if (config->client) { | 267 if (config->client) { |
221 GError *error = NULL; | 268 GError *error = NULL; |
222 if (!dconf_client_unwatch (config->client, DCONF_PREFIX"/", NULL, &error
)) | 269 if (!dconf_client_unwatch (config->client, DCONF_PREFIX"/", NULL, &error
)) |
223 g_warning ("Can not unwatch dconf path %s", DCONF_PREFIX"/"); | 270 g_warning ("Can not unwatch dconf path %s", DCONF_PREFIX"/"); |
224 | 271 |
225 g_object_unref (config->client); | 272 g_object_unref (config->client); |
226 config->client = NULL; | 273 config->client = NULL; |
227 } | 274 } |
| 275 |
| 276 g_slist_free_full (config->preserve_name_prefixes, (GDestroyNotify) g_free); |
| 277 config->preserve_name_prefixes = NULL; |
228 | 278 |
229 IBUS_OBJECT_CLASS (ibus_config_dconf_parent_class)-> | 279 IBUS_OBJECT_CLASS (ibus_config_dconf_parent_class)-> |
230 destroy ((IBusObject *)config); | 280 destroy ((IBusObject *)config); |
231 } | 281 } |
232 | 282 |
233 static gboolean | 283 static gboolean |
234 ibus_config_dconf_set_value (IBusConfigService *config, | 284 ibus_config_dconf_set_value (IBusConfigService *config, |
235 const gchar *section, | 285 const gchar *section, |
236 const gchar *name, | 286 const gchar *name, |
237 GVariant *value, | 287 GVariant *value, |
238 GError **error) | 288 GError **error) |
239 { | 289 { |
240 DConfClient *client = ((IBusConfigDConf *)config)->client; | 290 IBusConfigDConf *dconf = IBUS_CONFIG_DCONF (config); |
| 291 DConfClient *client = dconf->client; |
241 gchar *path, *gpath, *gname, *gkey; | 292 gchar *path, *gpath, *gname, *gkey; |
242 gboolean retval; | 293 gboolean retval; |
243 | 294 |
244 path = g_strdup_printf (DCONF_PREFIX"/%s", section); | 295 path = g_strdup_printf (DCONF_PREFIX"/%s", section); |
245 | |
246 gpath = _to_gsettings_path (path); | 296 gpath = _to_gsettings_path (path); |
247 gname = _to_gsettings_name (name); | 297 g_free (path); |
| 298 |
| 299 if (_has_prefixes (gpath, dconf->preserve_name_prefixes)) { |
| 300 gname = (char *) name; |
| 301 } else { |
| 302 gname = _to_gsettings_name (name); |
| 303 } |
248 gkey = g_strconcat (gpath, "/", gname, NULL); | 304 gkey = g_strconcat (gpath, "/", gname, NULL); |
249 g_free (gpath); | 305 g_free (gpath); |
250 g_free (gname); | 306 if (gname != name) { |
| 307 g_free (gname); |
| 308 } |
251 | 309 |
252 retval = dconf_client_write (client, | 310 retval = dconf_client_write (client, |
253 gkey, | 311 gkey, |
254 value, | 312 value, |
255 NULL, /* tag */ | 313 NULL, /* tag */ |
256 NULL, /* cancellable */ | 314 NULL, /* cancellable */ |
257 error); | 315 error); |
258 g_free (gkey); | 316 g_free (gkey); |
259 | 317 |
260 /* notify the caller that the value has changed, as dconf does not | 318 /* notify the caller that the value has changed, as dconf does not |
261 call watch_func when the caller is the process itself */ | 319 call watch_func when the caller is the process itself */ |
262 if (retval) { | 320 if (retval) { |
263 if (value == NULL) { | 321 if (value == NULL) { |
264 /* Use a empty typle for a unset value */ | 322 /* Use a empty tuple for a unset value */ |
265 value = g_variant_new_tuple (NULL, 0); | 323 value = g_variant_new_tuple (NULL, 0); |
266 } | 324 } |
267 ibus_config_service_value_changed (config, section, name, value); | 325 ibus_config_service_value_changed (config, section, name, value); |
268 } | 326 } |
269 return retval; | 327 return retval; |
270 } | 328 } |
271 | 329 |
272 static GVariant * | 330 static GVariant * |
273 ibus_config_dconf_get_value (IBusConfigService *config, | 331 ibus_config_dconf_get_value (IBusConfigService *config, |
274 const gchar *section, | 332 const gchar *section, |
275 const gchar *name, | 333 const gchar *name, |
276 GError **error) | 334 GError **error) |
277 { | 335 { |
278 DConfClient *client = ((IBusConfigDConf *) config)->client; | 336 IBusConfigDConf *dconf = IBUS_CONFIG_DCONF (config); |
| 337 DConfClient *client = dconf->client; |
279 gchar *path, *gpath, *gname, *gkey; | 338 gchar *path, *gpath, *gname, *gkey; |
280 GVariant *variant; | 339 GVariant *variant; |
281 | 340 |
282 path = g_strdup_printf (DCONF_PREFIX"/%s", section); | 341 path = g_strdup_printf (DCONF_PREFIX"/%s", section); |
283 | |
284 gpath = _to_gsettings_path (path); | 342 gpath = _to_gsettings_path (path); |
285 gname = _to_gsettings_name (name); | 343 g_free (path); |
| 344 |
| 345 if (_has_prefixes (gpath, dconf->preserve_name_prefixes)) { |
| 346 gname = (char *) name; |
| 347 } else { |
| 348 gname = _to_gsettings_name (name); |
| 349 } |
286 gkey = g_strconcat (gpath, "/", gname, NULL); | 350 gkey = g_strconcat (gpath, "/", gname, NULL); |
287 g_free (gpath); | 351 g_free (gpath); |
288 g_free (gname); | 352 if (gname != name) { |
| 353 g_free (gname); |
| 354 } |
289 | 355 |
290 variant = dconf_client_read (client, gkey); | 356 variant = dconf_client_read (client, gkey); |
291 g_free (gkey); | 357 g_free (gkey); |
292 | 358 |
293 if (variant == NULL) { | 359 if (variant == NULL) { |
294 *error = g_error_new (G_DBUS_ERROR, G_DBUS_ERROR_FAILED, | 360 *error = g_error_new (G_DBUS_ERROR, G_DBUS_ERROR_FAILED, |
295 "Config value [%s:%s] does not exist.", section, name); | 361 "Config value [%s:%s] does not exist.", section, name); |
296 return NULL; | 362 return NULL; |
297 } | 363 } |
298 | 364 |
299 return variant; | 365 return variant; |
300 } | 366 } |
301 | 367 |
302 static GVariant * | 368 static GVariant * |
303 ibus_config_dconf_get_values (IBusConfigService *config, | 369 ibus_config_dconf_get_values (IBusConfigService *config, |
304 const gchar *section, | 370 const gchar *section, |
305 GError **error) | 371 GError **error) |
306 { | 372 { |
307 DConfClient *client = ((IBusConfigDConf *) config)->client; | 373 IBusConfigDConf *dconf = IBUS_CONFIG_DCONF (config); |
| 374 DConfClient *client = dconf->client; |
308 gchar *dir, *gdir; | 375 gchar *dir, *gdir; |
309 gint len; | 376 gint len; |
310 gchar **entries, **p; | 377 gchar **entries, **p; |
311 GVariantBuilder *builder; | 378 GVariantBuilder *builder; |
| 379 gboolean preserve_name; |
312 | 380 |
313 dir = g_strdup_printf (DCONF_PREFIX"/%s/", section); | 381 dir = g_strdup_printf (DCONF_PREFIX"/%s/", section); |
314 gdir = _to_gsettings_path (dir); | 382 gdir = _to_gsettings_path (dir); |
315 g_free (dir); | 383 g_free (dir); |
| 384 |
| 385 preserve_name = _has_prefixes (gdir, dconf->preserve_name_prefixes); |
316 | 386 |
317 entries = dconf_client_list (client, gdir, &len); | 387 entries = dconf_client_list (client, gdir, &len); |
318 builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}")); | 388 builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}")); |
319 for (p = entries; *p != NULL; p++) { | 389 for (p = entries; *p != NULL; p++) { |
320 gchar *gkey = g_strconcat (gdir, *p, NULL); | 390 gchar *gkey = g_strconcat (gdir, *p, NULL); |
321 GVariant *value = dconf_client_read (client, gkey); | 391 GVariant *value = dconf_client_read (client, gkey); |
322 g_free (gkey); | 392 g_free (gkey); |
323 if (value) { | 393 if (value) { |
324 gchar *name = _from_gsettings_name (*p); | 394 gchar *name = *p; |
| 395 if (!preserve_name) { |
| 396 name = _from_gsettings_name (*p); |
| 397 } |
325 g_variant_builder_add (builder, "{sv}", name, value); | 398 g_variant_builder_add (builder, "{sv}", name, value); |
326 g_free (name); | 399 if (name != *p) { |
| 400 g_free (name); |
| 401 } |
327 g_variant_unref (value); | 402 g_variant_unref (value); |
328 } | 403 } |
329 } | 404 } |
330 g_strfreev (entries); | 405 g_strfreev (entries); |
331 g_free (gdir); | 406 g_free (gdir); |
332 | 407 |
333 return g_variant_builder_end (builder); | 408 return g_variant_builder_end (builder); |
334 } | 409 } |
335 | 410 |
336 static gboolean | 411 static gboolean |
337 ibus_config_dconf_unset_value (IBusConfigService *config, | 412 ibus_config_dconf_unset_value (IBusConfigService *config, |
338 const gchar *section, | 413 const gchar *section, |
339 const gchar *name, | 414 const gchar *name, |
340 GError **error) | 415 GError **error) |
341 { | 416 { |
342 return ibus_config_dconf_set_value (config, section, name, NULL, error); | 417 return ibus_config_dconf_set_value (config, section, name, NULL, error); |
343 } | 418 } |
344 | 419 |
345 IBusConfigDConf * | 420 IBusConfigDConf * |
346 ibus_config_dconf_new (GDBusConnection *connection) | 421 ibus_config_dconf_new (GDBusConnection *connection) |
347 { | 422 { |
348 IBusConfigDConf *config; | 423 IBusConfigDConf *config; |
349 config = (IBusConfigDConf *) g_object_new (IBUS_TYPE_CONFIG_DCONF, | 424 config = (IBusConfigDConf *) g_object_new (IBUS_TYPE_CONFIG_DCONF, |
350 "object-path", IBUS_PATH_CONFIG, | 425 "object-path", IBUS_PATH_CONFIG, |
351 "connection", connection, | 426 "connection", connection, |
352 NULL); | 427 NULL); |
353 return config; | 428 return config; |
354 } | 429 } |
LEFT | RIGHT |