[gtk+/wip/gmenu] GtkApplication: Extract accelerators from menus



commit 700bea7f47fc0ebb5e33340509ce595a87970b69
Author: Matthias Clasen <mclasen redhat com>
Date:   Mon Dec 5 17:41:56 2011 -0500

    GtkApplication: Extract accelerators from menus
    
    This allows to specify accelerators in a convenient way, by
    adding accel="..." attributes to the menu items in the
    XML for the menu.
    
    Currently, the accelerators are extracted only once, when the
    menu property is changed on the application.

 gtk/gtkapplication.c |   78 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 78 insertions(+), 0 deletions(-)
---
diff --git a/gtk/gtkapplication.c b/gtk/gtkapplication.c
index 3ba6bf1..6dd2818 100644
--- a/gtk/gtkapplication.c
+++ b/gtk/gtkapplication.c
@@ -348,10 +348,88 @@ gtk_application_window_removed (GtkApplication *application,
 }
 
 static void
+extract_accel_from_menu_item (GMenuModel     *model,
+                              gint            item,
+                              GtkApplication *app)
+{
+  GMenuAttributeIter *iter;
+  const gchar *key;
+  GVariant *value;
+  const gchar *accel = NULL;
+  const gchar *action = NULL;
+  GVariant *target = NULL;
+
+  iter = g_menu_model_iterate_item_attributes (model, item);
+  while (g_menu_attribute_iter_get_next (iter, &key, &value))
+    {
+      if (g_str_equal (key, "action") && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
+        action = g_variant_get_string (value, NULL);
+      else if (g_str_equal (key, "accel") && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
+        accel = g_variant_get_string (value, NULL);
+      else if (g_str_equal (key, "target"))
+        target = g_variant_ref (value);
+      g_variant_unref (value);
+    }
+  g_object_unref (iter);
+
+  if (accel && action)
+    gtk_application_add_accelerator (app, accel, action, target);
+
+  if (target)
+    g_variant_unref (target);
+}
+
+static void
+extract_accels_from_menu (GMenuModel     *model,
+                          GtkApplication *app)
+{
+  gint i;
+  GMenuLinkIter *iter;
+  const gchar *key;
+  GMenuModel *m;
+
+  for (i = 0; i < g_menu_model_get_n_items (model); i++)
+    {
+      extract_accel_from_menu_item (model, i, app);
+
+      iter = g_menu_model_iterate_item_links (model, i);
+      while (g_menu_link_iter_get_next (iter, &key, &m))
+        {
+          extract_accels_from_menu (m, app);
+          g_object_unref (m);
+        }
+      g_object_unref (iter);
+    }
+}
+
+static void
+gtk_application_notify (GObject    *object,
+                        GParamSpec *pspec)
+{
+  if (strcmp (pspec->name, "app-menu") == 0 ||
+      strcmp (pspec->name, "menubar") == 0)
+    {
+      GMenuModel *model;
+      g_object_get (object, pspec->name, &model, NULL);
+      if (model)
+        {
+          extract_accels_from_menu (model, GTK_APPLICATION (object));
+          g_object_unref (model);
+        }
+    }
+
+  if (G_OBJECT_CLASS (gtk_application_parent_class)->notify)
+    G_OBJECT_CLASS (gtk_application_parent_class)->notify (object, pspec);
+}
+
+static void
 gtk_application_class_init (GtkApplicationClass *class)
 {
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
   GApplicationClass *application_class = G_APPLICATION_CLASS (class);
 
+  object_class->notify = gtk_application_notify;
+
   application_class->add_platform_data = gtk_application_add_platform_data;
   application_class->before_emit = gtk_application_before_emit;
   application_class->after_emit = gtk_application_after_emit;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]