]> git.0d.be Git - empathy.git/blobdiff - libempathy-gtk/empathy-individual-menu.c
translate "Call $NUMBER" menu items
[empathy.git] / libempathy-gtk / empathy-individual-menu.c
index 03a8ee22018745947c74d2319267bf070b26d8cb..5dc1309839142c6c0bcda24124c97ee2c61070ef 100644 (file)
  */
 
 #include "config.h"
-
-#include <string.h>
+#include "empathy-individual-menu.h"
 
 #include <glib/gi18n-lib.h>
-#include <gtk/gtk.h>
-
-#include <telepathy-glib/telepathy-glib.h>
-
-#include <folks/folks.h>
-#include <folks/folks-telepathy.h>
-
-#include <libempathy/empathy-camera-monitor.h>
-#include <libempathy/empathy-request-util.h>
-#include <libempathy/empathy-individual-manager.h>
-#include <libempathy/empathy-chatroom-manager.h>
-#include <libempathy/empathy-utils.h>
+#include <tp-account-widgets/tpaw-camera-monitor.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
 
 #include "empathy-account-selector-dialog.h"
-#include "empathy-individual-menu.h"
+#include "empathy-call-utils.h"
+#include "empathy-chatroom-manager.h"
+#include "empathy-gtk-enum-types.h"
 #include "empathy-images.h"
-#include "empathy-log-window.h"
 #include "empathy-individual-dialogs.h"
-#include "empathy-gtk-enum-types.h"
 #include "empathy-individual-dialogs.h"
 #include "empathy-individual-edit-dialog.h"
-#include "empathy-ui-utils.h"
-#include "empathy-share-my-desktop.h"
-#include "empathy-call-utils.h"
-#include "empathy-individual-store-channel.h"
 #include "empathy-individual-information-dialog.h"
+#include "empathy-individual-manager.h"
+#include "empathy-individual-store-channel.h"
+#include "empathy-log-window.h"
+#include "empathy-request-util.h"
+#include "empathy-share-my-desktop.h"
+#include "empathy-ui-utils.h"
+#include "empathy-utils.h"
 
 #define DEBUG_FLAG EMPATHY_DEBUG_CONTACT
-#include <libempathy/empathy-debug.h>
+#include "empathy-debug.h"
 
 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyIndividualMenu)
 
 typedef struct {
+  gchar *active_group; /* may be NULL */
   FolksIndividual *individual; /* owned */
   EmpathyIndividualFeatureFlags features;
   EmpathyIndividualStore *store; /* may be NULL */
 } EmpathyIndividualMenuPriv;
 
 enum {
-  PROP_INDIVIDUAL = 1,
+  PROP_ACTIVE_GROUP = 1,
+  PROP_INDIVIDUAL,
   PROP_FEATURES,
   PROP_STORE,
 };
 
