Index: gtkmenuitem.c
===================================================================
--- gtkmenuitem.c	(revision 21804)
+++ gtkmenuitem.c	(working copy)
@@ -37,9 +37,16 @@
 #include "gtkseparatormenuitem.h"
 #include "gtkprivate.h"
 #include "gtkbuildable.h"
+#include "gtkactivatable.h"
 #include "gtkintl.h"
 #include "gtkalias.h"
 
+
+typedef struct {
+  GtkAction *action;
+  gboolean   use_action_appearance;
+} GtkMenuItemPrivate;
+
 enum {
   ACTIVATE,
   ACTIVATE_ITEM,
@@ -54,7 +61,11 @@ enum {
   PROP_SUBMENU,
   PROP_ACCEL_PATH,
   PROP_LABEL,
-  PROP_USE_UNDERLINE
+  PROP_USE_UNDERLINE,
+
+  /* activatable properties */
+  PROP_ACTIVATABLE_ACTION,
+  PROP_ACTIVATABLE_USE_APPEARANCE
 };
 
 
@@ -120,13 +131,27 @@ static void gtk_menu_item_buildable_add_
 						    GObject             *child,
 						    const gchar         *type);
 
+static void gtk_menu_item_activatable_interface_init (GtkActivatableIface  *iface);
+static void gtk_menu_item_activatable_update         (GtkActivatable       *activatable,
+						      const gchar          *property_name);
+static void gtk_menu_item_set_related_action         (GtkMenuItem          *menu_item, 
+						      GtkAction            *action);
+static void gtk_menu_item_set_use_action_appearance  (GtkMenuItem          *menu_item, 
+						      gboolean              use_appearance);
+
+
 static guint menu_item_signals[LAST_SIGNAL] = { 0 };
 
 static GtkBuildableIface *parent_buildable_iface;
 
 G_DEFINE_TYPE_WITH_CODE (GtkMenuItem, gtk_menu_item, GTK_TYPE_ITEM,
 			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
-						gtk_menu_item_buildable_interface_init))
+						gtk_menu_item_buildable_interface_init)
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
+						gtk_menu_item_activatable_interface_init))
+
+#define GET_PRIVATE(object)  \
+  (G_TYPE_INSTANCE_GET_PRIVATE ((object), GTK_TYPE_MENU_ITEM, GtkMenuItemPrivate))
 
 static void
 gtk_menu_item_class_init (GtkMenuItemClass *klass)
@@ -288,6 +313,9 @@ gtk_menu_item_class_init (GtkMenuItemCla
 							 FALSE,
 							 GTK_PARAM_READWRITE));
 
