]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkmodelmenuitem.c
filechooserbutton: whitespace fixes
[~andy/gtk] / gtk / gtkmodelmenuitem.c
index 07cad7093c88dc02e20df6d7d739c3b6c7f89c04..6d902c2352d3502f97678f872be62120c2aaf60d 100644 (file)
@@ -23,7 +23,8 @@
 
 #include "gtkaccelmapprivate.h"
 #include "gtkactionhelper.h"
-#include "gtkmodelmenu.h"
+#include "gtkwidgetprivate.h"
+#include "gtkaccellabel.h"
 
 struct _GtkModelMenuItem
 {
@@ -63,11 +64,50 @@ gtk_model_menu_item_draw_indicator (GtkCheckMenuItem *check_item,
       ->draw_indicator (check_item, cr);
 }
 
+static void
+gtk_actionable_set_namespaced_action_name (GtkActionable *actionable,
+                                           const gchar   *namespace,
+                                           const gchar   *action_name)
+{
+  if (namespace)
+    {
+      gchar *name = g_strdup_printf ("%s.%s", namespace, action_name);
+      gtk_actionable_set_action_name (actionable, name);
+      g_free (name);
+    }
+  else
+    {
+      gtk_actionable_set_action_name (actionable, action_name);
+    }
+}
+
+static void
+gtk_model_menu_item_submenu_shown (GtkWidget *widget,
+                                   gpointer   user_data)
+{
+  const gchar *action_name = user_data;
+  GActionMuxer *muxer;
+
+  muxer = _gtk_widget_get_action_muxer (widget);
+  g_action_group_change_action_state (G_ACTION_GROUP (muxer), action_name, g_variant_new_boolean (TRUE));
+}
+
+static void
+gtk_model_menu_item_submenu_hidden (GtkWidget *widget,
+                                    gpointer   user_data)
+{
+  const gchar *action_name = user_data;
+  GActionMuxer *muxer;
+
+  muxer = _gtk_widget_get_action_muxer (widget);
+  g_action_group_change_action_state (G_ACTION_GROUP (muxer), action_name, g_variant_new_boolean (FALSE));
+}
+
 static void
 gtk_model_menu_item_setup (GtkModelMenuItem  *item,
                            GMenuModel        *model,
                            gint               item_index,
-                           GtkAccelGroup     *accels)
+                           const gchar       *action_namespace)
 {
   GMenuAttributeIter *iter;
   GMenuModel *submenu;
@@ -76,7 +116,24 @@ gtk_model_menu_item_setup (GtkModelMenuItem  *item,
 
   if ((submenu = g_menu_model_get_item_link (model, item_index, "submenu")))
     {
-      gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), gtk_model_menu_create_menu (submenu, accels));
+      gchar *section_namespace = NULL;
+      GtkWidget *menu;
+
+      g_menu_model_get_item_attribute (model, item_index, "action-namespace", "s", &section_namespace);
+      menu = gtk_menu_new ();
+
+      if (action_namespace)
+        {
+          gchar *namespace = g_strjoin (".", action_namespace, section_namespace, NULL);
+          gtk_menu_shell_bind_model (GTK_MENU_SHELL (menu), submenu, namespace, TRUE);
+          g_free (namespace);
+        }
+      else
+        gtk_menu_shell_bind_model (GTK_MENU_SHELL (menu), submenu, section_namespace, TRUE);
+
+      gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), menu);
+
+      g_free (section_namespace);
       g_object_unref (submenu);
     }
 
@@ -86,12 +143,55 @@ gtk_model_menu_item_setup (GtkModelMenuItem  *item,
       if (g_str_equal (key, "label") && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
         gtk_menu_item_set_label (GTK_MENU_ITEM (item), g_variant_get_string (value, NULL));
 
+      else if (g_str_equal (key, "accel") && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
+        {
+          GdkModifierType modifiers;
+          guint key;
+
+          gtk_accelerator_parse (g_variant_get_string (value, NULL), &key, &modifiers);
+
+          if (key)
+            {
+              GtkAccelLabel *accel_label;
+
+              /* Ensure that the GtkAccelLabel has been created... */
+              (void) gtk_menu_item_get_label (GTK_MENU_ITEM (item));
+              accel_label = GTK_ACCEL_LABEL (gtk_bin_get_child (GTK_BIN (item)));
+              g_assert (accel_label);
+
+              gtk_accel_label_set_accel (accel_label, key, modifiers);
+            }
+        }
+
       else if (g_str_equal (key, "action") && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
-        gtk_actionable_set_action_name (GTK_ACTIONABLE (item), g_variant_get_string (value, NULL));
+        gtk_actionable_set_namespaced_action_name (GTK_ACTIONABLE (item), action_namespace,
+                                                   g_variant_get_string (value, NULL));
 
       else if (g_str_equal (key, "target"))
         gtk_actionable_set_action_target_value (GTK_ACTIONABLE (item), value);
 
+      else if (g_str_equal (key, "submenu-action") && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
+        {
+          GtkWidget *submenu;
+
+          submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (item));
+
+          if (submenu != NULL)
+            {
+              const gchar *action = g_variant_get_string (value, NULL);
+              gchar *full_action;
+
+              if (action_namespace)
+                full_action = g_strjoin (".", action_namespace, action, NULL);
+              else
+                full_action = g_strdup (action);
+
+              g_object_set_data_full (G_OBJECT (submenu), "gtkmodelmenu-visibility-action", full_action, g_free);
+              g_signal_connect (submenu, "show", G_CALLBACK (gtk_model_menu_item_submenu_shown), full_action);
+              g_signal_connect (submenu, "hide", G_CALLBACK (gtk_model_menu_item_submenu_hidden), full_action);
+            }
+        }
+
       g_variant_unref (value);
     }
   g_object_unref (iter);
@@ -178,13 +278,13 @@ gtk_model_menu_item_class_init (GtkModelMenuItemClass *class)
 GtkMenuItem *
 gtk_model_menu_item_new (GMenuModel        *model,
                          gint               item_index,
-                         GtkAccelGroup     *accels)
+                         const gchar       *action_namespace)
 {
   GtkModelMenuItem *item;
 
   item = g_object_new (GTK_TYPE_MODEL_MENU_ITEM, NULL);
 
-  gtk_model_menu_item_setup (item, model, item_index, accels);
+  gtk_model_menu_item_setup (item, model, item_index, action_namespace);
 
   return GTK_MENU_ITEM (item);
 }