[glib/new-gsettings] lots of schemas changes



commit a07b0fc2edb7c324cac4433eadb3ac37a29dec6f
Author: Ryan Lortie <desrt desrt ca>
Date:   Thu Apr 15 13:10:45 2010 -0400

    lots of schemas changes

 docs/reference/gio/Makefile.am |    4 +-
 gio/gschema-compile.c          |   97 +++++++++++++++++++++++++++++++---------
 gio/gsettings.c                |   71 ++++++++++++++++++-----------
 gio/gsettingsschema.c          |   55 +++++++++++-----------
 gio/gvdb/gvdb-builder.c        |   40 +++++++++++++++-
 gio/gvdb/gvdb-builder.h        |    3 +
 gio/gvdb/gvdb-format.h         |   26 +++++++++++
 gio/gvdb/gvdb-reader.c         |    2 +
 gio/gvdb/gvdb-reader.h         |    2 +
 9 files changed, 217 insertions(+), 83 deletions(-)
---
diff --git a/docs/reference/gio/Makefile.am b/docs/reference/gio/Makefile.am
index fcc7890..9ea1904 100644
--- a/docs/reference/gio/Makefile.am
+++ b/docs/reference/gio/Makefile.am
@@ -126,11 +126,11 @@ include $(top_srcdir)/gtk-doc.make
 EXTRA_DIST +=			\
 	version.xml.in
 
+if ENABLE_MAN
+
 man_MANS =			\
 	gschema-compile.1
 
-if ENABLE_MAN
-
 %.1 : xml/%.xml
 	@XSLTPROC@ -nonet http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
 
diff --git a/gio/gschema-compile.c b/gio/gschema-compile.c
index 105bf86..2a7f283 100644
--- a/gio/gschema-compile.c
+++ b/gio/gschema-compile.c
@@ -7,6 +7,9 @@
 
 typedef struct
 {
+  gboolean byteswap;
+
+  GVariantBuilder key_options;
   GHashTable *schemas;
   gchar *schemalist_domain;
 
@@ -20,7 +23,8 @@ typedef struct
   GVariant *value;
   GVariant *min, *max;
   GVariant *strings;
-  gchar *l10n;
+  gchar l10n;
+  gchar *context;
   GVariantType *type;
 } ParseState;
 
@@ -112,6 +116,9 @@ start_element (GMarkupParseContext  *context,
                 g_set_error (error, G_MARKUP_ERROR,
                              G_MARKUP_ERROR_INVALID_CONTENT,
                              "invalid GVariant type string");
+
+              g_variant_builder_init (&state->key_options,
+                                      G_VARIANT_TYPE ("a{sv}"));
             }
 
           return;
