From: Ryan Lortie Date: Thu, 26 Jan 2012 00:55:33 +0000 (-0500) Subject: Drop the GMenu markup functions X-Git-Tag: 2.31.14~35 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=2a90aba068439ef528cd31f36971ca92b5a70f94;p=platform%2Fupstream%2Fglib.git Drop the GMenu markup functions The parser has been moved into Gtk in a modified form and the printer was never really useful anyway (except for debugging/testing). --- diff --git a/gio/Makefile.am b/gio/Makefile.am index 815465e..9ad8434 100644 --- a/gio/Makefile.am +++ b/gio/Makefile.am @@ -145,7 +145,6 @@ application_headers = \ gsimpleaction.h \ \ gmenumodel.h \ - gmenumarkup.h \ gmenu.h \ gmenuexporter.h \ gdbusmenumodel.h \ @@ -167,7 +166,6 @@ application_sources = \ gsimpleaction.c \ \ gmenumodel.c \ - gmenumarkup.c \ gmenu.c \ gmenuexporter.c \ gdbusmenumodel.c \ @@ -615,9 +613,6 @@ EXTRA_DIST += \ abicheck.sh \ gio.rc.in \ gschema.dtd \ - menumarkup.xml \ - menumarkup2.xml \ - menumarkup.dtd \ $(NULL) BUILT_EXTRA_DIST = \ diff --git a/gio/gio.h b/gio/gio.h index 6e26e50..94ce721 100644 --- a/gio/gio.h +++ b/gio/gio.h @@ -152,7 +152,6 @@ #include #include #include -#include #include #undef __GIO_GIO_H_INSIDE__ diff --git a/gio/gmenumarkup.c b/gio/gmenumarkup.c deleted file mode 100644 index 3564c2e..0000000 --- a/gio/gmenumarkup.c +++ /dev/null @@ -1,741 +0,0 @@ -/* - * Copyright © 2011 Canonical Ltd. - * All rights reserved. - * - * Author: Ryan Lortie - */ - -#include "gmenumarkup.h" - -#include - -/** - * SECTION:gmenumarkup - * @title: GMenu Markup - * @short_description: parsing and printing GMenuModel XML - * - * The functions here allow to instantiate #GMenuModels by parsing - * fragments of an XML document. - * * The XML format for #GMenuModel consists of a toplevel - * menu element, which contains one or more - * item elements. Each item - * element contains attribute and link - * elements with a mandatory name attribute. - * link elements have the same content - * model as menu. - * - * Here is the XML for : - * |[FIXME: MISSING XINCLUDE CONTENT]| - * - * The parser also understands a somewhat less verbose format, in which - * attributes are encoded as actual XML attributes of item - * elements, and link elements are replaced by - * section and submenu elements. - * - * Here is how the example looks in this format: - * |[FIXME: MISSING XINCLUDE CONTENT]| - * - * The parser can obtaing translations for attribute values using gettext. - * To make use of this, the menu element must - * have a domain attribute which specifies the gettext domain to use, and - * attribute elements can be marked for translation - * with a translatable="yes" attribute. It is also possible - * to specify message context and translator comments, using the context - * and comments attributes. - * - * The following DTD describes the XML format approximately: - * |[FIXME: MISSING XINCLUDE CONTENT]| - * - * To serialize a #GMenuModel into an XML fragment, use - * g_menu_markup_print_string(). - */ - -struct frame -{ - GMenu *menu; - GMenuItem *item; - struct frame *prev; -}; - -typedef struct -{ - GHashTable *objects; - struct frame frame; - - /* attributes */ - GQuark attribute; - GVariantType *type; - GString *string; - - /* translation */ - gchar *domain; - gchar *context; - gboolean translatable; -} GMenuMarkupState; - -static void -g_menu_markup_push_frame (GMenuMarkupState *state, - GMenu *menu, - GMenuItem *item) -{ - struct frame *new; - - new = g_slice_new (struct frame); - *new = state->frame; - - state->frame.menu = menu; - state->frame.item = item; - state->frame.prev = new; -} - -static void -g_menu_markup_pop_frame (GMenuMarkupState *state) -{ - struct frame *prev = state->frame.prev; - - if (state->frame.item) - { - g_assert (prev->menu != NULL); - g_menu_append_item (prev->menu, state->frame.item); - g_object_unref (state->frame.item); - } - - state->frame = *prev; - - g_slice_free (struct frame, prev); -} - -static void -add_string_attributes (GMenuItem *item, - const gchar **names, - const gchar **values) -{ - gint i; - - for (i = 0; names[i]; i++) - { - g_menu_item_set_attribute (item, names[i], "s", values[i]); - } -} - -static gboolean -find_id_attribute (const gchar **names, - const gchar **values, - const gchar **id) -{ - gint i; - - for (i = 0; names[i]; i++) - { - if (strcmp (names[i], "id") == 0) - { - *id = values[i]; - return TRUE; - } - } - - return FALSE; -} - -static void -g_menu_markup_start_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error) -{ - GMenuMarkupState *state = user_data; - -#define COLLECT(first, ...) \ - g_markup_collect_attributes (element_name, \ - attribute_names, attribute_values, error, \ - first, __VA_ARGS__, G_MARKUP_COLLECT_INVALID) -#define OPTIONAL G_MARKUP_COLLECT_OPTIONAL -#define BOOLEAN G_MARKUP_COLLECT_BOOLEAN -#define STRING G_MARKUP_COLLECT_STRING - - if (!(state->frame.menu || state->frame.item || state->string)) - { - /* Can only have here. */ - if (g_str_equal (element_name, "menu")) - { - gchar *id; - - if (COLLECT (STRING, "id", &id)) - { - GMenu *menu; - - menu = g_menu_new (); - if (state->objects) - g_hash_table_insert (state->objects, g_strdup (id), menu); - g_menu_markup_push_frame (state, menu, NULL); - } - - return; - } - } - - if (state->frame.menu) - { - /* Can have '', '' or '
' here. */ - if (g_str_equal (element_name, "item")) - { - GMenuItem *item; - - item = g_menu_item_new (NULL, NULL); - add_string_attributes (item, attribute_names, attribute_values); - g_menu_markup_push_frame (state, NULL, item); - return; - } - - else if (g_str_equal (element_name, "submenu")) - { - GMenuItem *item; - GMenu *menu; - const gchar *id; - - menu = g_menu_new (); - item = g_menu_item_new_submenu (NULL, G_MENU_MODEL (menu)); - add_string_attributes (item, attribute_names, attribute_values); - g_menu_markup_push_frame (state, menu, item); - - if (find_id_attribute (attribute_names, attribute_values, &id)) - { - if (state->objects) - g_hash_table_insert (state->objects, g_strdup (id), g_object_ref (menu)); - } - g_object_unref (menu); - - return; - } - - else if (g_str_equal (element_name, "section")) - { - GMenuItem *item; - GMenu *menu; - const gchar *id; - - menu = g_menu_new (); - item = g_menu_item_new_section (NULL, G_MENU_MODEL (menu)); - add_string_attributes (item, attribute_names, attribute_values); - g_menu_markup_push_frame (state, menu, item); - - if (find_id_attribute (attribute_names, attribute_values, &id)) - { - if (state->objects) - g_hash_table_insert (state->objects, g_strdup (id), g_object_ref (menu)); - } - g_object_unref (menu); - - return; - } - } - - if (state->frame.item) - { - /* Can have '' or '' here. */ - if (g_str_equal (element_name, "attribute")) - { - const gchar *typestr; - const gchar *name; - const gchar *context; - - if (COLLECT (STRING, "name", &name, - OPTIONAL | BOOLEAN, "translatable", &state->translatable, - OPTIONAL | STRING, "context", &context, - OPTIONAL | STRING, "comments", NULL, /* ignore, just for translators */ - OPTIONAL | STRING, "type", &typestr)) - { - if (typestr && !g_variant_type_string_is_valid (typestr)) - { - g_set_error (error, G_VARIANT_PARSE_ERROR, - G_VARIANT_PARSE_ERROR_INVALID_TYPE_STRING, - "Invalid GVariant type string '%s'", typestr); - return; - } - - state->type = typestr ? g_variant_type_new (typestr) : g_variant_type_copy (G_VARIANT_TYPE_STRING); - state->string = g_string_new (NULL); - state->attribute = g_quark_from_string (name); - state->context = g_strdup (context); - - g_menu_markup_push_frame (state, NULL, NULL); - } - - return; - } - - if (g_str_equal (element_name, "link")) - { - const gchar *name; - const gchar *id; - - if (COLLECT (STRING, "name", &name, - STRING | OPTIONAL, "id", &id)) - { - GMenu *menu; - - menu = g_menu_new (); - g_menu_item_set_link (state->frame.item, name, G_MENU_MODEL (menu)); - g_menu_markup_push_frame (state, menu, NULL); - - if (id != NULL && state->objects) - g_hash_table_insert (state->objects, g_strdup (id), g_object_ref (menu)); - g_object_unref (menu); - } - - return; - } - } - - { - const GSList *element_stack; - - element_stack = g_markup_parse_context_get_element_stack (context); - - if (element_stack->next) - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, - _("Element <%s> not allowed inside <%s>"), - element_name, (const gchar *) element_stack->next->data); - - else - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, - _("Element <%s> not allowed at toplevel"), element_name); - } -} - -static void -g_menu_markup_end_element (GMarkupParseContext *context, - const gchar *element_name, - gpointer user_data, - GError **error) -{ - GMenuMarkupState *state = user_data; - - g_menu_markup_pop_frame (state); - - if (state->string) - { - GVariant *value; - gchar *text; - - text = g_string_free (state->string, FALSE); - state->string = NULL; - - /* If error is set here, it will follow us out, ending the parse. - * We still need to free everything, though. - */ - if ((value = g_variant_parse (state->type, text, NULL, NULL, error))) - { - /* Deal with translatable string attributes */ - if (state->domain && state->translatable && - g_variant_type_equal (state->type, G_VARIANT_TYPE_STRING)) - { - const gchar *msgid; - const gchar *msgstr; - - msgid = g_variant_get_string (value, NULL); - if (state->context) - msgstr = g_dpgettext2 (state->domain, state->context, msgid); - else - msgstr = g_dgettext (state->domain, msgid); - - if (msgstr != msgid) - { - g_variant_unref (value); - value = g_variant_new_string (msgstr); - g_variant_ref_sink (value); - } - } - - g_menu_item_set_attribute_value (state->frame.item, g_quark_to_string (state->attribute), value); - g_variant_unref (value); - } - - g_variant_type_free (state->type); - state->type = NULL; - - g_free (state->context); - state->context = NULL; - - g_free (text); - } -} - -static void -g_menu_markup_text (GMarkupParseContext *context, - const gchar *text, - gsize text_len, - gpointer user_data, - GError **error) -{ - GMenuMarkupState *state = user_data; - gint i; - - for (i = 0; i < text_len; i++) - if (!g_ascii_isspace (text[i])) - { - if (state->string) - g_string_append_len (state->string, text, text_len); - - else - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, - _("text may not appear inside <%s>"), - g_markup_parse_context_get_element (context)); - break; - } -} - -static void -g_menu_markup_error (GMarkupParseContext *context, - GError *error, - gpointer user_data) -{ - GMenuMarkupState *state = user_data; - - while (state->frame.prev) - { - struct frame *prev = state->frame.prev; - - state->frame = *prev; - - g_slice_free (struct frame, prev); - } - - if (state->string) - g_string_free (state->string, TRUE); - - if (state->type) - g_variant_type_free (state->type); - - if (state->objects) - g_hash_table_unref (state->objects); - - g_free (state->context); - - g_slice_free (GMenuMarkupState, state); -} - -static GMarkupParser g_menu_subparser = -{ - g_menu_markup_start_element, - g_menu_markup_end_element, - g_menu_markup_text, - NULL, /* passthrough */ - g_menu_markup_error -}; - -/** - * g_menu_markup_parser_start: - * @context: a #GMarkupParseContext - * @domain: (allow-none): translation domain for labels, or %NULL - * @objects: (allow-none): a #GHashTable for the objects, or %NULL - * - * Begin parsing a group of menus in XML form. - * - * If @domain is not %NULL, it will be used to translate attributes - * that are marked as translatable, using gettext(). - * - * If @objects is specified then it must be a #GHashTable that was - * created using g_hash_table_new_full() with g_str_hash(), - * g_str_equal(), g_free() and g_object_unref(). - * Any named menus (ie: menu, - * submenu, - * section or link - * elements with an id='' attribute) that are encountered while parsing - * will be added to this table. Each toplevel menu must be named. - * - * If @objects is %NULL then an empty hash table will be created. - * - * This function should be called from the start_element function for - * the element representing the group containing the menus. In other - * words, the content inside of this element is expected to be a list of - * menus. - * - * Since: 2.32 - */ -void -g_menu_markup_parser_start (GMarkupParseContext *context, - const gchar *domain, - GHashTable *objects) -{ - GMenuMarkupState *state; - - g_return_if_fail (context != NULL); - - state = g_slice_new0 (GMenuMarkupState); - - state->domain = g_strdup (domain); - - if (objects != NULL) - state->objects = g_hash_table_ref (objects); - else - state->objects = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); - - g_markup_parse_context_push (context, &g_menu_subparser, state); -} - -/** - * g_menu_markup_parser_end: - * @context: a #GMarkupParseContext - * - * Stop the parsing of a set of menus and return the #GHashTable. - * - * The #GHashTable maps strings to #GObject instances. The parser only - * adds #GMenu instances to the table, but it may contain other types if - * a table was provided to g_menu_markup_parser_start(). - * - * This call should be matched with g_menu_markup_parser_start(). - * See that function for more information - * - * Returns: (transfer full): the #GHashTable containing the objects - * - * Since: 2.32 - */ -GHashTable * -g_menu_markup_parser_end (GMarkupParseContext *context) -{ - GMenuMarkupState *state = g_markup_parse_context_pop (context); - GHashTable *objects; - - objects = state->objects; - - g_free (state->domain); - - g_slice_free (GMenuMarkupState, state); - - return objects; -} - -/** - * g_menu_markup_parser_start_menu: - * @context: a #GMarkupParseContext - * @domain: (allow-none): translation domain for labels, or %NULL - * @objects: (allow-none): a #GHashTable for the objects, or %NULL - * - * Begin parsing the XML definition of a menu. - * - * This function should be called from the start_element function for - * the element representing the menu itself. In other words, the - * content inside of this element is expected to be a list of items. - * - * If @domain is not %NULL, it will be used to translate attributes - * that are marked as translatable, using gettext(). - * - * If @objects is specified then it must be a #GHashTable that was - * created using g_hash_table_new_full() with g_str_hash(), - * g_str_equal(), g_free() and g_object_unref(). - * Any named menus (ie: submenu, - * section or link - * elements with an id='' attribute) that are encountered while parsing - * will be added to this table. - * Note that toplevel menu is not added to - * the hash table, even if it has an id attribute. - * - * If @objects is %NULL then named menus will not be supported. - * - * You should call g_menu_markup_parser_end_menu() from the - * corresponding end_element function in order to collect the newly - * parsed menu. - * - * Since: 2.32 - */ -void -g_menu_markup_parser_start_menu (GMarkupParseContext *context, - const gchar *domain, - GHashTable *objects) -{ - GMenuMarkupState *state; - - g_return_if_fail (context != NULL); - - state = g_slice_new0 (GMenuMarkupState); - - if (objects) - state->objects = g_hash_table_ref (objects); - - state->domain = g_strdup (domain); - - g_markup_parse_context_push (context, &g_menu_subparser, state); - - state->frame.menu = g_menu_new (); -} - -/** - * g_menu_markup_parser_end_menu: - * @context: a #GMarkupParseContext - * - * Stop the parsing of a menu and return the newly-created #GMenu. - * - * This call should be matched with g_menu_markup_parser_start_menu(). - * See that function for more information - * - * Returns: (transfer full): the newly-created #GMenu - * - * Since: 2.32 - */ -GMenu * -g_menu_markup_parser_end_menu (GMarkupParseContext *context) -{ - GMenuMarkupState *state = g_markup_parse_context_pop (context); - GMenu *menu; - - menu = state->frame.menu; - - if (state->objects) - g_hash_table_unref (state->objects); - g_free (state->domain); - g_slice_free (GMenuMarkupState, state); - - return menu; -} - -static void -indent_string (GString *string, - gint indent) -{ - while (indent--) - g_string_append_c (string, ' '); -} - -/** - * g_menu_markup_print_string: - * @string: a #GString - * @model: the #GMenuModel to print - * @indent: the intentation level to start at - * @tabstop: how much to indent each level - * - * Print the contents of @model to @string. - * Note that you have to provide the containing - * menu element yourself. - * - * Returns: @string - * - * Since: 2.32 - */ -GString * -g_menu_markup_print_string (GString *string, - GMenuModel *model, - gint indent, - gint tabstop) -{ - gboolean need_nl = FALSE; - gint i, n; - - if G_UNLIKELY (string == NULL) - string = g_string_new (NULL); - - n = g_menu_model_get_n_items (model); - - for (i = 0; i < n; i++) - { - GMenuAttributeIter *attr_iter; - GMenuLinkIter *link_iter; - GString *contents; - GString *attrs; - - attr_iter = g_menu_model_iterate_item_attributes (model, i); - link_iter = g_menu_model_iterate_item_links (model, i); - contents = g_string_new (NULL); - attrs = g_string_new (NULL); - - while (g_menu_attribute_iter_next (attr_iter)) - { - const char *name = g_menu_attribute_iter_get_name (attr_iter); - GVariant *value = g_menu_attribute_iter_get_value (attr_iter); - - if (g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)) - { - gchar *str; - str = g_markup_printf_escaped (" %s='%s'", name, g_variant_get_string (value, NULL)); - g_string_append (attrs, str); - g_free (str); - } - - else - { - gchar *printed; - gchar *str; - const gchar *type; - - printed = g_variant_print (value, TRUE); - type = g_variant_type_peek_string (g_variant_get_type (value)); - str = g_markup_printf_escaped ("%s\n", name, type, printed); - indent_string (contents, indent + tabstop); - g_string_append (contents, str); - g_free (printed); - g_free (str); - } - - g_variant_unref (value); - } - g_object_unref (attr_iter); - - while (g_menu_link_iter_next (link_iter)) - { - const gchar *name = g_menu_link_iter_get_name (link_iter); - GMenuModel *menu = g_menu_link_iter_get_value (link_iter); - gchar *str; - - if (contents->str[0]) - g_string_append_c (contents, '\n'); - - str = g_markup_printf_escaped ("\n", name); - indent_string (contents, indent + tabstop); - g_string_append (contents, str); - g_free (str); - - g_menu_markup_print_string (contents, menu, indent + 2 * tabstop, tabstop); - - indent_string (contents, indent + tabstop); - g_string_append (contents, "\n"); - g_object_unref (menu); - } - g_object_unref (link_iter); - - if (contents->str[0]) - { - indent_string (string, indent); - g_string_append_printf (string, "\n", attrs->str); - g_string_append (string, contents->str); - indent_string (string, indent); - g_string_append (string, "\n"); - need_nl = TRUE; - } - - else - { - if (need_nl) - g_string_append_c (string, '\n'); - - indent_string (string, indent); - g_string_append_printf (string, "\n", attrs->str); - need_nl = FALSE; - } - - g_string_free (contents, TRUE); - g_string_free (attrs, TRUE); - } - - return string; -} - -/** - * g_menu_markup_print_stderr: - * @model: a #GMenuModel - * - * Print @model to stderr for debugging purposes. - * - * This debugging function will be removed in the future. - */ -void -g_menu_markup_print_stderr (GMenuModel *model) -{ - GString *string; - - string = g_string_new ("\n"); - g_menu_markup_print_string (string, model, 2, 2); - g_printerr ("%s\n", string->str); - g_string_free (string, TRUE); -} diff --git a/gio/gmenumarkup.h b/gio/gmenumarkup.h deleted file mode 100644 index 1dfb326..0000000 --- a/gio/gmenumarkup.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright © 2011 Canonical Ltd. - * - * 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 - */ - -#ifndef __G_MENU_MARKUP_H__ -#define __G_MENU_MARKUP_H__ - -#include - -G_BEGIN_DECLS - -void g_menu_markup_parser_start (GMarkupParseContext *context, - const gchar *domain, - GHashTable *objects); -GHashTable * g_menu_markup_parser_end (GMarkupParseContext *context); - -void g_menu_markup_parser_start_menu (GMarkupParseContext *context, - const gchar *domain, - GHashTable *objects); -GMenu * g_menu_markup_parser_end_menu (GMarkupParseContext *context); - -void g_menu_markup_print_stderr (GMenuModel *model); -GString * g_menu_markup_print_string (GString *string, - GMenuModel *model, - gint indent, - gint tabstop); - -G_END_DECLS - -#endif /* __G_MENU_MARKUP_H__ */ diff --git a/gio/menumarkup.dtd b/gio/menumarkup.dtd deleted file mode 100644 index a554910..0000000 --- a/gio/menumarkup.dtd +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/gio/menumarkup.xml b/gio/menumarkup.xml deleted file mode 100644 index 8c0ef30..0000000 --- a/gio/menumarkup.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - -
- - -
-
- -
-
- -
- - -
-
- - -
-
-
-
- -
diff --git a/gio/menumarkup2.xml b/gio/menumarkup2.xml deleted file mode 100644 index a505e88..0000000 --- a/gio/menumarkup2.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - File - - - Edit - - - View - - - - - Toolbar - toolbar - - - Statusbar - statusbar - - - - - - - Fullscreen - fullscreen - - - - - - - Highlight Mode - - - Sources - - - Vala - sources - vala - - - Python - sources - python - - - - - Markup - - - asciidoc - markup - asciidoc - - - HTML - markup - html - - - - - - - - - - - Help - - diff --git a/gio/tests/gmenumodel.c b/gio/tests/gmenumodel.c index 4253f99..d8eb567 100644 --- a/gio/tests/gmenumodel.c +++ b/gio/tests/gmenumodel.c @@ -1,5 +1,125 @@ #include +/* Markup printing {{{1 */ + +/* This used to be part of GLib, but it was removed before the stable + * release because it wasn't generally useful. We want it here, though. + */ +static void +indent_string (GString *string, + gint indent) +{ + while (indent--) + g_string_append_c (string, ' '); +} + +static GString * +g_menu_markup_print_string (GString *string, + GMenuModel *model, + gint indent, + gint tabstop) +{ + gboolean need_nl = FALSE; + gint i, n; + + if G_UNLIKELY (string == NULL) + string = g_string_new (NULL); + + n = g_menu_model_get_n_items (model); + + for (i = 0; i < n; i++) + { + GMenuAttributeIter *attr_iter; + GMenuLinkIter *link_iter; + GString *contents; + GString *attrs; + + attr_iter = g_menu_model_iterate_item_attributes (model, i); + link_iter = g_menu_model_iterate_item_links (model, i); + contents = g_string_new (NULL); + attrs = g_string_new (NULL); + + while (g_menu_attribute_iter_next (attr_iter)) + { + const char *name = g_menu_attribute_iter_get_name (attr_iter); + GVariant *value = g_menu_attribute_iter_get_value (attr_iter); + + if (g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)) + { + gchar *str; + str = g_markup_printf_escaped (" %s='%s'", name, g_variant_get_string (value, NULL)); + g_string_append (attrs, str); + g_free (str); + } + + else + { + gchar *printed; + gchar *str; + const gchar *type; + + printed = g_variant_print (value, TRUE); + type = g_variant_type_peek_string (g_variant_get_type (value)); + str = g_markup_printf_escaped ("%s\n", name, type, printed); + indent_string (contents, indent + tabstop); + g_string_append (contents, str); + g_free (printed); + g_free (str); + } + + g_variant_unref (value); + } + g_object_unref (attr_iter); + + while (g_menu_link_iter_next (link_iter)) + { + const gchar *name = g_menu_link_iter_get_name (link_iter); + GMenuModel *menu = g_menu_link_iter_get_value (link_iter); + gchar *str; + + if (contents->str[0]) + g_string_append_c (contents, '\n'); + + str = g_markup_printf_escaped ("\n", name); + indent_string (contents, indent + tabstop); + g_string_append (contents, str); + g_free (str); + + g_menu_markup_print_string (contents, menu, indent + 2 * tabstop, tabstop); + + indent_string (contents, indent + tabstop); + g_string_append (contents, "\n"); + g_object_unref (menu); + } + g_object_unref (link_iter); + + if (contents->str[0]) + { + indent_string (string, indent); + g_string_append_printf (string, "\n", attrs->str); + g_string_append (string, contents->str); + indent_string (string, indent); + g_string_append (string, "\n"); + need_nl = TRUE; + } + + else + { + if (need_nl) + g_string_append_c (string, '\n'); + + indent_string (string, indent); + g_string_append_printf (string, "\n", attrs->str); + need_nl = FALSE; + } + + g_string_free (contents, TRUE); + g_string_free (attrs, TRUE); + } + + return string; +} + /* TestItem {{{1 */ /* This utility struct is used by both the RandomMenu and MirrorMenu @@ -789,189 +909,6 @@ test_dbus_threaded (void) g_object_unref (menu[i]); } -typedef struct { - GMenu *menu; - GHashTable *objects; -} ParserData; - -static void -start_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error) -{ - ParserData *data = user_data; - - if (g_strcmp0 (element_name, "menu") == 0) - g_menu_markup_parser_start_menu (context, "domain", data->objects); -} - -static void -end_element (GMarkupParseContext *context, - const gchar *element_name, - gpointer user_data, - GError **error) -{ - ParserData *data = user_data; - - if (g_strcmp0 (element_name, "menu") == 0) - data->menu = g_menu_markup_parser_end_menu (context); -} - -static GMenuModel * -parse_menu_string (const gchar *string, GHashTable *objects, GError **error) -{ - const GMarkupParser parser = { - start_element, end_element, NULL, NULL, NULL - }; - GMarkupParseContext *context; - ParserData data; - - data.menu = NULL; - data.objects = objects; - - context = g_markup_parse_context_new (&parser, 0, &data, NULL); - g_markup_parse_context_parse (context, string, -1, error); - g_markup_parse_context_free (context); - - return (GMenuModel*)data.menu; -} - -static gchar * -menu_to_string (GMenuModel *menu) -{ - GString *s; - - s = g_string_new ("\n"); - g_menu_markup_print_string (s, menu, 2, 2); - g_string_append (s, "\n"); - - return g_string_free (s, FALSE); -} - -const gchar menu_data[] = - "\n" - "
\n" - " \n" - " '_Undo'\n" - " \n" - " \n" - "
\n" - "
\n" - "
\n" - " \n" - " \n" - " \n" - "
\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " 'quite-some-action'\n" - " 36\n" - " ['a','b']\n" - " 's(uu)'\n" - " 'small blue thing'\n" - " \n" - " \n" - "
\n"; - -static void -test_markup_roundtrip (void) -{ - GError *error = NULL; - GMenuModel *a; - GMenuModel *b; - gchar *s; - gchar *s2; - - a = parse_menu_string (menu_data, NULL, &error); - g_assert_no_error (error); - g_assert (G_IS_MENU_MODEL (a)); - - /* normalized representation */ - s = menu_to_string (a); - - b = parse_menu_string (s, NULL, &error); - g_assert_no_error (error); - g_assert (G_IS_MENU_MODEL (b)); - - assert_menus_equal (G_MENU_MODEL (a), G_MENU_MODEL (b)); - - s2 = menu_to_string (b); - - g_assert_cmpstr (s, ==, s2); - - g_object_unref (a); - g_object_unref (b); - g_free (s); - g_free (s2); -} - -static void -test_markup_objects (void) -{ - GMenuModel *a, *b; - GHashTable *objects; - GError *error = NULL; - - objects = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); - a = parse_menu_string (menu_data, objects, &error); - g_assert_no_error (error); - g_assert (G_IS_MENU_MODEL (a)); - g_assert_cmpint (g_hash_table_size (objects), ==, 1); - b = g_hash_table_lookup (objects, "blargh"); - g_assert (G_IS_MENU_MODEL (b)); - g_object_unref (a); - g_hash_table_unref (objects); -} - -const gchar menu_data2[] = - "" - "
" - " " - "
" - "
\n" - "
" - " " - "
" - "
" - " " - " " - "
" - " " - "
" - "
" - "
" - "
"; -static void -test_markup_ids (void) -{ - GMenuModel *a, *b; - GHashTable *objects; - GError *error = NULL; - - objects = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); - a = parse_menu_string (menu_data2, objects, &error); - g_assert_no_error (error); - g_assert (G_IS_MENU_MODEL (a)); - g_assert_cmpint (g_hash_table_size (objects), ==, 3); - b = g_hash_table_lookup (objects, "section1"); - g_assert (G_IS_MENU_MODEL (b)); - b = g_hash_table_lookup (objects, "section2"); - g_assert (G_IS_MENU_MODEL (b)); - b = g_hash_table_lookup (objects, "submenu1"); - g_assert (G_IS_MENU_MODEL (b)); - g_object_unref (a); - g_hash_table_unref (objects); -} - static void test_attributes (void) { @@ -1078,73 +1015,7 @@ test_mutable (void) g_object_unref (menu); } -static void -test_misc (void) -{ - /* trying to use most of the GMenu api for constructing the - * same menu two different ways - */ - GMenu *a, *m, *m2; - GMenuModel *b; - GMenuItem *item; - const gchar *s; - - a = g_menu_new (); - item = g_menu_item_new ("test1", "action1::target1"); - g_menu_prepend_item (a, item); - g_object_unref (item); - - m = g_menu_new (); - g_menu_prepend (m, "test2a", "action2"); - g_menu_append (m, "test2c", NULL); - g_menu_insert (m, 1, "test2b", NULL); - - item = g_menu_item_new_submenu ("test2", G_MENU_MODEL (m)); - g_menu_append_item (a, item); - g_object_unref (item); - g_object_unref (m); - - m = g_menu_new (); - - m2 = g_menu_new (); - g_menu_append (m2, "x", NULL); - g_menu_prepend_section (m, "test3a", G_MENU_MODEL (m2)); - g_object_unref (m2); - - item = g_menu_item_new_section ("test3", G_MENU_MODEL (m)); - g_menu_insert_item (a, -1, item); - g_object_unref (item); - g_object_unref (m); - - s = "" -"" -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -""; - - b = parse_menu_string (s, NULL, NULL); - - assert_menus_equal (G_MENU_MODEL (a), G_MENU_MODEL (b)); - g_object_unref (a); - g_object_unref (b); -} - - /* Epilogue {{{1 */ +/* Epilogue {{{1 */ int main (int argc, char **argv) { @@ -1157,13 +1028,9 @@ main (int argc, char **argv) g_test_add_func ("/gmenu/dbus/roundtrip", test_dbus_roundtrip); g_test_add_func ("/gmenu/dbus/subscriptions", test_dbus_subscriptions); g_test_add_func ("/gmenu/dbus/threaded", test_dbus_threaded); - g_test_add_func ("/gmenu/markup/roundtrip", test_markup_roundtrip); - g_test_add_func ("/gmenu/markup/objects", test_markup_objects); - g_test_add_func ("/gmenu/markup/ids", test_markup_ids); g_test_add_func ("/gmenu/attributes", test_attributes); g_test_add_func ("/gmenu/links", test_links); g_test_add_func ("/gmenu/mutable", test_mutable); - g_test_add_func ("/gmenu/misc", test_misc); return g_test_run (); }