Drop the GMenu markup functions
authorRyan Lortie <desrt@desrt.ca>
Thu, 26 Jan 2012 00:55:33 +0000 (19:55 -0500)
committerRyan Lortie <desrt@desrt.ca>
Thu, 26 Jan 2012 02:05:27 +0000 (21:05 -0500)
The parser has been moved into Gtk in a modified form and the printer
was never really useful anyway (except for debugging/testing).

gio/Makefile.am
gio/gio.h
gio/gmenumarkup.c [deleted file]
gio/gmenumarkup.h [deleted file]
gio/menumarkup.dtd [deleted file]
gio/menumarkup.xml [deleted file]
gio/menumarkup2.xml [deleted file]
gio/tests/gmenumodel.c

index 815465e..9ad8434 100644 (file)
@@ -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 =             \
index 6e26e50..94ce721 100644 (file)
--- a/gio/gio.h
+++ b/gio/gio.h
 #include <gio/gmenumodel.h>
 #include <gio/gmenu.h>
 #include <gio/gmenuexporter.h>
-#include <gio/gmenumarkup.h>
 #include <gio/gdbusmenumodel.h>
 
 #undef __GIO_GIO_H_INSIDE__
diff --git a/gio/gmenumarkup.c b/gio/gmenumarkup.c
deleted file mode 100644 (file)
index 3564c2e..0000000
+++ /dev/null
@@ -1,741 +0,0 @@
-/*
- * Copyright © 2011 Canonical Ltd.
- * All rights reserved.
- *
- * Author: Ryan Lortie <desrt@desrt.ca>
- */
-
-#include "gmenumarkup.h"
-
-#include <gi18n.h>
-
-/**
- * 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
- * <tag class="starttag">menu</tag> element, which contains one or more
- * <tag class="starttag">item</tag> elements. Each <tag class="starttag">item</tag>
- * element contains <tag class="starttag">attribute</tag> and <tag class="starttag">link</tag>
- * elements with a mandatory name attribute.
- * <tag class="starttag">link</tag> elements have the same content
- * model as <tag class="starttag">menu</tag>.
- *
- * Here is the XML for <xref linkend="menu-example"/>:
- * |[<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gio/menumarkup2.xml"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include>]|
- *
- * The parser also understands a somewhat less verbose format, in which
- * attributes are encoded as actual XML attributes of <tag class="starttag">item</tag>
- * elements, and <tag class="starttag">link</tag> elements are replaced by
- * <tag class="starttag">section</tag> and <tag class="starttag">submenu</tag> elements.
- *
- * Here is how the example looks in this format:
- * |[<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gio/menumarkup.xml"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include>]|
- *
- * The parser can obtaing translations for attribute values using gettext.
- * To make use of this, the <tag class="starttag">menu</tag> element must
- * have a domain attribute which specifies the gettext domain to use, and
- * <tag class="starttag">attribute</tag> elements can be marked for translation
- * with a <literal>translatable="yes"</literal> 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:
- * |[<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gio/menumarkup.dtd"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include>]|
- *
- * 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 <menu> 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 '<item>', '<submenu>' or '<section>' 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 '<attribute>' or '<link>' 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: <tag class="starttag">menu</tag>,
- * <tag class="starttag">submenu</tag>,
- * <tag class="starttag">section</tag> or <tag class="starttag">link</tag>
- * 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: <tag class="starttag">submenu</tag>,
- * <tag class="starttag">section</tag> or <tag class="starttag">link</tag>
- * elements with an id='' attribute) that are encountered while parsing
- * will be added to this table.
- * Note that toplevel <tag class="starttag">menu</tag> 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
- * <tag class="starttag">menu</tag> 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 ("<attribute name='%s' type='%s'>%s</attribute>\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 ("<link name='%s'>\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, "</link>\n");
-          g_object_unref (menu);
-        }
-      g_object_unref (link_iter);
-
-      if (contents->str[0])
-        {
-          indent_string (string, indent);
-          g_string_append_printf (string, "<item%s>\n", attrs->str);
-          g_string_append (string, contents->str);
-          indent_string (string, indent);
-          g_string_append (string, "</item>\n");
-          need_nl = TRUE;
-        }
-
-      else
-        {
-          if (need_nl)
-            g_string_append_c (string, '\n');
-
-          indent_string (string, indent);
-          g_string_append_printf (string, "<item%s/>\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 ("<menu>\n");
-  g_menu_markup_print_string (string, model, 2, 2);
-  g_printerr ("%s</menu>\n", string->str);
-  g_string_free (string, TRUE);
-}
diff --git a/gio/gmenumarkup.h b/gio/gmenumarkup.h
deleted file mode 100644 (file)
index 1dfb326..0000000
+++ /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 <desrt@desrt.ca>
- */
-
-#ifndef __G_MENU_MARKUP_H__
-#define __G_MENU_MARKUP_H__
-
-#include <gio/gmenu.h>
-
-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 (file)
index a554910..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-<!ELEMENT menu (item|submenu|section)* >
-<!ATTLIST menu id     CDATA #REQUIRED
-               domain #IMPLIED >
-
-<!ELEMENT item (attribute|link)* >
-<!ATTLIST item label CDATA #IMPLIED
-               action CDATA #IMPLIED
-               target CDATA #IMPLIED >
-
-<!ELEMENT attribute (#PCDATA) >
-<!ATTLIST attribute name         CDATA #REQUIRED
-                    type         CDATA #IMPLIED
-                    translatable (yes|no) #IMPLIED
-                    context      CDATA #IMPLIED
-                    comments     CDATA #IMPLIED >
-
-<!ELEMENT link (item*) >
-<!ATTLIST link name CDATA #REQUIRED
-               id   CDATA #IMPLIED >
-
-<!ELEMENT submenu (item|submenu|section)* >
-<!ATTLIST submenu label CDATA #IMPLIED
-                  action CDATA #IMPLIED
-                  target CDATA #IMPLIED >
-
-<!ELEMENT section (item|submenu|section)* >
-<!ATTLIST section label CDATA #IMPLIED
-                  action CDATA #IMPLIED
-                  target CDATA #IMPLIED >
diff --git a/gio/menumarkup.xml b/gio/menumarkup.xml
deleted file mode 100644 (file)
index 8c0ef30..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-<menu id='menubar'>
-  <submenu label='File'></submenu>
-  <submenu label='Edit'></submenu>
-  <submenu label='View'>
-    <section>
-      <item label='Toolbar' action='toolbar'/>
-      <item label='Statusbar' action='statusbar'/>
-    </section>
-    <section>
-      <item label='Fullscreen' action='fullscreen'/>
-    </section>
-    <section>
-      <submenu label='Highlight Mode'>
-        <section label='Sources'>
-           <item label='Vala' action='sources' target='vala'/>
-           <item label='Python' action='sources' target='python'/>
-        </section>
-        <section label='Markup'>
-           <item label='asciidoc' action='markup' target='asciidoc'/>
-           <item label='HTML' action='markup' target='html'/>
-        </section>
-      </submenu>
-    </section>
-  </submenu>
-  <submenu label='Help'></submenu>
-</menu>
diff --git a/gio/menumarkup2.xml b/gio/menumarkup2.xml
deleted file mode 100644 (file)
index a505e88..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-<menu id='menubar'>
-  <item>
-    <attribute name='label'>File</attribute>
-  </item>
-  <item>
-    <attribute name='label'>Edit</attribute>
-  </item>
-  <item>
-    <attribute name='label'>View</attribute>
-    <link name='submenu'>
-      <item>
-        <link name='section'>
-          <item>
-            <attribute name='label'>Toolbar</attribute>
-            <attribute name='action'>toolbar</attribute>
-          </item>
-          <item>
-            <attribute name='label'>Statusbar</attribute>
-            <attribute name='action'>statusbar</attribute>
-          </item>
-        </link>
-      </item>
-      <item>
-        <link name='section'>
-          <item>
-            <attribute name='label'>Fullscreen</attribute>
-            <attribute name='action'>fullscreen</attribute>
-          </item>
-        </link>
-      </item>
-      <item>
-        <link name='section'>
-          <item>
-            <attribute name='label'>Highlight Mode</attribute>
-            <link name='submenu'>
-              <item>
-                <attribute name='label'>Sources</attribute>
-                <link name='section'>
-                  <item>
-                    <attribute name='label'>Vala</attribute>
-                    <attribute name='action'>sources</attribute>
-                    <attribute name='target'>vala</attribute>
-                  </item>
-                  <item>
-                    <attribute name='label'>Python</attribute>
-                    <attribute name='action'>sources</attribute>
-                    <attribute name='target'>python</attribute>
-                  </item>
-                </link>
-              </item>
-              <item>
-                <attribute name='label'>Markup</attribute>
-                <link name='section'>
-                  <item>
-                    <attribute name='label'>asciidoc</attribute>
-                    <attribute name='action'>markup</attribute>
-                    <attribute name='target'>asciidoc</attribute>
-                  </item>
-                  <item>
-                    <attribute name='label'>HTML</attribute>
-                    <attribute name='action'>markup</attribute>
-                    <attribute name='target'>html</attribute>
-                  </item>
-                </link>
-              </item>
-            </link>
-          </item>
-        </link>
-      </item>
-    </link>
-  </item>
-  <item>
-    <attribute name='label'>Help</attribute>
-  </item>
-</menu>
index 4253f99..d8eb567 100644 (file)
@@ -1,5 +1,125 @@
 #include <gio/gio.h>
 
+/* 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 ("<attribute name='%s' type='%s'>%s</attribute>\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 ("<link name='%s'>\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, "</link>\n");
+          g_object_unref (menu);
+        }
+      g_object_unref (link_iter);
+
+      if (contents->str[0])
+        {
+          indent_string (string, indent);
+          g_string_append_printf (string, "<item%s>\n", attrs->str);
+          g_string_append (string, contents->str);
+          indent_string (string, indent);
+          g_string_append (string, "</item>\n");
+          need_nl = TRUE;
+        }
+
+      else
+        {
+          if (need_nl)
+            g_string_append_c (string, '\n');
+
+          indent_string (string, indent);
+          g_string_append_printf (string, "<item%s/>\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 ("<menu>\n");
-  g_menu_markup_print_string (s, menu, 2, 2);
-  g_string_append (s, "</menu>\n");
-
-  return g_string_free (s, FALSE);
-}
-
-const gchar menu_data[] =
-  "<menu id='edit-menu'>\n"
-  "  <section>\n"
-  "    <item action='undo'>\n"
-  "      <attribute name='label' translatable='yes' context='Stock label'>'_Undo'</attribute>\n"
-  "    </item>\n"
-  "    <item label='Redo' action='redo'/>\n"
-  "  </section>\n"
-  "  <section></section>\n"
-  "  <section label='Copy &amp; Paste'>\n"
-  "    <item label='Cut' action='cut'/>\n"
-  "    <item label='Copy' action='copy'/>\n"
-  "    <item label='Paste' action='paste'/>\n"
-  "  </section>\n"
-  "  <item><link name='section' id='blargh'>\n"
-  "    <item label='Bold' action='bold'/>\n"
-  "    <submenu label='Language'>\n"
-  "      <item label='Latin' action='lang' target='latin'/>\n"
-  "      <item label='Greek' action='lang' target='greek'/>\n"
-  "      <item label='Urdu'  action='lang' target='urdu'/>\n"
-  "    </submenu>\n"
-  "    <item name='test unusual attributes'>\n"
-  "      <attribute name='action' type='s'>'quite-some-action'</attribute>\n"
-  "      <attribute name='target' type='i'>36</attribute>\n"
-  "      <attribute name='chocolate-thunda' type='as'>['a','b']</attribute>\n"
-  "      <attribute name='thing1' type='g'>'s(uu)'</attribute>\n"
-  "      <attribute name='icon' type='s'>'small blue thing'</attribute>\n"
-  "   </item>\n"
-  "  </link></item>\n"
-  "</menu>\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[] =
-  "<menu>"
-  "  <section>"
-  "    <item label='Redo' action='redo'/>"
-  "  </section>"
-  "  <section></section>\n"
-  "  <section label='Copy &amp; Paste'>"
-  "    <item label='Cut' action='cut'/>"
-  "  </section>"
-  "  <section id='section1'>"
-  "    <item label='Bold' action='bold'/>"
-  "    <submenu label='Language' id='submenu1'>"
-  "      <section id='section2'>"
-  "        <item label='Urdu'  action='lang' target='urdu'/>"
-  "      </section>"
-  "    </submenu>"
-  "  </section>"
-  "</menu>";
-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 = ""
-"<menu>"
-"  <item target='target1' action='action1' label='test1'/>"
-"  <item label='test2'>"
-"    <link name='submenu'>"
-"      <item action='action2' label='test2a'/>"
-"      <item label='test2b'/>"
-"      <item label='test2c'/>"
-"    </link>"
-"  </item>"
-"  <item label='test3'>"
-"    <link name='section'>"
-"      <item label='test3a'>"
-"        <link name='section'>"
-"          <item label='x'/>"
-"        </link>"
-"      </item>"
-"    </link>"
-"  </item>"
-"</menu>";
-
-  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 ();
 }