From 1ddaf01aed98462dfdd13370ec3d62d468cf343f Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 1 Nov 2011 19:53:51 -0400 Subject: [PATCH] Quick-and-dirty GtkBuilder integration This makes GtkBuilder accept a GMenuMarkup tree at the toplevel (ie with being a child of ) and the resulting GMenu object can be obtained via gtk_builder_get_object (builder, "foo"). --- gtk/gtkbuilder.c | 7 +++++++ gtk/gtkbuilderparser.c | 43 +++++++++++++++++++++++++++++++++++++++++ gtk/gtkbuilderprivate.h | 3 +++ gtk/tests/builder.c | 43 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 96 insertions(+) diff --git a/gtk/gtkbuilder.c b/gtk/gtkbuilder.c index 10373f6c27..de24427bb5 100644 --- a/gtk/gtkbuilder.c +++ b/gtk/gtkbuilder.c @@ -731,6 +731,13 @@ _gtk_builder_construct (GtkBuilder *builder, return obj; } +void +_gtk_builder_add_object (GtkBuilder *builder, + const gchar *id, + GObject *object) +{ + g_hash_table_insert (builder->priv->objects, g_strdup (id), g_object_ref (object)); +} void _gtk_builder_add (GtkBuilder *builder, diff --git a/gtk/gtkbuilderparser.c b/gtk/gtkbuilderparser.c index 5ea15e3c60..d0071f90de 100644 --- a/gtk/gtkbuilderparser.c +++ b/gtk/gtkbuilderparser.c @@ -23,6 +23,7 @@ #include #include +#include #include "gtkbuilderprivate.h" #include "gtkbuilder.h" #include "gtkbuildable.h" @@ -823,6 +824,34 @@ parse_custom (GMarkupParseContext *context, return TRUE; } +static gboolean +parse_menu (GMarkupParseContext *context, + const gchar *element_name, + const gchar **names, + const gchar **values, + gpointer user_data, + GError **error) +{ + gchar *id; + ParserData *data = user_data; + ObjectInfo *object_info; + + if (!g_markup_collect_attributes (element_name, names, values, error, + G_MARKUP_COLLECT_STRING, "id", &id, + G_MARKUP_COLLECT_INVALID)) + return FALSE; + + object_info = g_slice_new0 (ObjectInfo); + object_info->class_name = g_strdup ("GMenu"); + object_info->id = g_strdup (id); + object_info->tag.name = element_name; + state_push (data, object_info); + + g_menu_markup_parser_start_menu (context, NULL); + + return TRUE; +} + static void start_element (GMarkupParseContext *context, const gchar *element_name, @@ -883,6 +912,8 @@ start_element (GMarkupParseContext *context, parse_signal (data, element_name, names, values, error); else if (strcmp (element_name, "interface") == 0) parse_interface (data, element_name, names, values, error); + else if (strcmp (element_name, "menu") == 0) + parse_menu (context, element_name, names, values, data, error); else if (strcmp (element_name, "placeholder") == 0) { /* placeholder has no special treatmeant, but it needs an @@ -954,6 +985,18 @@ end_element (GMarkupParseContext *context, else if (strcmp (element_name, "interface") == 0) { } + else if (strcmp (element_name, "menu") == 0) + { + ObjectInfo *object_info; + GObject *menu; + + object_info = state_pop_info (data, ObjectInfo); + menu = (GObject*)g_menu_markup_parser_end_menu (context); + _gtk_builder_add_object (data->builder, object_info->id, menu); + g_object_unref (menu); + + free_object_info (object_info); + } else if (data->requested_objects && !data->inside_requested_object) { /* If outside a requested object, simply ignore this tag */ diff --git a/gtk/gtkbuilderprivate.h b/gtk/gtkbuilderprivate.h index e633a28b5d..a7fc500443 100644 --- a/gtk/gtkbuilderprivate.h +++ b/gtk/gtkbuilderprivate.h @@ -117,6 +117,9 @@ void _gtk_builder_parser_parse_buffer (GtkBuilder *builder, GObject * _gtk_builder_construct (GtkBuilder *builder, ObjectInfo *info, GError **error); +void _gtk_builder_add_object (GtkBuilder *builder, + const gchar *id, + GObject *object); void _gtk_builder_add (GtkBuilder *builder, ChildInfo *child_info); void _gtk_builder_add_signals (GtkBuilder *builder, diff --git a/gtk/tests/builder.c b/gtk/tests/builder.c index 082b69a12a..1bbba85366 100644 --- a/gtk/tests/builder.c +++ b/gtk/tests/builder.c @@ -2572,6 +2572,48 @@ test_message_area (void) g_object_unref (builder); } +static void +test_gmenu (void) +{ + GtkBuilder *builder; + GError *error; + GObject *obj, *obj1; + const gchar buffer[] = + "" + " " + " " + " " + "
" + " " + " " + "
" + "
" + "
" + " " + " " + " " + "
" + "
" + " " + " " + " " + " " + " " + " " + "
" + "
" + "
"; + + error = NULL; + builder = builder_new_from_string (buffer, -1, NULL); + g_assert (error == NULL); + obj = gtk_builder_get_object (builder, "window"); + g_assert (GTK_IS_WINDOW (obj)); + obj1 = gtk_builder_get_object (builder, "edit-menu"); + g_assert (G_IS_MENU_MODEL (obj1)); + g_object_unref (builder); +} + int main (int argc, char **argv) { @@ -2618,6 +2660,7 @@ main (int argc, char **argv) g_test_add_func ("/Builder/Menus", test_menus); g_test_add_func ("/Builder/MessageArea", test_message_area); g_test_add_func ("/Builder/MessageDialog", test_message_dialog); + g_test_add_func ("/Builder/GMenu", test_gmenu); return g_test_run(); }