[gnome-desktop] gnome-xkb-info: Parse XKB options
- From: Bastien Nocera <hadess src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-desktop] gnome-xkb-info: Parse XKB options
- Date: Sat, 18 Aug 2012 15:18:17 +0000 (UTC)
commit 871601119af2646350732f32b531aa08ea0c6da9
Author: Rui Matos <tiagomatos gmail com>
Date: Fri Jul 6 18:38:41 2012 +0200
gnome-xkb-info: Parse XKB options
And offer public API to get at them.
https://bugzilla.gnome.org/show_bug.cgi?id=682004
configure.ac | 2 +-
libgnome-desktop/gnome-xkb-info.c | 233 ++++++++++++++++++++++++++++++++++++-
libgnome-desktop/gnome-xkb-info.h | 6 +
libgnome-desktop/test-xkb-info.c | 24 ++++
4 files changed, 263 insertions(+), 2 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 6d6e842..5324b97 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,6 @@
m4_define(gnome_platform, 3)
m4_define(gnome_minor, 5)
-m4_define(gnome_micro, 5)
+m4_define(gnome_micro, 6)
dnl gnome_sub is an optional sub-version which will not be advertised to the user
dnl It allows to release a 2.30.1.1 which is just a better 2.30.1
dnl Leave empty if not needed
diff --git a/libgnome-desktop/gnome-xkb-info.c b/libgnome-desktop/gnome-xkb-info.c
index 7923589..1e47a45 100644
--- a/libgnome-desktop/gnome-xkb-info.c
+++ b/libgnome-desktop/gnome-xkb-info.c
@@ -57,13 +57,32 @@ struct _Layout
const Layout *main_layout;
};
+typedef struct _XkbOption XkbOption;
+struct _XkbOption
+{
+ gchar *id;
+ gchar *description;
+};
+
+typedef struct _XkbOptionGroup XkbOptionGroup;
+struct _XkbOptionGroup
+{
+ gchar *id;
+ gchar *description;
+ gboolean allow_multiple_selection;
+ GHashTable *options_table;
+};
+
struct _GnomeXkbInfoPrivate
{
+ GHashTable *option_groups_table;
GHashTable *layouts_by_short_desc;
GHashTable *layouts_by_iso639;
GHashTable *layouts_table;
/* Only used while parsing */
+ XkbOptionGroup *current_parser_group;
+ XkbOption *current_parser_option;
Layout *current_parser_layout;
Layout *current_parser_variant;
gchar *current_parser_iso639Id;
@@ -86,6 +105,31 @@ free_layout (gpointer data)
g_free (layout);
}
+static void
+free_option (gpointer data)
+{
+ XkbOption *option = data;
+
+ g_return_if_fail (option != NULL);
+
+ g_free (option->id);
+ g_free (option->description);
+ g_free (option);
+}
+
+static void
+free_option_group (gpointer data)
+{
+ XkbOptionGroup *group = data;
+
+ g_return_if_fail (group != NULL);
+
+ g_free (group->id);
+ g_free (group->description);
+ g_hash_table_destroy (group->options_table);
+ g_free (group);
+}
+
/**
* gnome_xkb_info_get_var_defs: (skip)
* @rules: (out) (transfer full): location to store the rules file
@@ -197,6 +241,10 @@ parse_start_element (GMarkupParseContext *context,
priv->current_parser_text = &priv->current_parser_variant->xkb_name;
else if (priv->current_parser_layout)
priv->current_parser_text = &priv->current_parser_layout->xkb_name;
+ else if (priv->current_parser_option)
+ priv->current_parser_text = &priv->current_parser_option->id;
+ else if (priv->current_parser_group)
+ priv->current_parser_text = &priv->current_parser_group->id;
}
else if (strcmp (element_name, "description") == 0)
{
@@ -204,6 +252,10 @@ parse_start_element (GMarkupParseContext *context,
priv->current_parser_text = &priv->current_parser_variant->description;
else if (priv->current_parser_layout)
priv->current_parser_text = &priv->current_parser_layout->description;
+ else if (priv->current_parser_option)
+ priv->current_parser_text = &priv->current_parser_option->description;
+ else if (priv->current_parser_group)
+ priv->current_parser_text = &priv->current_parser_group->description;
}
else if (strcmp (element_name, "shortDescription") == 0)
{
@@ -247,6 +299,46 @@ parse_start_element (GMarkupParseContext *context,
priv->current_parser_variant->is_variant = TRUE;
priv->current_parser_variant->main_layout = priv->current_parser_layout;
}
+ else if (strcmp (element_name, "group") == 0)
+ {
+ if (priv->current_parser_group)
+ {
+ g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
+ "'group' elements can't be nested");
+ return;
+ }
+
+ priv->current_parser_group = g_new0 (XkbOptionGroup, 1);
+ /* Maps option ids to XkbOption structs. Owns the XkbOption structs. */
+ priv->current_parser_group->options_table = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL, free_option);
+ g_markup_collect_attributes (element_name,
+ attribute_names,
+ attribute_values,
+ error,
+ G_MARKUP_COLLECT_BOOLEAN | G_MARKUP_COLLECT_OPTIONAL,
+ "allowMultipleSelection",
+ &priv->current_parser_group->allow_multiple_selection,
+ G_MARKUP_COLLECT_INVALID);
+ }
+ else if (strcmp (element_name, "option") == 0)
+ {
+ if (priv->current_parser_option)
+ {
+ g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
+ "'option' elements can't be nested");
+ return;
+ }
+
+ if (!priv->current_parser_group)
+ {
+ g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
+ "'option' elements must be inside 'group' elements");
+ return;
+ }
+
+ priv->current_parser_option = g_new0 (XkbOption, 1);
+ }
}
static void
@@ -339,6 +431,34 @@ parse_end_element (GMarkupParseContext *context,
priv->current_parser_iso639Id = NULL;
}
+ else if (strcmp (element_name, "group") == 0)
+ {
+ if (!priv->current_parser_group->description || !priv->current_parser_group->id)
+ {
+ g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
+ "'group' elements must enclose 'description' and 'name' elements");
+ return;
+ }
+
+ g_hash_table_replace (priv->option_groups_table,
+ priv->current_parser_group->id,
+ priv->current_parser_group);
+ priv->current_parser_group = NULL;
+ }
+ else if (strcmp (element_name, "option") == 0)
+ {
+ if (!priv->current_parser_option->description || !priv->current_parser_option->id)
+ {
+ g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
+ "'option' elements must enclose 'description' and 'name' elements");
+ return;
+ }
+
+ g_hash_table_replace (priv->current_parser_group->options_table,
+ priv->current_parser_option->id,
+ priv->current_parser_option);
+ priv->current_parser_option = NULL;
+ }
}
static void
@@ -364,6 +484,8 @@ parse_error (GMarkupParseContext *context,
{
GnomeXkbInfoPrivate *priv = GNOME_XKB_INFO (data)->priv;
+ free_option_group (priv->current_parser_group);
+ free_option (priv->current_parser_option);
free_layout (priv->current_parser_layout);
free_layout (priv->current_parser_variant);
g_free (priv->current_parser_iso639Id);
@@ -396,9 +518,13 @@ parse_rules_file (GnomeXkbInfo *self)
return;
}
+ /* Maps option group ids to XkbOptionGroup structs. Owns the
+ XkbOptionGroup structs. */
+ priv->option_groups_table = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL, free_option_group);
priv->layouts_by_short_desc = g_hash_table_new (g_str_hash, g_str_equal);
priv->layouts_by_iso639 = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
- /* This is the "master" table so it assumes memory "ownership". */
+ /* Maps layout ids to Layout structs. Owns the Layout structs. */
priv->layouts_table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, free_layout);
context = g_markup_parse_context_new (&markup_parser, 0, self, NULL);
@@ -409,6 +535,8 @@ parse_rules_file (GnomeXkbInfo *self)
{
g_warning ("Failed to parse XKB rules file: %s", error->message);
g_error_free (error);
+ g_hash_table_destroy (priv->option_groups_table);
+ priv->option_groups_table = NULL;
g_hash_table_destroy (priv->layouts_by_short_desc);
priv->layouts_by_short_desc = NULL;
g_hash_table_destroy (priv->layouts_by_iso639);
@@ -440,6 +568,8 @@ gnome_xkb_info_finalize (GObject *self)
{
GnomeXkbInfoPrivate *priv = GNOME_XKB_INFO (self)->priv;
+ if (priv->option_groups_table)
+ g_hash_table_destroy (priv->option_groups_table);
if (priv->layouts_by_short_desc)
g_hash_table_destroy (priv->layouts_by_short_desc);
if (priv->layouts_by_iso639)
@@ -500,6 +630,107 @@ gnome_xkb_info_get_all_layouts (GnomeXkbInfo *self)
}
/**
+ * gnome_xkb_info_get_all_option_groups:
+ * @self: a #GnomeXkbInfo
+ *
+ * Returns a list of all option group identifiers we know about.
+ *
+ * Return value: (transfer container) (element-type gchar): the list
+ * of option group ids. The caller takes ownership of the #GList but
+ * not of the strings themselves, those are internally allocated and
+ * must not be modified.
+ *
+ * Since: 3.6
+ */
+GList *
+gnome_xkb_info_get_all_option_groups (GnomeXkbInfo *self)
+{
+ GnomeXkbInfoPrivate *priv;
+
+ g_return_val_if_fail (GNOME_IS_XKB_INFO (self), NULL);
+
+ priv = self->priv;
+
+ if (!ensure_rules_are_parsed (self))
+ return NULL;
+
+ return g_hash_table_get_keys (priv->option_groups_table);
+}
+
+/**
+ * gnome_xkb_info_get_options_for_group:
+ * @self: a #GnomeXkbInfo
+ * @group_id: group's identifier about which to retrieve the options
+ *
+ * Returns a list of all option identifiers we know about for group
+ * @group_id.
+ *
+ * Return value: (transfer container) (element-type gchar): the list
+ * of option ids. The caller takes ownership of the #GList but not of
+ * the strings themselves, those are internally allocated and must not
+ * be modified.
+ *
+ * Since: 3.6
+ */
+GList *
+gnome_xkb_info_get_options_for_group (GnomeXkbInfo *self,
+ const gchar *group_id)
+{
+ GnomeXkbInfoPrivate *priv;
+ const XkbOptionGroup *group;
+
+ g_return_val_if_fail (GNOME_IS_XKB_INFO (self), NULL);
+
+ priv = self->priv;
+
+ if (!ensure_rules_are_parsed (self))
+ return NULL;
+
+ group = g_hash_table_lookup (priv->option_groups_table, group_id);
+ if (!group)
+ return NULL;
+
+ return g_hash_table_get_keys (group->options_table);
+}
+
+/**
+ * gnome_xkb_info_description_for_option:
+ * @self: a #GnomeXkbInfo
+ * @group_id: identifier for group containing the option
+ * @id: option identifier
+ *
+ * Return value: the translated description for the option @id.
+ *
+ * Since: 3.6
+ */
+const gchar *
+gnome_xkb_info_description_for_option (GnomeXkbInfo *self,
+ const gchar *group_id,
+ const gchar *id)
+{
+ GnomeXkbInfoPrivate *priv;
+ const XkbOptionGroup *group;
+ const XkbOption *option;
+
+ g_return_val_if_fail (GNOME_IS_XKB_INFO (self), NULL);
+
+ priv = self->priv;
+
+ if (!ensure_rules_are_parsed (self))
+ return NULL;
+
+ group = g_hash_table_lookup (priv->option_groups_table, group_id);
+ if (!group)
+ return NULL;
+
+ option = g_hash_table_lookup (group->options_table, id);
+ if (!option)
+ return NULL;
+
+ return XKEYBOARD_CONFIG_(option->description);
+}
+
+/**
* gnome_xkb_info_get_layout_info:
* @self: a #GnomeXkbInfo
* @id: layout's identifier about which to retrieve the info
diff --git a/libgnome-desktop/gnome-xkb-info.h b/libgnome-desktop/gnome-xkb-info.h
index edc3965..d667a65 100644
--- a/libgnome-desktop/gnome-xkb-info.h
+++ b/libgnome-desktop/gnome-xkb-info.h
@@ -74,6 +74,12 @@ gboolean gnome_xkb_info_get_layout_info_for_language (GnomeXkbInfo *s
const gchar **short_name,
const gchar **xkb_layout,
const gchar **xkb_variant);
+GList *gnome_xkb_info_get_all_option_groups (GnomeXkbInfo *self);
+GList *gnome_xkb_info_get_options_for_group (GnomeXkbInfo *self,
+ const gchar *group_id);
+const gchar *gnome_xkb_info_description_for_option (GnomeXkbInfo *self,
+ const gchar *group_id,
+ const gchar *id);
void gnome_xkb_info_get_var_defs (gchar **rules,
XkbRF_VarDefsRec **var_defs);
diff --git a/libgnome-desktop/test-xkb-info.c b/libgnome-desktop/test-xkb-info.c
index e88b4f8..6a6bb16 100644
--- a/libgnome-desktop/test-xkb-info.c
+++ b/libgnome-desktop/test-xkb-info.c
@@ -6,10 +6,13 @@ main (int argc, char **argv)
{
GnomeXkbInfo *info;
GList *layouts, *l;
+ GList *option_groups, *g;
+ GList *options, *o;
gtk_init (&argc, &argv);
info = gnome_xkb_info_new ();
+
layouts = gnome_xkb_info_get_all_layouts (info);
for (l = layouts; l != NULL; l = l->next) {
const char *id = l->data;
@@ -33,6 +36,27 @@ main (int argc, char **argv)
}
}
g_list_free (layouts);
+
+ option_groups = gnome_xkb_info_get_all_option_groups (info);
+ for (g = option_groups; g != NULL; g = g->next) {
+ const char *group_id = g->data;
+
+ g_print ("\noption group: %s\n", group_id);
+
+ options = gnome_xkb_info_get_options_for_group (info, group_id);
+ for (o = options; o != NULL; o = o->next) {
+ const char *id = o->data;
+
+ g_print ("id: %s\n", id);
+ g_print ("\tdescription: %s\n",
+ gnome_xkb_info_description_for_option (info,
+ group_id,
+ id));
+ }
+ g_list_free (options);
+ }
+ g_list_free (option_groups);
+
g_object_unref (info);
return 0;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]