From e2534d54e12c3d9c4b2047608574bf3e2fa5db76 Mon Sep 17 00:00:00 2001 From: Johan Dahlin Date: Sun, 2 Mar 2008 01:14:48 +0000 Subject: [PATCH] Add translatable/context and comment attributes on tags under a 2008-02-29 Johan Dahlin * demos/gtk-demo/demo.ui: * gtk/gtkbuilderparser.c: * gtk/gtkbuilderprivate.h: * gtk/gtkliststore.c: * tests/buildertest.c: Add translatable/context and comment attributes on tags under a GtkListStore. Refactor parts of the translation api and make it available inside gtk+ itself. Update tests and example. Fixes a part of #518642 svn path=/trunk/; revision=19685 --- ChangeLog | 13 +++++++ demos/gtk-demo/demo.ui | 14 +++---- gtk/gtkbuilderparser.c | 32 ++++++++++------ gtk/gtkbuilderprivate.h | 6 +++ gtk/gtkliststore.c | 81 ++++++++++++++++++++++++++++++++++++++--- tests/buildertest.c | 6 +-- 6 files changed, 124 insertions(+), 28 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4f9a9c9aed..ac23015c11 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2008-02-29 Johan Dahlin + + * demos/gtk-demo/demo.ui: + * gtk/gtkbuilderparser.c: + * gtk/gtkbuilderprivate.h: + * gtk/gtkliststore.c: + * tests/buildertest.c: + Add translatable/context and comment attributes on + tags under a GtkListStore. Refactor parts of the + translation api and make it available inside gtk+ itself. + Update tests and example. + Fixes a part of #518642 + 2008-02-29 Johan Dahlin * gtk/gtkbuilder.c: diff --git a/demos/gtk-demo/demo.ui b/demos/gtk-demo/demo.ui index 9d27c85cea..57dd232505 100644 --- a/demos/gtk-demo/demo.ui +++ b/demos/gtk-demo/demo.ui @@ -1,5 +1,5 @@ - + @@ -9,16 +9,16 @@ - John - Doe + John + Doe 25 - This is the John Doe row + This is the John Doe row - Mary - Dole + Mary + Unknown 50 - This is the Mary Dole row + This is the Mary Unknown row diff --git a/gtk/gtkbuilderparser.c b/gtk/gtkbuilderparser.c index 76e633e874..d6d69a46cf 100644 --- a/gtk/gtkbuilderparser.c +++ b/gtk/gtkbuilderparser.c @@ -791,6 +791,21 @@ dpgettext (const char *domain, return translation; } +gchar * +_gtk_builder_parser_translate (const gchar *domain, + const gchar *context, + const gchar *text) +{ + const char *s; + + if (context) + s = dpgettext (domain, context, text); + else + s = dgettext (domain, text); + + return g_strdup (s); +} + /* Called for close tags */ static void end_element (GMarkupParseContext *context, @@ -841,22 +856,15 @@ end_element (GMarkupParseContext *context, if (prop_info->translatable && prop_info->text->len) { - const char *text; - - if (prop_info->context) - text = dpgettext (data->domain, - prop_info->context, - prop_info->text->str); - else - text = dgettext (data->domain, prop_info->text->str); - - prop_info->data = g_strdup (text); + prop_info->data = _gtk_builder_parser_translate (data->domain, + prop_info->context, + prop_info->text->str); g_string_free (prop_info->text, TRUE); } else { - prop_info->data = prop_info->text->str; - g_string_free (prop_info->text, FALSE); + prop_info->data = g_string_free (prop_info->text, FALSE); + } object_info->properties = diff --git a/gtk/gtkbuilderprivate.h b/gtk/gtkbuilderprivate.h index 2cbb322bec..1a45aca236 100644 --- a/gtk/gtkbuilderprivate.h +++ b/gtk/gtkbuilderprivate.h @@ -97,6 +97,7 @@ typedef struct { typedef GType (*GTypeGetFunc) (void); +/* Things only GtkBuilder should use */ void _gtk_builder_parser_parse_buffer (GtkBuilder *builder, const gchar *filename, const gchar *buffer, @@ -112,6 +113,8 @@ void _gtk_builder_add_signals (GtkBuilder *builder, void _gtk_builder_finish (GtkBuilder *builder); void _free_signal_info (SignalInfo *info, gpointer user_data); + +/* Internal API which might be made public at some point */ gboolean _gtk_builder_boolean_from_string (const gchar *string, gboolean *value, GError **error); @@ -119,5 +122,8 @@ gboolean _gtk_builder_flags_from_string (GType type, const char *string, guint *value, GError **error); +gchar * _gtk_builder_parser_translate (const gchar *domain, + const gchar *context, + const gchar *text); #endif /* __GTK_BUILDER_PRIVATE_H__ */ diff --git a/gtk/gtkliststore.c b/gtk/gtkliststore.c index 3557a7cf36..3e56ef4b6e 100644 --- a/gtk/gtkliststore.c +++ b/gtk/gtkliststore.c @@ -28,6 +28,7 @@ #include "gtktreednd.h" #include "gtkintl.h" #include "gtkbuildable.h" +#include "gtkbuilderprivate.h" #include "gtkalias.h" #define GTK_LIST_STORE_IS_SORTED(list) (((GtkListStore*)(list))->sort_column_id != GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID) @@ -2042,18 +2043,26 @@ gtk_list_store_insert_with_valuesv (GtkListStore *list_store, * * */ +typedef struct { + gboolean translatable; + gchar *context; + int id; +} ColInfo; + typedef struct { GtkBuilder *builder; GObject *object; GSList *column_type_names; GType *column_types; GValue *values; - gint *columns; + gint *colids; + ColInfo **columns; gint last_row; gint n_columns; gint row_column; GQuark error_quark; gboolean is_data; + const gchar *domain; } SubParserData; static void @@ -2070,6 +2079,9 @@ list_store_start_element (GMarkupParseContext *context, if (strcmp (element_name, "col") == 0) { int i, id = -1; + gchar *context = NULL; + gboolean translatable = FALSE; + ColInfo *info; if (data->row_column >= data->n_columns) g_set_error (error, data->error_quark, 0, @@ -2082,14 +2094,35 @@ list_store_start_element (GMarkupParseContext *context, id = atoi (values[i]); if (errno) g_set_error (error, data->error_quark, 0, - "the id tag %s could not be converted to an integer", values[i]); + "the id tag %s could not be converted to an integer", + values[i]); + } + else if (strcmp (names[i], "translatable") == 0) + { + if (!_gtk_builder_boolean_from_string (values[i], &translatable, + error)) + return; + } + else if (strcmp (names[i], "comments") == 0) + { + /* do nothing, comments are for translators */ + } + else if (strcmp (names[i], "context") == 0) + { + context = g_strdup (values[i]); } if (id == -1) g_set_error (error, data->error_quark, 0, " needs an id attribute"); + + info = g_slice_new0 (ColInfo); + info->translatable = translatable; + info->context = context; + info->id = id; - data->columns[data->row_column] = id; + data->colids[data->row_column] = id; + data->columns[data->row_column] = info; data->row_column++; data->is_data = TRUE; } @@ -2127,11 +2160,17 @@ list_store_end_element (GMarkupParseContext *context, gtk_list_store_insert_with_valuesv (GTK_LIST_STORE (data->object), &iter, data->last_row, - data->columns, + data->colids, data->values, data->row_column); for (i = 0; i < data->row_column; i++) - g_value_unset (&data->values[i]); + { + ColInfo *info = data->columns[i]; + g_free (info->context); + g_slice_free (ColInfo, info); + data->columns[i] = NULL; + g_value_unset (&data->values[i]); + } g_free (data->values); data->values = g_new0 (GValue, data->n_columns); data->last_row++; @@ -2189,13 +2228,30 @@ list_store_text (GMarkupParseContext *context, gint i; GError *tmp_error = NULL; gchar *string; + ColInfo *info; if (!data->is_data) return; i = data->row_column - 1; + info = data->columns[i]; string = g_strndup (text, text_len); + if (info->translatable && text_len) + { + gchar *translated; + + /* FIXME: This will not use the domain set in the .ui file, + * since the parser is not telling the builder about the domain. + * However, it will work for gtk_builder_set_translation_domain() calls. + */ + translated = _gtk_builder_parser_translate (data->domain, + info->context, + string); + g_free (string); + string = translated; + } + if (!gtk_builder_value_from_string_type (data->builder, data->column_types[i], string, @@ -2255,11 +2311,13 @@ gtk_list_store_buildable_custom_tag_start (GtkBuildable *buildable, parser_data->builder = builder; parser_data->object = G_OBJECT (buildable); parser_data->values = g_new0 (GValue, n_columns); - parser_data->columns = g_new0 (gint, n_columns); + parser_data->colids = g_new0 (gint, n_columns); + parser_data->columns = g_new0 (ColInfo*, n_columns); parser_data->column_types = GTK_LIST_STORE (buildable)->column_headers; parser_data->n_columns = n_columns; parser_data->last_row = 0; parser_data->error_quark = g_quark_from_static_string ("GtkListStore"); + parser_data->domain = gtk_builder_get_translation_domain (builder); *parser = list_store_parser; *data = parser_data; @@ -2287,6 +2345,17 @@ gtk_list_store_buildable_custom_tag_end (GtkBuildable *buildable, } else if (strcmp (tagname, "data") == 0) { + int i; + for (i = 0; i < sub->n_columns; i++) + { + ColInfo *info = sub->columns[i]; + if (info) + { + g_free (info->context); + g_slice_free (ColInfo, info); + } + } + g_free (sub->colids); g_free (sub->columns); g_free (sub->values); g_slice_free (SubParserData, sub); diff --git a/tests/buildertest.c b/tests/buildertest.c index fb6f7104d3..6649aa18b6 100644 --- a/tests/buildertest.c +++ b/tests/buildertest.c @@ -527,9 +527,9 @@ test_list_store (void) " " " " " " - " John" - " Doe" - " 25" + " _Quit" + " Doe" + " 25" " " " " " Johan"