+enum {
+  MENU_ITEM_ACTIVATED,
+  LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0 };
+
 G_DEFINE_TYPE (EmpathyIndividualMenu, empathy_individual_menu, GTK_TYPE_MENU);
 
 static GtkWidget * empathy_individual_chat_menu_item_new (
-    FolksIndividual *individual);
+    EmpathyIndividualMenu *self, FolksIndividual *individual);
 static GtkWidget * empathy_individual_sms_menu_item_new (
-    FolksIndividual *individual);
+    EmpathyIndividualMenu *self, FolksIndividual *individual);
 static GtkWidget * empathy_individual_log_menu_item_new  (
     FolksIndividual *individual);
 static GtkWidget * empathy_individual_info_menu_item_new (
@@ -85,9 +86,9 @@ static GtkWidget * empathy_individual_invite_menu_item_new (
     FolksIndividual *individual,
     EmpathyContact *contact);
 static GtkWidget * empathy_individual_file_transfer_menu_item_new (
-    FolksIndividual *individual);
+    EmpathyIndividualMenu *self, FolksIndividual *individual);
 static GtkWidget * empathy_individual_share_my_desktop_menu_item_new (
-    FolksIndividual *individual);
+    EmpathyIndividualMenu *self, FolksIndividual *individual);
 static GtkWidget * empathy_individual_favourite_menu_item_new (
     FolksIndividual *individual);
 static GtkWidget * empathy_individual_add_menu_item_new (
@@ -96,10 +97,11 @@ static GtkWidget * empathy_individual_add_menu_item_new (
 static GtkWidget * empathy_individiual_block_menu_item_new (
     FolksIndividual *individual);
 static GtkWidget * empathy_individiual_remove_menu_item_new (
-    FolksIndividual *individual);
+    EmpathyIndividualMenu *self);
 
 static void
-individual_menu_add_personas (GtkMenuShell *menu,
+individual_menu_add_personas (EmpathyIndividualMenu *self,
+    GtkMenuShell *menu,
     FolksIndividual *individual,
     EmpathyIndividualFeatureFlags features)
 {
@@ -107,7 +109,6 @@ individual_menu_add_personas (GtkMenuShell *menu,
   GeeSet *personas;
   GeeIterator *iter;
   guint persona_count = 0;
-  gboolean c;
 
   g_return_if_fail (GTK_IS_MENU (menu));
   g_return_if_fail (FOLKS_IS_INDIVIDUAL (individual));
@@ -137,7 +138,8 @@ individual_menu_add_personas (GtkMenuShell *menu,
   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
   gtk_widget_show (item);
 
-  for (c = gee_iterator_first (iter); c; c = gee_iterator_next (iter))
+  iter = gee_iterable_iterator (GEE_ITERABLE (personas));
+  while (gee_iterator_next (iter))
     {
       GtkWidget *image;
       GtkWidget *contact_item;
@@ -190,7 +192,8 @@ individual_menu_add_personas (GtkMenuShell *menu,
       /* Chat */
       if (features & EMPATHY_INDIVIDUAL_FEATURE_CHAT)
         {
-          action = empathy_individual_chat_menu_item_new (single_individual);
+          action = empathy_individual_chat_menu_item_new (self,
+              single_individual);
           gtk_menu_shell_append (GTK_MENU_SHELL (contact_submenu), action);
           gtk_widget_show (action);
         }
@@ -198,7 +201,8 @@ individual_menu_add_personas (GtkMenuShell *menu,
       /* SMS */
       if (features & EMPATHY_INDIVIDUAL_FEATURE_SMS)
         {
-          action = empathy_individual_sms_menu_item_new (single_individual);
+          action = empathy_individual_sms_menu_item_new (self,
+              single_individual);
           gtk_menu_shell_append (GTK_MENU_SHELL (contact_submenu), action);
           gtk_widget_show (action);
         }
@@ -207,13 +211,13 @@ individual_menu_add_personas (GtkMenuShell *menu,
         {
           /* Audio Call */
           action = empathy_individual_audio_call_menu_item_new (
-              single_individual);
+              self, single_individual);
           gtk_menu_shell_append (GTK_MENU_SHELL (contact_submenu), action);
           gtk_widget_show (action);
 
           /* Video Call */
           action = empathy_individual_video_call_menu_item_new (
-              single_individual);
+              self, single_individual);
           gtk_menu_shell_append (GTK_MENU_SHELL (contact_submenu), action);
           gtk_widget_show (action);
         }
@@ -235,14 +239,14 @@ individual_menu_add_personas (GtkMenuShell *menu,
       if (features & EMPATHY_INDIVIDUAL_FEATURE_FILE_TRANSFER)
         {
           action = empathy_individual_file_transfer_menu_item_new (
-              single_individual);
+              self, single_individual);
           gtk_menu_shell_append (GTK_MENU_SHELL (contact_submenu), action);
           gtk_widget_show (action);
         }
 
       /* Share my desktop */
       action = empathy_individual_share_my_desktop_menu_item_new (
-          single_individual);
+          self, single_individual);
       gtk_menu_shell_append (GTK_MENU_SHELL (contact_submenu), action);
       gtk_widget_show (action);
 
@@ -303,7 +307,7 @@ find_phone_accounts (void)
           TP_CONNECTION_STATUS_CONNECTED)
         continue;
 
-      if (!empathy_account_has_uri_scheme_tel (account))
+      if (!tp_account_associated_with_uri_scheme (account, "tel"))
         continue;
 
       found = g_list_prepend (found, g_object_ref (account));
@@ -454,13 +458,16 @@ add_phone_numbers (EmpathyIndividualMenu *self)
 
       if (type != NULL)
         {
-          tmp = g_strdup_printf ("Call %s (%s)",
+          /* translators: first argument is a phone number like +32123456 and
+           * the second one is something like 'home' or 'work'. */
+          tmp = g_strdup_printf (_("Call %s (%s)"),
               folks_phone_field_details_get_normalised (details),
               type);
         }
       else
         {
-          tmp = g_strdup_printf ("Call %s",
+          /* translators: argument is a phone number like +32123456 */
+          tmp = g_strdup_printf (_("Call %s"),
               folks_phone_field_details_get_normalised (details));
         }
 
@@ -694,13 +701,16 @@ enum
   REMOVE_DIALOG_RESPONSE_CANCEL = 0,
   REMOVE_DIALOG_RESPONSE_DELETE,
   REMOVE_DIALOG_RESPONSE_DELETE_AND_BLOCK,
+  REMOVE_DIALOG_RESPONSE_REMOVE_FROM_GROUP
 };
 
 static int
 remove_dialog_show (const gchar *message,
     const gchar *secondary_text,
+    gboolean show_remove_from_group,
     gboolean block_button,
-    GdkPixbuf *avatar)
+    GdkPixbuf *avatar,
+    const gchar *active_group)
 {
   GtkWidget *dialog;
   gboolean res;
@@ -715,6 +725,23 @@ remove_dialog_show (const gchar *message,
       gtk_widget_show (image);
     }
 
+  if (show_remove_from_group)
+    {
+      GtkWidget *button;
+      gchar *button_text = g_strdup_printf (_("Remove from _Group \'%s\'"),
+          active_group);
+
+      /* gtk_dialog_add_button() doesn't allow us to pass a string with a
+       * mnemonic so we have to create the button manually. */
+      button = gtk_button_new_with_mnemonic (button_text);
+      g_free (button_text);
+
+      gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button,
+          REMOVE_DIALOG_RESPONSE_REMOVE_FROM_GROUP);
+
+      gtk_widget_show (button);
+    }
+
   if (block_button)
     {
       GtkWidget *button;
@@ -744,12 +771,32 @@ remove_dialog_show (const gchar *message,
   return res;
 }
 
+static void
+individual_removed_from_group_cb (GObject *source_object,
+    GAsyncResult *res,
+    gpointer user_data)
+{
+  GError *error = NULL;
+  FolksIndividual *individual = FOLKS_INDIVIDUAL (source_object);
+
+  folks_group_details_change_group_finish (
+      FOLKS_GROUP_DETAILS (individual), res, &error);
+  if (error != NULL)
+    {
+      DEBUG ("Individual could not be removed from group: %s",
+          error->message);
+      g_error_free (error);
+    }
+}
+
 static void
 remove_got_avatar (GObject *source_object,
     GAsyncResult *result,
     gpointer user_data)
 {
   FolksIndividual *individual = FOLKS_INDIVIDUAL (source_object);
+  EmpathyIndividualMenu *self = EMPATHY_INDIVIDUAL_MENU (user_data);
+  EmpathyIndividualMenuPriv *priv = GET_PRIV (self);
   GdkPixbuf *avatar;
   EmpathyIndividualManager *manager;
   gchar *text;
@@ -758,6 +805,8 @@ remove_got_avatar (GObject *source_object,
   gboolean can_block;
   GError *error = NULL;
   gint res;
+  gboolean show_remove_from_group;
+  GeeSet *groups;
 
   avatar = empathy_pixbuf_avatar_from_individual_scaled_finish (individual,
       result, &error);
@@ -771,6 +820,10 @@ remove_got_avatar (GObject *source_object,
   /* We couldn't retrieve the avatar, but that isn't a fatal error,
    * so we still display the remove dialog. */
 
+  groups = folks_group_details_get_groups (FOLKS_GROUP_DETAILS (individual));
+  show_remove_from_group =
+      gee_collection_get_size (GEE_COLLECTION (groups)) > 1;
+
   personas = folks_individual_get_personas (individual);
 
   persona_count = gee_collection_get_size (GEE_COLLECTION (personas));
@@ -804,7 +857,15 @@ remove_got_avatar (GObject *source_object,
   manager = empathy_individual_manager_dup_singleton ();
   can_block = empathy_individual_manager_supports_blocking (manager,
       individual);
-  res = remove_dialog_show (_("Removing contact"), text, can_block, avatar);
+  res = remove_dialog_show (_("Removing contact"), text,
+      show_remove_from_group, can_block, avatar, priv->active_group);
+
+  if (res == REMOVE_DIALOG_RESPONSE_REMOVE_FROM_GROUP)
+    {
+      folks_group_details_change_group (FOLKS_GROUP_DETAILS (individual),
+          priv->active_group, false, individual_removed_from_group_cb, NULL);
+      goto finally;
+    }
 
   if (res == REMOVE_DIALOG_RESPONSE_DELETE ||
       res == REMOVE_DIALOG_RESPONSE_DELETE_AND_BLOCK)
@@ -827,29 +888,33 @@ remove_got_avatar (GObject *source_object,
  finally:
   g_free (text);
   g_object_unref (manager);
+  g_object_unref (self);
 }
 
 static void
 remove_activate_cb (GtkMenuItem *menuitem,
-    FolksIndividual *individual)
+    EmpathyIndividualMenu *self)
 {
-  empathy_pixbuf_avatar_from_individual_scaled_async (individual,
-      48, 48, NULL, remove_got_avatar, NULL);
+  EmpathyIndividualMenuPriv *priv = GET_PRIV (self);
+
+  empathy_pixbuf_avatar_from_individual_scaled_async (priv->individual,
+      48, 48, NULL, remove_got_avatar, g_object_ref (self));
 }
 
 static GtkWidget *
-empathy_individiual_remove_menu_item_new (FolksIndividual *individual)
+empathy_individiual_remove_menu_item_new (EmpathyIndividualMenu *self)
 {
   GeeSet *personas;
   GeeIterator *iter;
   gboolean can_remove = FALSE;
   GtkWidget *item, *image;
+  EmpathyIndividualMenuPriv *priv = GET_PRIV (self);
 
   /* If any of the Individual's personas can be removed, add an option to
    * remove. This will act as a best-effort option. If any Personas cannot be
    * removed from the server, then this option will just be inactive upon
    * subsequent menu openings */
-  personas = folks_individual_get_personas (individual);
+  personas = folks_individual_get_personas (priv->individual);
   iter = gee_iterable_iterator (GEE_ITERABLE (personas));
   while (!can_remove && gee_iterator_next (iter))
     {
@@ -874,7 +939,7 @@ empathy_individiual_remove_menu_item_new (FolksIndividual *individual)
   gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
 
   g_signal_connect (item, "activate",
-      G_CALLBACK (remove_activate_cb), individual);
+      G_CALLBACK (remove_activate_cb), self);
 
   return item;
 }
@@ -882,7 +947,7 @@ empathy_individiual_remove_menu_item_new (FolksIndividual *individual)
 static void
 constructed (GObject *object)
 {
-  EmpathyIndividualMenu *self = (EmpathyIndividualMenu *) object;
+  EmpathyIndividualMenu *self = EMPATHY_INDIVIDUAL_MENU (object);
   EmpathyIndividualMenuPriv *priv = GET_PRIV (object);
   GtkMenuShell *shell;
   GtkWidget *item;
@@ -908,7 +973,7 @@ constructed (GObject *object)
   /* Chat */
   if (features & EMPATHY_INDIVIDUAL_FEATURE_CHAT)
     {
-      item = empathy_individual_chat_menu_item_new (individual);
+      item = empathy_individual_chat_menu_item_new (self, individual);
       if (item != NULL)
         {
           gtk_menu_shell_append (shell, item);
@@ -919,7 +984,7 @@ constructed (GObject *object)
   /* SMS */
   if (features & EMPATHY_INDIVIDUAL_FEATURE_SMS)
     {
-      item = empathy_individual_sms_menu_item_new (individual);
+      item = empathy_individual_sms_menu_item_new (self, individual);
       if (item != NULL)
         {
           gtk_menu_shell_append (shell, item);
@@ -930,12 +995,12 @@ constructed (GObject *object)
   if (features & EMPATHY_INDIVIDUAL_FEATURE_CALL)
     {
       /* Audio Call */
-      item = empathy_individual_audio_call_menu_item_new (individual);
+      item = empathy_individual_audio_call_menu_item_new (self, individual);
       gtk_menu_shell_append (shell, item);
       gtk_widget_show (item);
 
       /* Video Call */
-      item = empathy_individual_video_call_menu_item_new (individual);
+      item = empathy_individual_video_call_menu_item_new (self, individual);
       gtk_menu_shell_append (shell, item);
       gtk_widget_show (item);
     }
@@ -951,7 +1016,7 @@ constructed (GObject *object)
   /* File transfer */
   if (features & EMPATHY_INDIVIDUAL_FEATURE_FILE_TRANSFER)
     {
-      item = empathy_individual_file_transfer_menu_item_new (individual);
+      item = empathy_individual_file_transfer_menu_item_new (self, individual);
       gtk_menu_shell_append (shell, item);
       gtk_widget_show (item);
     }
@@ -959,12 +1024,13 @@ constructed (GObject *object)
   /* Share my desktop */
   /* FIXME we should add the "Share my desktop" menu item if Vino is
   a registered handler in MC5 */
-  item = empathy_individual_share_my_desktop_menu_item_new (individual);
+  item = empathy_individual_share_my_desktop_menu_item_new (self, individual);
   gtk_menu_shell_append (shell, item);
   gtk_widget_show (item);
 
   /* Menu items to target specific contacts */
-  individual_menu_add_personas (GTK_MENU_SHELL (object), individual, features);
+  individual_menu_add_personas (self, GTK_MENU_SHELL (object),
+      individual, features);
 
   /* Separator */
   if (features & (EMPATHY_INDIVIDUAL_FEATURE_EDIT |
@@ -1023,7 +1089,7 @@ constructed (GObject *object)
 
   /* Separator & Remove */
   if (features & EMPATHY_INDIVIDUAL_FEATURE_REMOVE &&
-      (item = empathy_individiual_remove_menu_item_new (individual)) != NULL) {
+      (item = empathy_individiual_remove_menu_item_new (self)) != NULL) {
     GtkWidget *sep;
 
     sep = gtk_separator_menu_item_new ();
@@ -1047,6 +1113,9 @@ get_property (GObject *object,
 
   switch (param_id)
     {
+      case PROP_ACTIVE_GROUP:
+        g_value_set_string (value, priv->active_group);
+        break;
       case PROP_INDIVIDUAL:
         g_value_set_object (value, priv->individual);
         break;
@@ -1074,6 +1143,10 @@ set_property (GObject *object,
 
   switch (param_id)
     {
+      case PROP_ACTIVE_GROUP:
+        g_assert (priv->active_group == NULL); /* construct only */
+        priv->active_group = g_value_dup_string (value);
+        break;
       case PROP_INDIVIDUAL:
         priv->individual = g_value_dup_object (value);
         break;
@@ -1100,6 +1173,16 @@ dispose (GObject *object)
   G_OBJECT_CLASS (empathy_individual_menu_parent_class)->dispose (object);
 }
 
+static void
+finalize (GObject *object)
+{
+  EmpathyIndividualMenuPriv *priv = GET_PRIV (object);
+
+  g_free (priv->active_group);
+
+  G_OBJECT_CLASS (empathy_individual_menu_parent_class)->finalize (object);
+}
+
 static void
 empathy_individual_menu_class_init (EmpathyIndividualMenuClass *klass)
 {
@@ -1109,6 +1192,19 @@ empathy_individual_menu_class_init (EmpathyIndividualMenuClass *klass)
   object_class->get_property = get_property;
   object_class->set_property = set_property;
   object_class->dispose = dispose;
+  object_class->finalize = finalize;
+
+  /**
+   * gchar *:active-group:
+   *
+   * The group the selected roster-contact widget belongs, or NULL.
+   */
+  g_object_class_install_property (object_class, PROP_ACTIVE_GROUP,
+      g_param_spec_string ("active-group",
+          "Active group",
+          "The group the selected roster-contact widget belongs, or NULL",
+          NULL,
+          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
 
   /**
    * EmpathyIndividualMenu:individual:
@@ -1142,11 +1238,22 @@ empathy_individual_menu_class_init (EmpathyIndividualMenuClass *klass)
           EMPATHY_TYPE_INDIVIDUAL_STORE,
           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
 
+  signals[MENU_ITEM_ACTIVATED] =
+      g_signal_new ("menu-item-activated",
+          G_TYPE_FROM_CLASS (klass),
+          G_SIGNAL_RUN_LAST,
+          0,
+          NULL, NULL,
+          g_cclosure_marshal_generic,
+          G_TYPE_NONE,
+          0);
+
   g_type_class_add_private (object_class, sizeof (EmpathyIndividualMenuPriv));
 }
 
 GtkWidget *
 empathy_individual_menu_new (FolksIndividual *individual,
+    const gchar *active_group,
     EmpathyIndividualFeatureFlags features,
     EmpathyIndividualStore *store)
 {
@@ -1156,6 +1263,7 @@ empathy_individual_menu_new (FolksIndividual *individual,
   g_return_val_if_fail (features != EMPATHY_INDIVIDUAL_FEATURE_NONE, NULL);
 
   return g_object_new (EMPATHY_TYPE_INDIVIDUAL_MENU,
+      "active-group", active_group,
       "individual", individual,
       "features", features,
       "store", store,
@@ -1213,6 +1321,16 @@ menu_item_set_first_contact (GtkWidget *item,
   return item;
 }
 
+static void
+emit_menu_item_activated (GtkMenuItem *item)
+{
+  EmpathyIndividualMenu *self;
+
+  self = EMPATHY_INDIVIDUAL_MENU (g_object_get_data (G_OBJECT (item),
+      "individual-menu"));
+  g_signal_emit (self, signals [MENU_ITEM_ACTIVATED], 0);
+}
+
 static void
 empathy_individual_chat_menu_item_activated (GtkMenuItem *item,
   EmpathyContact *contact)
@@ -1220,10 +1338,13 @@ empathy_individual_chat_menu_item_activated (GtkMenuItem *item,
   g_return_if_fail (EMPATHY_IS_CONTACT (contact));
 
   empathy_chat_with_contact (contact, empathy_get_current_action_time ());
+
+  emit_menu_item_activated (item);
 }
 
 static GtkWidget *
-empathy_individual_chat_menu_item_new (FolksIndividual *individual)
+empathy_individual_chat_menu_item_new (EmpathyIndividualMenu *self,
+    FolksIndividual *individual)
 {
   GtkWidget *item;
   GtkWidget *image;
@@ -1237,6 +1358,7 @@ empathy_individual_chat_menu_item_new (FolksIndividual *individual)
   gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
   gtk_widget_show (image);
 
+  g_object_set_data (G_OBJECT (item), "individual-menu", self);
   menu_item_set_first_contact (item, individual,
       G_CALLBACK (empathy_individual_chat_menu_item_activated),
       EMPATHY_ACTION_CHAT);
@@ -1255,10 +1377,13 @@ empathy_individual_sms_menu_item_activated (GtkMenuItem *item,
       empathy_contact_get_id (contact),
       empathy_get_current_action_time (),
       NULL, NULL);
+
+  emit_menu_item_activated (item);
 }
 
 static GtkWidget *
-empathy_individual_sms_menu_item_new (FolksIndividual *individual)
+empathy_individual_sms_menu_item_new (EmpathyIndividualMenu *self,
+    FolksIndividual *individual)
 {
   GtkWidget *item;
   GtkWidget *image;
@@ -1272,6 +1397,7 @@ empathy_individual_sms_menu_item_new (FolksIndividual *individual)
   gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
   gtk_widget_show (image);
 
+  g_object_set_data (G_OBJECT (item), "individual-menu", self);
   menu_item_set_first_contact (item, individual,
       G_CALLBACK (empathy_individual_sms_menu_item_activated),
       EMPATHY_ACTION_SMS);
@@ -1289,10 +1415,13 @@ empathy_individual_audio_call_menu_item_activated (GtkMenuItem *item,
       empathy_contact_get_account (contact),
       TRUE, FALSE,
       empathy_get_current_action_time ());
+
+  emit_menu_item_activated (item);
 }
 
 GtkWidget *
-empathy_individual_audio_call_menu_item_new (FolksIndividual *individual)
+empathy_individual_audio_call_menu_item_new (EmpathyIndividualMenu *self,
+    FolksIndividual *individual)
 {
   GtkWidget *item;
   GtkWidget *image;
@@ -1304,6 +1433,7 @@ empathy_individual_audio_call_menu_item_new (FolksIndividual *individual)
   gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
   gtk_widget_show (image);
 
+  g_object_set_data (G_OBJECT (item), "individual-menu", self);
   menu_item_set_first_contact (item, individual,
       G_CALLBACK (empathy_individual_audio_call_menu_item_activated),
       EMPATHY_ACTION_AUDIO_CALL);
@@ -1321,14 +1451,17 @@ empathy_individual_video_call_menu_item_activated (GtkMenuItem *item,
       empathy_contact_get_account (contact),
       TRUE, TRUE,
       empathy_get_current_action_time ());
+
+  emit_menu_item_activated (item);
 }
 
 GtkWidget *
-empathy_individual_video_call_menu_item_new (FolksIndividual *individual)
+empathy_individual_video_call_menu_item_new (EmpathyIndividualMenu *self,
+    FolksIndividual *individual)
 {
   GtkWidget *item;
   GtkWidget *image;
-  EmpathyCameraMonitor *monitor;
+  TpawCameraMonitor *monitor;
 
   g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL);
 
@@ -1338,6 +1471,7 @@ empathy_individual_video_call_menu_item_new (FolksIndividual *individual)
   gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
   gtk_widget_show (image);
 
+  g_object_set_data (G_OBJECT (item), "individual-menu", self);
   menu_item_set_first_contact (item, individual,
       G_CALLBACK (empathy_individual_video_call_menu_item_activated),
       EMPATHY_ACTION_VIDEO_CALL);
@@ -1345,7 +1479,7 @@ empathy_individual_video_call_menu_item_new (FolksIndividual *individual)
   /* Only follow available cameras if the contact can do Video calls */
   if (gtk_widget_get_sensitive (item))
     {
-      monitor = empathy_camera_monitor_dup_singleton ();
+      monitor = tpaw_camera_monitor_dup_singleton ();
       g_object_set_data_full (G_OBJECT (item),
           "monitor", monitor, g_object_unref);
       g_object_bind_property (monitor, "available", item, "sensitive",
@@ -1392,10 +1526,13 @@ empathy_individual_file_transfer_menu_item_activated (GtkMenuItem *item,
   g_return_if_fail (EMPATHY_IS_CONTACT (contact));
 
   empathy_send_file_with_file_chooser (contact);
+
+  emit_menu_item_activated (item);
 }
 
 static GtkWidget *
-empathy_individual_file_transfer_menu_item_new (FolksIndividual *individual)
+empathy_individual_file_transfer_menu_item_new (EmpathyIndividualMenu *self,
+    FolksIndividual *individual)
 {
   GtkWidget *item;
   GtkWidget *image;
@@ -1408,6 +1545,7 @@ empathy_individual_file_transfer_menu_item_new (FolksIndividual *individual)
   gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
   gtk_widget_show (image);
 
+  g_object_set_data (G_OBJECT (item), "individual-menu", self);
   menu_item_set_first_contact (item, individual,
       G_CALLBACK (empathy_individual_file_transfer_menu_item_activated),
       EMPATHY_ACTION_SEND_FILE);
@@ -1422,10 +1560,13 @@ empathy_individual_share_my_desktop_menu_item_activated (GtkMenuItem *item,
   g_return_if_fail (EMPATHY_IS_CONTACT (contact));
 
   empathy_share_my_desktop_share_with_contact (contact);
+
+  emit_menu_item_activated (item);
 }
 
 static GtkWidget *
-empathy_individual_share_my_desktop_menu_item_new (FolksIndividual *individual)
+empathy_individual_share_my_desktop_menu_item_new (EmpathyIndividualMenu *self,
+    FolksIndividual *individual)
 {
   GtkWidget *item;
   GtkWidget *image;
@@ -1437,6 +1578,7 @@ empathy_individual_share_my_desktop_menu_item_new (FolksIndividual *individual)
   gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
   gtk_widget_show (image);
 
+  g_object_set_data (G_OBJECT (item), "individual-menu", self);
   menu_item_set_first_contact (item, individual,
       G_CALLBACK (empathy_individual_share_my_desktop_menu_item_activated),
       EMPATHY_ACTION_SHARE_MY_DESKTOP);