@@ -143,9 +150,12 @@ start_element (GMarkupParseContext  *context,
     {
       if (strcmp (element_name, "default") == 0)
         {
-          if (COLLECT (STRDUP | OPTIONAL, "l10n", &state->l10n))
+          const gchar *l10n;
+
+          if (COLLECT (STRING | OPTIONAL, "l10n", &l10n,
+                       STRDUP | OPTIONAL, "context", &state->context))
             {
-              if (state->l10n != NULL)
+              if (l10n != NULL)
                 {
                   if (!g_hash_table_lookup (state->schema, ".gettext-domain"))
                     {   
@@ -166,22 +176,36 @@ start_element (GMarkupParseContext  *context,
 			                             ".gettext-domain",
 						     domain);
 
-                      /* XXX: todo: check l10n category validity */
+                      if (strcmp (l10n, "messages") == 0)
+                        state->l10n = 'm';
+                      else if (strcmp (l10n, "time") == 0)
+                        state->l10n = 't';
+                      else
+                        g_set_error (error, G_MARKUP_ERROR,
+                                     G_MARKUP_ERROR_INVALID_CONTENT,
+                                     "unsupported l10n category: %s", l10n);
                     }
                 }
+              else
+                {
+                  state->l10n = '\0';
+
+                   if (state->context != NULL)
+                     g_set_error (error, G_MARKUP_ERROR,
+                                  G_MARKUP_ERROR_INVALID_CONTENT,
+                                  "translation context given for "
+                                  " value without l10n enabled");
+                }
 
               state->string = g_string_new (NULL);
             }
 
           return;
         }
-      else if (strcmp (element_name, "summary") == 0)
-        {
-          NO_ARGS ();
-          return;
-        }
-      else if (strcmp (element_name, "description") == 0)
+      else if (strcmp (element_name, "summary") == 0 ||
+               strcmp (element_name, "description") == 0)
         {
+          state->string = g_string_new (NULL);
           NO_ARGS ();
           return;
         }
@@ -238,18 +262,46 @@ end_element (GMarkupParseContext  *context,
   if (strcmp (element_name, "default") == 0)
     {
       state->value = g_variant_parse (state->type, state->string->str,
-                                      state->string->str + state->string->len,
-                                      NULL, error);
+                                      NULL, NULL, error);
+
+      if (state->l10n)
+        {
+          if (state->context)
+            {
+              gint len;
+
+              /* Contextified messages are supported by prepending the
+               * context, followed by '\004' to the start of the message
+               * string.  We do that here to save GSettings the work
+               * later on.
+               *
+               * Note: we are about to g_free() the context anyway...
+               */
+              len = strlen (state->context);
+              state->context[len] = '\004';
+              g_string_prepend_len (state->string, state->context, len + 1);
+            }
+
+          g_variant_builder_add (&state->key_options, "{sv}", "l10n",
+                                 g_variant_new ("(ys)",
+                                                state->l10n,
+                                                state->string->str));
+        }
+
+      g_string_free (state->string, TRUE);
+      g_free (state->context);
     }
 
   else if (strcmp (element_name, "key") == 0)
     {
-      if (state->l10n)
-        gvdb_item_set_options (state->key,
-                               g_variant_new_parsed ("{'l10n': < %s >}",
-                                                     state->l10n));
       gvdb_item_set_value (state->key, state->value);
+      gvdb_item_set_options (state->key,
+                             g_variant_builder_end (&state->key_options));
     }
+
+  else if (strcmp (element_name, "summary") == 0 ||
+           strcmp (element_name, "description") == 0)
+    g_string_free (state->string, TRUE);
 }
 
 static void
@@ -278,12 +330,13 @@ text (GMarkupParseContext  *context,
 }
 
 static GHashTable *
-parse_gschema_files (gchar  **files,
-                     GError **error)
+parse_gschema_files (gchar    **files,
+                     gboolean   byteswap,
+                     GError   **error)
 {
   GMarkupParser parser = { start_element, end_element, text };
   GMarkupParseContext *context;
-  ParseState state = { 0, };
+  ParseState state = { byteswap, };
   const gchar *filename;
 
   context = g_markup_parse_context_new (&parser,
@@ -318,6 +371,7 @@ parse_gschema_files (gchar  **files,
 int
 main (int argc, char **argv)
 {
+  gboolean byteswap = G_BYTE_ORDER != G_LITTLE_ENDIAN;
   GError *error = NULL;
   GHashTable *table;
   glob_t matched;
@@ -382,9 +436,8 @@ main (int argc, char **argv)
       return 1;
     }
 
-  /* FIXME: need a way to specify the output location, for !srcdir builds */
-  if (!(table = parse_gschema_files (matched.gl_pathv, &error)) ||
-      !gvdb_table_write_contents (table, target, &error))
+  if (!(table = parse_gschema_files (matched.gl_pathv, byteswap, &error)) ||
+      !gvdb_table_write_contents (table, target, byteswap, &error))
     {
       fprintf (stderr, "%s\n", error->message);
       return 1;
diff --git a/gio/gsettings.c b/gio/gsettings.c
index 1e16dd6..b69cd73 100644
--- a/gio/gsettings.c
+++ b/gio/gsettings.c
@@ -658,9 +658,10 @@ GVariant *
 g_settings_get_value (GSettings   *settings,
                       const gchar *key)
 {
+  const gchar *unparsed = NULL;
   GVariant *value, *options;
   const GVariantType *type;
-  gint lc_category = -1;
+  gchar lc_char = '\0';
   GVariant *sval;
   gchar *path;
 
@@ -670,6 +671,11 @@ g_settings_get_value (GSettings   *settings,
     g_error ("schema '%s' does not contain a key named '%s'\n",
              settings->priv->schema_name, key);
 
+  path = g_strconcat (settings->priv->path, key, NULL);
+  type = g_variant_get_type (sval);
+  value = g_settings_backend_read (settings->priv->backend, path, type);
+  g_free (path);
+
   if (options != NULL)
     {
       GVariantIter iter;
@@ -677,50 +683,59 @@ g_settings_get_value (GSettings   *settings,
       GVariant *value;
 
       g_variant_iter_init (&iter, options);
-      while (g_variant_iter_loop (&iter, "{sv}", &key, &value))
+      while (g_variant_iter_loop (&iter, "{&sv}", &key, &value))
         {
-          if (strcmp (key, "l10n") == 0 &&
-              g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
-            {
-              const gchar *category = g_variant_get_string (value, NULL);
-
-              if (strcmp (category, "messages") == 0)
-                lc_category = LC_MESSAGES;
-              else if (strcmp (category, "time") == 0)
-                lc_category = LC_TIME;
-              else
-                g_error ("schema requests unsupported l10n category: %s",
-                         category);
-            }
+          if (strcmp (key, "l10n") == 0 && value == NULL)
+            g_variant_get (value, "(y&s)", &lc_char, &unparsed);
+          else
+            g_warning ("unknown schema extension '%s'", key);
         }
     }
 
-  path = g_strconcat (settings->priv->path, key, NULL);
-  type = g_variant_get_type (sval);
-  value = g_settings_backend_read (settings->priv->backend, path, type);
-  g_free (path);
-
   if (value && !g_variant_is_of_type (value, type))
     {
       g_variant_unref (value);
       value = NULL;
     }
 
-  if (value == NULL)
+  if (value == NULL && lc_char != '\0')
+  /* we will need to translate the schema default value */
     {
+      const gchar *translated;
+      GError *error = NULL;
+      const gchar *domain;
+      gint lc_category;
+      gchar category;
 
-      if (lc_category != -1)
+      domain = g_settings_schema_get_gettext_domain (settings->priv->schema);
+      g_variant_get (value, "(y&s)", &category, &unparsed);
+
+      if (lc_char == 't')
+        lc_category = LC_TIME;
+      else
+        lc_category = LC_MESSAGES;
+
+      translated = dcgettext (domain, unparsed, lc_category);
+
+      if (translated != unparsed)
+        /* it was translated, so we need to re-parse it */
         {
-          const gchar *domain;
+          value = g_variant_parse (g_variant_get_type (sval),
+                                   translated, NULL, NULL, &error);
 
-          domain = g_settings_schema_get_gettext_domain (settings->priv->schema);
+          if (value == NULL)
+            {
+              g_warning ("Failed to parse translated string `%s' for "
+                         "key `%s' in schema `%s': %s", unparsed, key,
+                         settings->priv->schema_name, error->message);
+              g_warning ("Using untranslated default instead.");
+              g_error_free (error);
 
-          value = g_variant_ref_sink (g_variant_new_string (
-            dcgettext (domain,
-                       g_variant_get_string (sval, NULL),
-                       lc_category)));
+              value = g_variant_ref (sval);
+            }
         }
       else
+        /* the string was untranslated, so just use the pre-parsed one */
         value = g_variant_ref (sval);
     }
 
diff --git a/gio/gsettingsschema.c b/gio/gsettingsschema.c
index f4103cc..910e1b5 100644
--- a/gio/gsettingsschema.c
+++ b/gio/gsettingsschema.c
@@ -30,6 +30,8 @@ G_DEFINE_TYPE (GSettingsSchema, g_settings_schema, G_TYPE_OBJECT)
 
 struct _GSettingsSchemaPrivate
 {
+  const gchar *gettext_domain;
+  const gchar *path;
   GvdbTable *table;
   gchar *name;
 };
@@ -109,6 +111,22 @@ g_settings_schema_class_init (GSettingsSchemaClass *class)
   g_type_class_add_private (class, sizeof (GSettingsSchemaPrivate));
 }
 
+static const gchar *
+g_settings_schema_get_string (GSettingsSchema *schema,
+                              const gchar     *key)
+{
+  const gchar *result = NULL;
+  GVariant *value;
+
+  if ((value = g_settings_schema_get_value (schema, key, NULL)))
+    {
+      result = g_variant_get_string (value, NULL);
+      g_variant_unref (value);
+    }
+
+  return result;
+}
+
 GSettingsSchema *
 g_settings_schema_new (const gchar *name)
 {
@@ -132,6 +150,13 @@ g_settings_schema_new (const gchar *name)
   schema = g_object_new (G_TYPE_SETTINGS_SCHEMA, NULL);
   schema->priv->name = g_strdup (name);
   schema->priv->table = table;
+  schema->priv->path =
+    g_settings_schema_get_string (schema, ".path");
+  schema->priv->gettext_domain =
+    g_settings_schema_get_string (schema, ".gettext-domain");
+
+  if (schema->priv->gettext_domain)
+    bind_textdomain_codeset (schema->priv->gettext_domain, "UTF-8");
 
   return schema;
 }
@@ -147,39 +172,13 @@ g_settings_schema_get_value (GSettingsSchema  *schema,
 const gchar *
 g_settings_schema_get_path (GSettingsSchema *schema)
 {
-  const gchar *result;
-  GVariant *value;
-
-  value = gvdb_table_get_value (schema->priv->table, ".path", NULL);
-
-  if (value && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
-    {
-      result = g_variant_get_string (value, NULL);
-      g_variant_unref (value);
-    }
-  else
-    result = NULL;
-
-  return result;
+  return schema->priv->path;
 }
 
 const gchar *
 g_settings_schema_get_gettext_domain (GSettingsSchema *schema)
 {
-  const gchar *result;
-  GVariant *value;
-
-  value = gvdb_table_get_value (schema->priv->table, ".gettext-domain", NULL);
-
-  if (value && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
-    {
-      result = g_variant_get_string (value, NULL);
-      g_variant_unref (value);
-    }
-  else
-    result = NULL;
-
-  return result;
+  return schema->priv->gettext_domain;
 }
 
 gboolean
diff --git a/gio/gvdb/gvdb-builder.c b/gio/gvdb/gvdb-builder.c
index a59772b..290309c 100644
--- a/gio/gvdb/gvdb-builder.c
+++ b/gio/gvdb/gvdb-builder.c
@@ -1,3 +1,24 @@
+/*
+ * Copyright © 2010 Codethink Limited
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the licence, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Ryan Lortie <desrt desrt ca>
+ */
+
 #include "gvdb-builder.h"
 #include "gvdb-format.h"
 
@@ -444,10 +465,22 @@ file_builder_new (void)
 
 static GString *
 file_builder_serialise (FileBuilder          *fb,
-                        struct gvdb_pointer   root)
+                        struct gvdb_pointer   root,
+                        gboolean              byteswap)
 {
-  struct gvdb_header header = { { GVDB_SIGNATURE0, GVDB_SIGNATURE1 } };
   GString *result = g_string_new (NULL);
+  struct gvdb_header header;
+
+  if (byteswap)
+    {
+      header.signature[0] = GUINT32_TO_LE (GVDB_SIGNATURE0);
+      header.signature[1] = GUINT32_TO_LE (GVDB_SIGNATURE1);
+    }
+  else
+    {
+      header.signature[0] = GVDB_SIGNATURE0;
+      header.signature[1] = GVDB_SIGNATURE1;
+    }
 
   result = g_string_new (NULL);
 
@@ -482,6 +515,7 @@ file_builder_serialise (FileBuilder          *fb,
 gboolean
 gvdb_table_write_contents (GHashTable   *table,
                            const gchar  *filename,
+                           gboolean      byteswap,
                            GError      **error)
 {
   struct gvdb_pointer root;
@@ -491,7 +525,7 @@ gvdb_table_write_contents (GHashTable   *table,
 
   fb = file_builder_new ();
   file_builder_add_hash (fb, table, &root);
-  str = file_builder_serialise (fb, root);
+  str = file_builder_serialise (fb, root, byteswap);
 
   status = g_file_set_contents (filename, str->str, str->len, error);
   g_string_free (str, TRUE);
diff --git a/gio/gvdb/gvdb-builder.h b/gio/gvdb/gvdb-builder.h
index d1a3eac..c0d3b30 100644
--- a/gio/gvdb/gvdb-builder.h
+++ b/gio/gvdb/gvdb-builder.h
@@ -15,6 +15,8 @@
  * License along with this library; if not, write to the
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
+ *
+ * Author: Ryan Lortie <desrt desrt ca>
  */
 
 #ifndef __gvdb_builder_h__
@@ -52,6 +54,7 @@ void                    gvdb_item_set_parent                            (GvdbIte
 G_GNUC_INTERNAL
 gboolean                gvdb_table_write_contents                       (GHashTable     *table,
                                                                          const gchar    *filename,
+                                                                         gboolean        byteswap,
                                                                          GError        **error);
 
 #endif /* __gvdb_builder_h__ */
diff --git a/gio/gvdb/gvdb-format.h b/gio/gvdb/gvdb-format.h
index 73d15b7..e90a4bc 100644
--- a/gio/gvdb/gvdb-format.h
+++ b/gio/gvdb/gvdb-format.h
@@ -1,3 +1,27 @@
+/*
+ * Copyright © 2010 Codethink Limited
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the licence, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Ryan Lortie <desrt desrt ca>
+ */
+
+#ifndef __gvdb_format_h__
+#define __gvdb_format_h__
+
 #include <glib.h>
 
 typedef struct { guint16 __value; } guint16_le;
@@ -59,3 +83,5 @@ static inline guint16 guint16_from_le (guint16_le value) {
 
 #define GVDB_SIGNATURE0 1918981703
 #define GVDB_SIGNATURE1 1953390953
+
+#endif /* __gvdb_format_h__ */
diff --git a/gio/gvdb/gvdb-reader.c b/gio/gvdb/gvdb-reader.c
index c4ea31b..7fe3d46 100644
--- a/gio/gvdb/gvdb-reader.c
+++ b/gio/gvdb/gvdb-reader.c
@@ -15,6 +15,8 @@
  * License along with this library; if not, write to the
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
+ *
+ * Author: Ryan Lortie <desrt desrt ca>
  */
 
 #include "gvdb-reader.h"
diff --git a/gio/gvdb/gvdb-reader.h b/gio/gvdb/gvdb-reader.h
index fe63e55..03ef97a 100644
--- a/gio/gvdb/gvdb-reader.h
+++ b/gio/gvdb/gvdb-reader.h
@@ -15,6 +15,8 @@
  * License along with this library; if not, write to the
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
+ *
+ * Author: Ryan Lortie <desrt desrt ca>
  */
 
 #ifndef __gvdb_reader_h__



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]