+  g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_ACTION, "related-action");
+  g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_USE_APPEARANCE, "use-action-appearance");
+
   gtk_widget_class_install_style_property_parser (widget_class,
 						  g_param_spec_enum ("selected-shadow-type",
 								     "Selected Shadow Type",
@@ -344,12 +372,19 @@ gtk_menu_item_class_init (GtkMenuItemCla
                                                              P_("The minimum desired width of the menu item in characters"),
                                                              0, G_MAXINT, 12,
                                                              GTK_PARAM_READABLE));
+
+  g_type_class_add_private (object_class, sizeof (GtkMenuItemPrivate));
 }
 
 static void
 gtk_menu_item_init (GtkMenuItem *menu_item)
 {
+  GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
+
   GTK_WIDGET_SET_FLAGS (menu_item, GTK_NO_WINDOW);
+
+  priv->action = NULL;
+  priv->use_action_appearance = FALSE;
   
   menu_item->submenu = NULL;
   menu_item->toggle_size = 0;
@@ -424,7 +459,12 @@ gtk_menu_item_set_property (GObject     
     case PROP_USE_UNDERLINE:
       gtk_menu_item_set_use_underline (menu_item, g_value_get_boolean (value));
       break;
-
+    case PROP_ACTIVATABLE_ACTION:
+      gtk_menu_item_set_related_action (menu_item, g_value_get_object (value));
+      break;
+    case PROP_ACTIVATABLE_USE_APPEARANCE:
+      gtk_menu_item_set_use_action_appearance (menu_item, g_value_get_boolean (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -438,6 +478,7 @@ gtk_menu_item_get_property (GObject    *
 			    GParamSpec *pspec)
 {
   GtkMenuItem *menu_item = GTK_MENU_ITEM (object);
+  GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
   
   switch (prop_id)
     {
@@ -456,7 +497,12 @@ gtk_menu_item_get_property (GObject    *
     case PROP_USE_UNDERLINE:
       g_value_set_boolean (value, gtk_menu_item_get_use_underline (menu_item));
       break;
-
+    case PROP_ACTIVATABLE_ACTION:
+      g_value_set_object (value, priv->action);
+      break;
+    case PROP_ACTIVATABLE_USE_APPEARANCE:
+      g_value_set_boolean (value, priv->use_action_appearance);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -505,6 +551,146 @@ gtk_menu_item_buildable_add_child (GtkBu
     parent_buildable_iface->add_child (buildable, builder, child, type);
 }
 
+static void
+gtk_menu_item_activatable_interface_init (GtkActivatableIface *iface)
+{
+  iface->update = gtk_menu_item_activatable_update;
+}
+
+static void 
+activatable_update_accel_path (GtkMenuItem *menu_item)
+{
+  GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
+  const gchar *accel_path;
+
+  accel_path = gtk_action_get_accel_path (priv->action);
+
+  if (accel_path)
+    gtk_menu_item_set_accel_path (menu_item, accel_path);
+}
+
+static void 
+activatable_update_label (GtkMenuItem *menu_item)
+{
+  GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
+  GtkWidget *child = GTK_BIN (menu_item)->child;
+	  
+  if (GTK_IS_LABEL (child))
+    {
+      const gchar *label;
+
+      label = gtk_action_get_label (priv->action);
+      gtk_label_set_label (GTK_LABEL (child), label ? label : "");
+    }
+}
+
+static void
+gtk_menu_item_activatable_update (GtkActivatable *activatable,
+				  const gchar    *property_name)
+{
+  GtkMenuItem *menu_item = GTK_MENU_ITEM (activatable);
+  GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
+
+  if (property_name == NULL)
+    {
+      if (gtk_action_is_visible (priv->action))
+	gtk_widget_show (GTK_WIDGET (menu_item));
+      else
+	gtk_widget_hide (GTK_WIDGET (menu_item));
+
+      gtk_widget_set_sensitive (GTK_WIDGET (menu_item), gtk_action_is_sensitive (priv->action));
+
+      activatable_update_accel_path (menu_item);
+
+      if (priv->use_action_appearance)
+	{
+	  GtkWidget *label = GTK_BIN (menu_item)->child;
+	  
+	  /* make sure label is a label */
+	  if (label && !GTK_IS_LABEL (label))
+	    {
+	      gtk_container_remove (GTK_CONTAINER (menu_item), label);
+	      label = NULL;
+	    }
+	  
+	  if (!label)
+	    label = g_object_new (GTK_TYPE_ACCEL_LABEL,
+				  "use-underline", TRUE,
+				  "xalign", 0.0,
+				  "visible", TRUE,
+				  "parent", menu_item,
+				  NULL);
+	  
+	  if (GTK_IS_ACCEL_LABEL (label) && gtk_action_get_accel_path (priv->action))
+	    g_object_set (label,
+			  "accel-closure", gtk_action_get_accel_closure (priv->action),
+			  NULL);
+
+	  activatable_update_label (menu_item);
+	}
+    }
+  else if (strcmp (property_name, "visible") == 0)
+    {
+      if (gtk_action_is_visible (priv->action))
+	gtk_widget_show (GTK_WIDGET (menu_item));
+      else
+	gtk_widget_hide (GTK_WIDGET (menu_item));
+    }
+  else if (strcmp (property_name, "sensitive") == 0)
+    gtk_widget_set_sensitive (GTK_WIDGET (menu_item), gtk_action_is_sensitive (priv->action));
+  else if (strcmp (property_name, "accel-path") == 0)
+    activatable_update_accel_path (menu_item);
+  else if (priv->use_action_appearance)
+    {
+      if (strcmp (property_name, "label") == 0)
+	  activatable_update_label (menu_item);
+    }
+}
+
+static void
+gtk_menu_item_action_notify (GtkAction   *action,
+			     GParamSpec  *pspec,
+			     GtkMenuItem *menu_item)
+{
+  gtk_activatable_update (GTK_ACTIVATABLE (menu_item), pspec->name);
+}
+
+static void
+gtk_menu_item_set_related_action (GtkMenuItem *menu_item, 
+				  GtkAction   *action)
+{
+    GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
+
+    if (priv->action == action)
+      return;
+
+    if (priv->action)
+      g_signal_handlers_disconnect_by_func (priv->action, gtk_menu_item_action_notify, menu_item);
+
+    g_signal_connect (G_OBJECT (action), "notify", G_CALLBACK (gtk_menu_item_action_notify), menu_item);
+
+    priv->action = action;
+
+    if (action)
+      gtk_activatable_update (GTK_ACTIVATABLE (menu_item), NULL);
+}
+
+static void
+gtk_menu_item_set_use_action_appearance (GtkMenuItem *menu_item, 
+					 gboolean     use_appearance)
+{
+    GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
+
+    if (priv->use_action_appearance != use_appearance)
+      {
+	priv->use_action_appearance = use_appearance;
+
+	if (priv->action && use_appearance)
+	  gtk_activatable_update (GTK_ACTIVATABLE (menu_item), NULL);
+      }
+}
+
+
 /**
  * gtk_menu_item_set_submenu:
  * @menu_item: a #GtkMenuItem
@@ -1145,10 +1331,12 @@ gtk_menu_item_mnemonic_activate (GtkWidg
 static void
 gtk_real_menu_item_activate_item (GtkMenuItem *menu_item)
 {
+  GtkMenuItemPrivate *priv;
   GtkWidget *widget;
 
   g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
 
+  priv   = GET_PRIVATE (menu_item);
   widget = GTK_WIDGET (menu_item);
   
   if (widget->parent &&
@@ -1169,6 +1357,9 @@ gtk_real_menu_item_activate_item (GtkMen
 	  gtk_menu_shell_select_first (GTK_MENU_SHELL (menu_item->submenu), TRUE);
 	}
     }
+
+  if (priv->action)
+    gtk_action_activate (priv->action);
 }
 
 static void
Index: gtkimagemenuitem.c
===================================================================
--- gtkimagemenuitem.c	(revision 21804)
+++ gtkimagemenuitem.c	(working copy)
@@ -34,6 +34,7 @@
 #include "gtkmenubar.h"
 #include "gtkcontainer.h"
 #include "gtkwindow.h"
+#include "gtkactivatable.h"
 #include "gtkprivate.h"
 #include "gtkalias.h"
 
@@ -70,6 +71,9 @@ static void gtk_image_menu_item_screen_c
 
 static void gtk_image_menu_item_recalculate          (GtkImageMenuItem *image_menu_item);
 
+static void gtk_image_menu_item_activatable_interface_init (GtkActivatableIface  *iface);
+static void gtk_image_menu_item_activatable_update         (GtkActivatable       *activatable,
+							    const gchar          *property_name);
 
 typedef struct {
   gchar          *label;
@@ -83,7 +87,12 @@ enum {
   PROP_ACCEL_GROUP
 };
 
-G_DEFINE_TYPE (GtkImageMenuItem, gtk_image_menu_item, GTK_TYPE_MENU_ITEM)
+static GtkActivatableIface *parent_activatable_iface;
+
+
+G_DEFINE_TYPE_WITH_CODE (GtkImageMenuItem, gtk_image_menu_item, GTK_TYPE_MENU_ITEM,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
+						gtk_image_menu_item_activatable_interface_init))
 
 #define GET_PRIVATE(object)  \
   (G_TYPE_INSTANCE_GET_PRIVATE ((object), GTK_TYPE_IMAGE_MENU_ITEM, GtkImageMenuItemPrivate))
@@ -504,6 +513,97 @@ gtk_image_menu_item_forall (GtkContainer
     (* callback) (image_menu_item->image, callback_data);
 }
 
+
+static void 
+gtk_image_menu_item_activatable_interface_init (GtkActivatableIface  *iface)
+{
+  parent_activatable_iface = g_type_interface_peek_parent (iface);
+  iface->update = gtk_image_menu_item_activatable_update;
+}
+
+static gboolean
+activatable_update_stock_id (GtkImageMenuItem *image_menu_item, GtkAction *action)
+{
+  GtkWidget   *image;
+  const gchar *stock_id  = gtk_action_get_stock_id (action);
+
+  image = gtk_image_menu_item_get_image (image_menu_item);
+	  
+  if (GTK_IS_IMAGE (image) &&
+      stock_id && gtk_icon_factory_lookup_default (stock_id))
+    {
+      gtk_image_set_from_stock (GTK_IMAGE (image), stock_id, GTK_ICON_SIZE_MENU);
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+activatable_update_icon_name (GtkImageMenuItem *image_menu_item, GtkAction *action)
+{
+  GtkWidget   *image;
+  const gchar *icon_name = gtk_action_get_icon_name (action);
+
+  image = gtk_image_menu_item_get_image (image_menu_item);
+	  
+  if (GTK_IS_IMAGE (image) && icon_name &&
+      (gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_EMPTY ||
+       gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_ICON_NAME))
+    {
+      gtk_image_set_from_icon_name (GTK_IMAGE (image), icon_name, GTK_ICON_SIZE_MENU);
+    }
+}
+
+static void 
+gtk_image_menu_item_activatable_update (GtkActivatable       *activatable,
+					const gchar          *property_name)
+{
+  GtkImageMenuItem *image_menu_item;
+  GtkWidget *image;
+  GtkAction *action;
+  gboolean   use_appearance;
+
+  image_menu_item = GTK_IMAGE_MENU_ITEM (activatable);
+
+  parent_activatable_iface->update (activatable, property_name);
+
+  use_appearance = gtk_activatable_get_use_action_appearance (activatable);
+  if (!use_appearance)
+    return;
+
+  action = gtk_activatable_get_related_action (activatable);
+
+  if (property_name == NULL)
+    {
+      const gchar *icon_name = gtk_action_get_icon_name (action);
+
+      image = gtk_image_menu_item_get_image (image_menu_item);
+      if (image && !GTK_IS_IMAGE (image))
+	{
+	  gtk_image_menu_item_set_image (image_menu_item, NULL);
+	  image = NULL;
+	}
+      
+      if (!image)
+	{
+	  image = gtk_image_new ();
+	  gtk_widget_show (image);
+	  gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (activatable),
+					 image);
+	}
+
+      if (!activatable_update_stock_id (image_menu_item, action))
+	activatable_update_icon_name (image_menu_item, action);
+
+    }
+  else if (strcmp (property_name, "stock-id") == 0)
+    activatable_update_stock_id (image_menu_item, action);
+  else if (strcmp (property_name, "icon-name") == 0)
+    activatable_update_icon_name (image_menu_item, action);
+}
+
+
 /**
  * gtk_image_menu_item_new:
  * @returns: a new #GtkImageMenuItem.
