Make gsettings-tool translatable again
[platform/upstream/glib.git] / gio / gsettings-tool.c
1 /*
2  * Copyright © 2010 Codethink Limited
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the licence, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  *
19  * Author: Ryan Lortie <desrt@desrt.ca>
20  */
21
22 #include "config.h"
23
24 #include <gio/gio.h>
25 #include <gi18n.h>
26 #include <locale.h>
27 #include <string.h>
28 #include <stdlib.h>
29
30 static gboolean
31 contained (const gchar * const *items,
32            const gchar         *item)
33 {
34   while (*items)
35     if (strcmp (*items++, item) == 0)
36       return TRUE;
37
38   return FALSE;
39 }
40
41 static gboolean
42 is_schema (const gchar *schema)
43 {
44   return contained (g_settings_list_schemas (), schema);
45 }
46
47 static gboolean
48 is_relocatable_schema (const gchar *schema)
49 {
50   return contained (g_settings_list_relocatable_schemas (), schema);
51 }
52
53 static gboolean
54 check_relocatable_schema (const gchar *schema)
55 {
56   if (is_relocatable_schema (schema))
57     return TRUE;
58
59   if (is_schema (schema))
60     g_printerr (_("Schema '%s' is not relocatable "
61                   "(path must not be specified)\n"),
62                 schema);
63
64   else
65     g_printerr (_("No such schema '%s'\n"), schema);
66
67   return FALSE;
68 }
69
70 static gboolean
71 check_schema (const gchar *schema)
72 {
73   if (is_schema (schema))
74     return TRUE;
75
76   if (is_relocatable_schema (schema))
77     g_printerr (_("Schema '%s' is relocatable "
78                   "(path must be specified)\n"),
79                 schema);
80
81   else
82     g_printerr (_("No such schema '%s'\n"), schema);
83
84   return FALSE;
85 }
86
87 static gboolean
88 check_path (const gchar *path)
89 {
90   if (path[0] == '\0')
91     {
92       g_printerr (_("Empty path given.\n"));
93       return FALSE;
94     }
95
96   if (path[0] != '/')
97     {
98       g_printerr (_("Path must begin with a slash (/)\n"));
99       return FALSE;
100     }
101
102   if (!g_str_has_suffix (path, "/"))
103     {
104       g_printerr (_("Path must end with a slash (/)\n"));
105       return FALSE;
106     }
107
108   if (strstr (path, "//"))
109     {
110       g_printerr (_("Path must not contain two adjacent slashes (//)\n"));
111       return FALSE;
112     }
113
114   return TRUE;
115 }
116
117 static gboolean
118 check_key (GSettings   *settings,
119            const gchar *key)
120 {
121   gboolean good;
122   gchar **keys;
123
124   keys = g_settings_list_keys (settings);
125   good = contained ((const gchar **) keys, key);
126   g_strfreev (keys);
127
128   if (good)
129     return TRUE;
130
131   g_printerr (_("No such key '%s'\n"), key);
132
133   return FALSE;
134 }
135
136 static void
137 output_list (const gchar * const *list)
138 {
139   gint i;
140
141   for (i = 0; list[i]; i++)
142     g_print ("%s\n", list[i]);
143 }
144
145 static void
146 gsettings_list_schemas (GSettings   *settings,
147                         const gchar *key,
148                         const gchar *value)
149 {
150   output_list (g_settings_list_schemas ());
151 }
152
153 static void
154 gsettings_list_relocatable_schemas (GSettings   *settings,
155                                     const gchar *key,
156                                     const gchar *value)
157 {
158   output_list (g_settings_list_relocatable_schemas ());
159 }
160
161 static void
162 gsettings_list_keys (GSettings   *settings,
163                      const gchar *key,
164                      const gchar *value)
165 {
166   gchar **keys;
167
168   keys = g_settings_list_keys (settings);
169   output_list ((const gchar **) keys);
170   g_strfreev (keys);
171 }
172
173 static void
174 gsettings_list_children (GSettings   *settings,
175                          const gchar *key,
176                          const gchar *value)
177 {
178   gchar **children;
179   gint max = 0;
180   gint i;
181
182   children = g_settings_list_children (settings);
183   for (i = 0; children[i]; i++)
184     if (strlen (children[i]) > max)
185       max = strlen (children[i]);
186
187   for (i = 0; children[i]; i++)
188     {
189       GSettings *child;
190       gchar *schema;
191       gchar *path;
192
193       child = g_settings_get_child (settings, children[i]);
194       g_object_get (child,
195                     "schema", &schema,
196                     "path", &path,
197                     NULL);
198
199       if (is_schema (schema))
200         g_print ("%-*s   %s\n", max, children[i], schema);
201       else
202         g_print ("%-*s   %s:%s\n", max, children[i], schema, path);
203
204       g_object_unref (child);
205       g_free (schema);
206       g_free (path);
207     }
208
209   g_strfreev (children);
210 }
211
212 static void
213 gsettings_range (GSettings   *settings,
214                  const gchar *key,
215                  const gchar *value)
216 {
217   GVariant *range, *detail;
218   const gchar *type;
219
220   range = g_settings_get_range (settings, key);
221   g_variant_get (range, "(&sv)", &type, &detail);
222
223   if (strcmp (type, "type") == 0)
224     g_print ("type %s\n", g_variant_get_type_string (detail) + 1);
225
226   else if (strcmp (type, "range") == 0)
227     {
228       GVariant *min, *max;
229       gchar *smin, *smax;
230
231       g_variant_get (detail, "(**)", &min, &max);
232       smin = g_variant_print (min, FALSE);
233       smax = g_variant_print (max, FALSE);
234
235       g_print ("range %s %s %s\n",
236                g_variant_get_type_string (min), smin, smax);
237       g_variant_unref (min);
238       g_variant_unref (max);
239       g_free (smin);
240       g_free (smax);
241     }
242
243   else if (strcmp (type, "enum") == 0 || strcmp (type, "flags") == 0)
244     {
245       GVariantIter iter;
246       GVariant *item;
247
248       g_print ("%s\n", type);
249
250       g_variant_iter_init (&iter, detail);
251       while (g_variant_iter_loop (&iter, "*", &item))
252         {
253           gchar *printed;
254
255           printed = g_variant_print (item, FALSE);
256           g_print ("%s\n", printed);
257           g_free (printed);
258         }
259     }
260
261   g_variant_unref (detail);
262   g_variant_unref (range);
263 }
264
265 static void
266 gsettings_get (GSettings   *settings,
267                const gchar *key,
268                const gchar *value_)
269 {
270   GVariant *value;
271   gchar *printed;
272
273   value = g_settings_get_value (settings, key);
274   printed = g_variant_print (value, TRUE);
275   g_print ("%s\n", printed);
276   g_variant_unref (value);
277   g_free (printed);
278 }
279
280 static void
281 gsettings_reset (GSettings   *settings,
282                  const gchar *key,
283                  const gchar *value)
284 {
285   g_settings_reset (settings, key);
286   g_settings_sync ();
287 }
288
289 static void
290 gsettings_writable (GSettings   *settings,
291                     const gchar *key,
292                     const gchar *value)
293 {
294   g_print ("%s\n",
295            g_settings_is_writable (settings, key) ?
296            "true" : "false");
297 }
298
299 static void
300 value_changed (GSettings   *settings,
301                const gchar *key,
302                gpointer     user_data)
303 {
304   GVariant *value;
305   gchar *printed;
306
307   value = g_settings_get_value (settings, key);
308   printed = g_variant_print (value, TRUE);
309   g_print ("%s: %s\n", key, printed);
310   g_variant_unref (value);
311   g_free (printed);
312 }
313
314 static void
315 gsettings_monitor (GSettings   *settings,
316                    const gchar *key,
317                    const gchar *value)
318 {
319   if (key)
320     {
321       gchar *name;
322
323       name = g_strdup_printf ("changed::%s", key);
324       g_signal_connect (settings, name, G_CALLBACK (value_changed), NULL);
325     }
326   else
327     g_signal_connect (settings, "changed", G_CALLBACK (value_changed), NULL);
328
329   g_main_loop_run (g_main_loop_new (NULL, FALSE));
330 }
331
332 static void
333 gsettings_set (GSettings   *settings,
334                const gchar *key,
335                const gchar *value)
336 {
337   const GVariantType *type;
338   GError *error = NULL;
339   GVariant *existing;
340   GVariant *new;
341
342   existing = g_settings_get_value (settings, key);
343   type = g_variant_get_type (existing);
344
345   new = g_variant_parse (type, value, NULL, NULL, &error);
346
347   if (new == NULL)
348     {
349       g_printerr ("%s\n", error->message);
350       exit (1);
351     }
352
353   if (!g_settings_range_check (settings, key, new))
354     {
355       g_printerr (_("The provided value is outside of the valid range\n"));
356       g_variant_unref (new);
357       exit (1);
358     }
359
360   g_settings_set_value (settings, key, new);
361   g_variant_unref (existing);
362   g_variant_unref (new);
363
364   g_settings_sync ();
365 }
366
367 static int
368 gsettings_help (gboolean     requested,
369                 const gchar *command)
370 {
371   const gchar *description;
372   const gchar *synopsis;
373   GString *string;
374
375   string = g_string_new (NULL);
376
377   if (command == NULL)
378     ;
379
380   else if (strcmp (command, "list-schemas") == 0)
381     {
382       description = _("List the installed (non-relocatable) schemas");
383       synopsis = "";
384     }
385
386   else if (strcmp (command, "list-relocatable-schemas") == 0)
387     {
388       description = _("List the installed relocatable schemas");
389       synopsis = "";
390     }
391
392   else if (strcmp (command, "list-keys") == 0)
393     {
394       description = _("Lists the keys in SCHEMA");
395       synopsis = N_("SCHEMA[:PATH]");
396     }
397
398   else if (strcmp (command, "list-children") == 0)
399     {
400       description = _("Lists the children of SCHEMA");
401       synopsis = N_("SCHEMA[:PATH]");
402     }
403
404   else if (strcmp (command, "get") == 0)
405     {
406       description = _("Gets the value of KEY");
407       synopsis = N_("SCHEMA[:PATH] KEY");
408     }
409
410   else if (strcmp (command, "range") == 0)
411     {
412       description = _("Queries the range of valid values for KEY");
413       synopsis = N_("SCHEMA[:PATH] KEY");
414     }
415
416   else if (strcmp (command, "set") == 0)
417     {
418       description = _("Sets the value of KEY to VALUE");
419       synopsis = N_("SCHEMA[:PATH] KEY VALUE");
420     }
421
422   else if (strcmp (command, "reset") == 0)
423     {
424       description = _("Resets KEY to its default value");
425       synopsis = N_("SCHEMA[:PATH] KEY");
426     }
427
428   else if (strcmp (command, "writable") == 0)
429     {
430       description = _("Checks if KEY is writable");
431       synopsis = N_("SCHEMA[:PATH] KEY");
432     }
433
434   else if (strcmp (command, "monitor") == 0)
435     {
436       description = _("Monitors KEY for changes.\n"
437                     "If no KEY is specified, monitor all keys in SCHEMA.\n"
438                     "Use ^C to stop monitoring.\n");
439       synopsis = N_("SCHEMA[:PATH] [KEY]");
440     }
441   else
442     {
443       g_string_printf (string, _("Unknown command %s\n\n"), command);
444       requested = FALSE;
445       command = NULL;
446     }
447
448   if (command == NULL)
449     {
450       g_string_append (string,
451       _("Usage:\n"
452         "  gsettings COMMAND [ARGS...]\n"
453         "\n"
454         "Commands:\n"
455         "  help                      Show this information\n"
456         "  list-schemas              List installed schemas\n"
457         "  list-relocatable-schemas  List relocatable schemas\n"
458         "  list-keys                 List keys in a schema\n"
459         "  list-children             List children of a schema\n"
460         "  range                     Queries the range of a key\n"
461         "  get                       Get the value of a key\n"
462         "  set                       Set the value of a key\n"
463         "  reset                     Reset the value of a key\n"
464         "  writable                  Check if a key is writable\n"
465         "  monitor                   Watch for changes\n"
466         "\n"
467         "Use 'gsettings help COMMAND' to get detailed help.\n\n"));
468     }
469   else
470     {
471       g_string_append_printf (string, _("Usage:\n  gsettings %s %s\n\n%s\n\n"),
472                               command, _(synopsis), description);
473
474       if (synopsis[0])
475         {
476           g_string_append (string, _("Arguments:\n"));
477
478           if (strstr (synopsis, "SCHEMA"))
479             g_string_append (string,
480                            _("  SCHEMA    The name of the schema\n"
481                              "  PATH      The path, for relocatable schemas\n"));
482
483           if (strstr (synopsis, "[KEY]"))
484             g_string_append (string,
485                            _("  KEY       The (optional) key within the schema\n"));
486
487           else if (strstr (synopsis, "KEY"))
488             g_string_append (string,
489                            _("  KEY       The key within the schema\n"));
490
491           if (strstr (synopsis, "VALUE"))
492             g_string_append (string,
493                            _("  VALUE     The value to set\n"));
494
495           g_string_append (string, "\n");
496         }
497     }
498
499   if (requested)
500     g_print ("%s", string->str);
501   else
502     g_printerr ("%s", string->str);
503
504   g_string_free (string, TRUE);
505
506   return requested ? 0 : 1;
507 }
508
509
510 int
511 main (int argc, char **argv)
512 {
513   void (* function) (GSettings *, const gchar *, const gchar *);
514   GSettings *settings;
515   const gchar *key;
516
517   setlocale (LC_ALL, "");
518
519   if (argc < 2)
520     return gsettings_help (FALSE, NULL);
521
522   else if (strcmp (argv[1], "help") == 0)
523     return gsettings_help (TRUE, argv[2]);
524
525   else if (argc == 2 && strcmp (argv[1], "list-schemas") == 0)
526     function = gsettings_list_schemas;
527
528   else if (argc == 2 && strcmp (argv[1], "list-relocatable-schemas") == 0)
529     function = gsettings_list_relocatable_schemas;
530
531   else if (argc == 3 && strcmp (argv[1], "list-keys") == 0)
532     function = gsettings_list_keys;
533
534   else if (argc == 3 && strcmp (argv[1], "list-children") == 0)
535     function = gsettings_list_children;
536
537   else if (argc == 4 && strcmp (argv[1], "range") == 0)
538     function = gsettings_range;
539
540   else if (argc == 4 && strcmp (argv[1], "get") == 0)
541     function = gsettings_get;
542
543   else if (argc == 5 && strcmp (argv[1], "set") == 0)
544     function = gsettings_set;
545
546   else if (argc == 4 && strcmp (argv[1], "reset") == 0)
547     function = gsettings_reset;
548
549   else if (argc == 4 && strcmp (argv[1], "writable") == 0)
550     function = gsettings_writable;
551
552   else if ((argc == 3 || argc == 4) && strcmp (argv[1], "monitor") == 0)
553     function = gsettings_monitor;
554
555   else
556     return gsettings_help (FALSE, argv[1]);
557
558   g_type_init ();
559
560   if (argc > 2)
561     {
562       gchar **parts;
563
564       if (argv[2][0] == '\0')
565         {
566           g_printerr (_("Empty schema name given"));
567           return 1;
568         }
569
570       parts = g_strsplit (argv[2], ":", 2);
571
572       if (parts[1])
573         {
574           if (!check_relocatable_schema (parts[0]) || !check_path (parts[1]))
575             return 1;
576
577           settings = g_settings_new_with_path (parts[0], parts[1]);
578         }
579       else
580         {
581           if (!check_schema (parts[0]))
582             return 1;
583
584           settings = g_settings_new (parts[0]);
585         }
586
587       g_strfreev (parts);
588     }
589   else
590     settings = NULL;
591
592   if (argc > 3)
593     {
594       if (!check_key (settings, argv[3]))
595         return 1;
596
597       key = argv[3];
598     }
599   else
600     key = NULL;
601
602   (* function) (settings, key, argc > 4 ? argv[4] : NULL);
603
604   if (settings != NULL)
605     g_object_unref (settings);
606
607   return 0;
608 }