[empathy] Re-implement the context menu for Individuals



commit c75319eb432d4d815bf07ee30396f958b021abed
Author: Travis Reitter <treitter gmail com>
Date:   Tue Jun 15 18:29:03 2010 -0700

    Re-implement the context menu for Individuals

 libempathy-gtk/Makefile.am                |    1 +
 libempathy-gtk/empathy-individual-menu.c  |  769 +++++++++++++++++++++++++++++
 libempathy-gtk/empathy-individual-menu.h  |   20 +
 libempathy-gtk/empathy-individual-store.c |   41 +-
 libempathy-gtk/empathy-individual-view.c  |   22 +-
 libempathy/empathy-individual-manager.c   |   30 ++
 libempathy/empathy-individual-manager.h   |    6 +
 libempathy/empathy-utils.c                |   24 +
 libempathy/empathy-utils.h                |    1 +
 src/empathy-main-window.c                 |    3 +
 10 files changed, 881 insertions(+), 36 deletions(-)
---
diff --git a/libempathy-gtk/Makefile.am b/libempathy-gtk/Makefile.am
index 6959578..eb32ccd 100644
--- a/libempathy-gtk/Makefile.am
+++ b/libempathy-gtk/Makefile.am
@@ -52,6 +52,7 @@ libempathy_gtk_handwritten_source =            	\
 	empathy-contact-selector-dialog.c \
 	empathy-contact-widget.c		\
 	empathy-geometry.c			\
+	empathy-individual-menu.c		\
 	empathy-individual-store.c		\
 	empathy-individual-view.c		\
 	empathy-irc-network-dialog.c		\
diff --git a/libempathy-gtk/empathy-individual-menu.c b/libempathy-gtk/empathy-individual-menu.c
new file mode 100644
index 0000000..a849e7e
--- /dev/null
+++ b/libempathy-gtk/empathy-individual-menu.c
@@ -0,0 +1,769 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008-2010 Collabora 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.1 of the License, 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Authors: Xavier Claessens <xclaesse gmail com>
+ *          Travis Reitter <travis reitter collabora co uk>
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <glib/gi18n-lib.h>
+#include <gtk/gtk.h>
+#include <telepathy-glib/util.h>
+#ifdef ENABLE_TPL
+#include <telepathy-logger/log-manager.h>
+#else
+
+#include <libempathy/empathy-log-manager.h>
+#endif /* ENABLE_TPL */
+#include <libempathy/empathy-call-factory.h>
+#include <libempathy/empathy-dispatcher.h>
+#include <libempathy/empathy-contact-manager.h>
+#include <libempathy/empathy-individual-manager.h>
+#include <libempathy/empathy-chatroom-manager.h>
+#include <libempathy/empathy-utils.h>
+
+#include "empathy-individual-menu.h"
+#include "empathy-images.h"
+#include "empathy-log-window.h"
+#include "empathy-contact-dialogs.h"
+#include "empathy-ui-utils.h"
+#include "empathy-share-my-desktop.h"
+
+GtkWidget *
+empathy_individual_menu_new (FolksIndividual *individual,
+    EmpathyIndividualFeatureFlags features)
+{
+  GtkWidget *menu;
+  GtkMenuShell *shell;
+  GtkWidget *item;
+
+  g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL);
+
+  if (features == EMPATHY_INDIVIDUAL_FEATURE_NONE)
+    return NULL;
+
+  menu = gtk_menu_new ();
+  shell = GTK_MENU_SHELL (menu);
+
+  /* Add Contact */
+  item = empathy_individual_add_menu_item_new (individual);
+  if (item)
+    {
+      gtk_menu_shell_append (shell, item);
+      gtk_widget_show (item);
+    }
+
+  /* Chat */
+  if (features & EMPATHY_INDIVIDUAL_FEATURE_CHAT)
+    {
+      item = empathy_individual_chat_menu_item_new (individual);
+      if (item != NULL)
+        {
+          gtk_menu_shell_append (shell, item);
+          gtk_widget_show (item);
+        }
+    }
+
+  if (features & EMPATHY_INDIVIDUAL_FEATURE_CALL)
+    {
+      /* Audio Call */
+      item = empathy_individual_audio_call_menu_item_new (individual);
+      gtk_menu_shell_append (shell, item);
+      gtk_widget_show (item);
+
+      /* Video Call */
+      item = empathy_individual_video_call_menu_item_new (individual);
+      gtk_menu_shell_append (shell, item);
+      gtk_widget_show (item);
+    }
+
+  /* Log */
+  if (features & EMPATHY_INDIVIDUAL_FEATURE_LOG)
+    {
+      item = empathy_individual_log_menu_item_new (individual);
+      gtk_menu_shell_append (shell, item);
+      gtk_widget_show (item);
+    }
+
+  /* Invite */
+  item = empathy_individual_invite_menu_item_new (individual);
+  gtk_menu_shell_append (shell, item);
+  gtk_widget_show (item);
+
+  /* File transfer */
+  item = empathy_individual_file_transfer_menu_item_new (individual);
+  gtk_menu_shell_append (shell, item);
+  gtk_widget_show (item);
+
+  /* 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);
+  gtk_menu_shell_append (shell, item);
+  gtk_widget_show (item);
+
+  /* Separator */
+  if (features & (EMPATHY_INDIVIDUAL_FEATURE_EDIT |
+      EMPATHY_INDIVIDUAL_FEATURE_INFO |
+      EMPATHY_INDIVIDUAL_FEATURE_FAVOURITE))
+    {
+      item = gtk_separator_menu_item_new ();
+      gtk_menu_shell_append (shell, item);
+      gtk_widget_show (item);
+    }
+
+  /* Edit */
+  if (features & EMPATHY_INDIVIDUAL_FEATURE_EDIT)
+    {
+      item = empathy_individual_edit_menu_item_new (individual);
+      gtk_menu_shell_append (shell, item);
+      gtk_widget_show (item);
+    }
+
+  /* Info */
+  if (features & EMPATHY_INDIVIDUAL_FEATURE_INFO)
+    {
+      item = empathy_individual_info_menu_item_new (individual);
+      gtk_menu_shell_append (shell, item);
+      gtk_widget_show (item);
+    }
+
+#if HAVE_FAVOURITE_CONTACTS
+  /* Favorite checkbox */
+  if (features & EMPATHY_INDIVIDUAL_FEATURE_FAVOURITE)
+    {
+      item = empathy_individual_favourite_menu_item_new (individual);
+      gtk_menu_shell_append (shell, item);
+      gtk_widget_show (item);
+    }
+#endif
+
+  return menu;
+}
+
+static void
+empathy_individual_add_menu_item_activated (GtkMenuItem *item,
+  FolksIndividual *individual)
+{
+  GtkWidget *toplevel;
+  EmpathyContact *contact;
+
+  toplevel = gtk_widget_get_toplevel (GTK_WIDGET (item));
+  if (!gtk_widget_is_toplevel (toplevel) || !GTK_IS_WINDOW (toplevel))
+    toplevel = NULL;
+
+  contact = empathy_contact_from_folks_individual (individual);
+  empathy_new_contact_dialog_show_with_contact (GTK_WINDOW (toplevel),
+      contact);
+
+  if (contact != NULL)
+    g_object_unref (contact);
+}
+
+GtkWidget *
+empathy_individual_add_menu_item_new (FolksIndividual *individual)
+{
+  GtkWidget *item;
+  GtkWidget *image;
+  EmpathyIndividualManager *manager;
+  EmpathyContact *contact = NULL;
+  TpConnection *connection;
+  GList *l, *members;
+  gboolean found = FALSE;
+  EmpathyIndividualManagerFlags flags;
+
+  g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL);
+
+  if (!empathy_individual_manager_initialized ())
+    {
+      item = NULL;
+      goto out;
+    }
+
+  manager = empathy_individual_manager_dup_singleton ();
+  contact = empathy_contact_from_folks_individual (individual);
+  connection = empathy_contact_get_connection (contact);
+
+  flags = empathy_individual_manager_get_flags_for_connection (manager,
+      connection);
+
+  if (!(flags & EMPATHY_INDIVIDUAL_MANAGER_CAN_ADD))
+    {
+      item = NULL;
+      goto out;
+    }
+
+  members = empathy_individual_manager_get_members (
+      EMPATHY_INDIVIDUAL_MANAGER (manager));
+
+  for (l = members; l && !found; l = l->next)
+    {
+      if (!tp_strdiff (folks_individual_get_id (l->data),
+              folks_individual_get_id (individual)))
+        {
+          found = TRUE;
+        }
+    }
+  g_list_free (members);
+  g_object_unref (manager);
+
+  if (found)
+    {
+      item = NULL;
+      goto out;
+    }
+
+  item = gtk_image_menu_item_new_with_mnemonic (_("_Add Contactâ?¦"));
+  image = gtk_image_new_from_icon_name (GTK_STOCK_ADD, GTK_ICON_SIZE_MENU);
+  gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
+
+  g_signal_connect (item, "activate",
+      G_CALLBACK (empathy_individual_add_menu_item_activated),
+      individual);
+
+out:
+  if (contact != NULL)
+    g_object_unref (contact);
+
+  return item;
+}
+
+static void
+empathy_individual_chat_menu_item_activated (GtkMenuItem *item,
+  FolksIndividual *individual)
+{
+  EmpathyContact *contact;
+
+  contact = empathy_contact_from_folks_individual (individual);
+
+  g_return_if_fail (EMPATHY_IS_CONTACT (contact));
+
+  empathy_dispatcher_chat_with_contact (contact, gtk_get_current_event_time (),
+      NULL, NULL);
+
+  g_object_unref (contact);
+}
+
+GtkWidget *
+empathy_individual_chat_menu_item_new (FolksIndividual *individual)
+{
+  GtkWidget *item;
+  GtkWidget *image;
+
+  g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL);
+  g_return_val_if_fail (empathy_folks_individual_contains_contact (individual),
+      NULL);
+
+  item = gtk_image_menu_item_new_with_mnemonic (_("_Chat"));
+  image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_MESSAGE,
+      GTK_ICON_SIZE_MENU);
+  gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
+  gtk_widget_show (image);
+
+  g_signal_connect (item, "activate",
+      G_CALLBACK (empathy_individual_chat_menu_item_activated), individual);
+
+  return item;
+}
+
+static void
+empathy_individual_audio_call_menu_item_activated (GtkMenuItem *item,
+  FolksIndividual *individual)
+{
+  EmpathyContact *contact;
+  EmpathyCallFactory *factory;
+
+  contact = empathy_contact_from_folks_individual (individual);
+
+  g_return_if_fail (EMPATHY_IS_CONTACT (contact));
+
+  factory = empathy_call_factory_get ();
+  empathy_call_factory_new_call_with_streams (factory, contact, TRUE, FALSE);
+  g_object_unref (contact);
+}
+
+GtkWidget *
+empathy_individual_audio_call_menu_item_new (FolksIndividual *individual)
+{
+  GtkWidget *item;
+  GtkWidget *image;
+  EmpathyContact *contact;
+
+  g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL);
+
+  contact = empathy_contact_from_folks_individual (individual);
+
+  g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
+
+  item = gtk_image_menu_item_new_with_mnemonic (C_("menu item", "_Audio Call"));
+  image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_VOIP, GTK_ICON_SIZE_MENU);
+  gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
+  gtk_widget_set_sensitive (item, empathy_contact_can_voip_audio (contact));
+  gtk_widget_show (image);
+
+  g_signal_connect (item, "activate",
+      G_CALLBACK (empathy_individual_audio_call_menu_item_activated),
+      individual);
+
+  g_object_unref (contact);
+
+  return item;
+}
+
+static void
+empathy_individual_video_call_menu_item_activated (GtkMenuItem *item,
+  FolksIndividual *individual)
+{
+  EmpathyContact *contact;
+  EmpathyCallFactory *factory;
+
+  contact = empathy_contact_from_folks_individual (individual);
+
+  g_return_if_fail (EMPATHY_IS_CONTACT (contact));
+
+  factory = empathy_call_factory_get ();
+  empathy_call_factory_new_call_with_streams (factory, contact, TRUE, TRUE);
+  g_object_unref (contact);
+}
+
+GtkWidget *
+empathy_individual_video_call_menu_item_new (FolksIndividual *individual)
+{
+  GtkWidget *item;
+  GtkWidget *image;
+  EmpathyContact *contact;
+
+  g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL);
+
+  contact = empathy_contact_from_folks_individual (individual);
+
+  g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
+
+  item = gtk_image_menu_item_new_with_mnemonic (C_("menu item", "_Video Call"));
+  image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_VIDEO_CALL,
+      GTK_ICON_SIZE_MENU);
+  gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
+  gtk_widget_set_sensitive (item, empathy_contact_can_voip_video (contact));
+  gtk_widget_show (image);
+
+  g_signal_connect (item, "activate",
+      G_CALLBACK (empathy_individual_video_call_menu_item_activated),
+      individual);
+
+  g_object_unref (contact);
+
+  return item;
+}
+
+static void
+individual_log_menu_item_activate_cb (FolksIndividual *individual)
+{
+  EmpathyContact *contact;
+
+  contact = empathy_contact_from_folks_individual (individual);
+
+  g_return_if_fail (EMPATHY_IS_CONTACT (contact));
+
+  empathy_log_window_show (empathy_contact_get_account (contact),
+      empathy_contact_get_id (contact), FALSE, NULL);
+}
+
+GtkWidget *
+empathy_individual_log_menu_item_new (FolksIndividual *individual)
+{
+#ifndef ENABLE_TPL
+  EmpathyLogManager *manager;
+#else
+  TplLogManager *manager;
+#endif /* ENABLE_TPL */
+  gboolean have_log;
+  GtkWidget *item;
+  GtkWidget *image;
+  EmpathyContact *contact;
+
+  g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL);
+
+  contact = empathy_contact_from_folks_individual (individual);
+
+  g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
+
+#ifndef ENABLE_TPL
+  manager = empathy_log_manager_dup_singleton ();
+  have_log = empathy_log_manager_exists (manager,
+      empathy_contact_get_account (contact), empathy_contact_get_id (contact),
+      FALSE);
+#else
+  manager = tpl_log_manager_dup_singleton ();
+  have_log = tpl_log_manager_exists (manager,
+      empathy_contact_get_account (contact), empathy_contact_get_id (contact),
+      FALSE);
+#endif /* ENABLE_TPL */
+  g_object_unref (manager);
+
+  item = gtk_image_menu_item_new_with_mnemonic (_("_Previous Conversations"));
+  image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_LOG, GTK_ICON_SIZE_MENU);
+  gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
+  gtk_widget_set_sensitive (item, have_log);
+  gtk_widget_show (image);
+
+  g_signal_connect_swapped (item, "activate",
+      G_CALLBACK (individual_log_menu_item_activate_cb), individual);
+
+  g_object_unref (contact);
+
+  return item;
+}
+
+static void
+individual_file_transfer_menu_item_activate_cb (FolksIndividual *individual)
+{
+  EmpathyContact *contact;
+
+  contact = empathy_contact_from_folks_individual (individual);
+
+  g_return_if_fail (EMPATHY_IS_CONTACT (contact));
+
+  empathy_send_file_with_file_chooser (contact);
+
+  g_object_unref (contact);
+}
+
+GtkWidget *
+empathy_individual_file_transfer_menu_item_new (FolksIndividual *individual)
+{
+  GtkWidget *item;
+  GtkWidget *image;
+  EmpathyContact *contact;
+
+  g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL);
+
+  contact = empathy_contact_from_folks_individual (individual);
+
+  g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
+
+  item = gtk_image_menu_item_new_with_mnemonic (_("Send File"));
+  image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_DOCUMENT_SEND,
+                GTK_ICON_SIZE_MENU);
+  gtk_widget_set_sensitive (item, empathy_contact_can_send_files (contact));
+  gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
+  gtk_widget_show (image);
+
+  g_signal_connect_swapped (item, "activate",
+      G_CALLBACK (individual_file_transfer_menu_item_activate_cb), individual);
+
+  g_object_unref (contact);
+
+  return item;
+}
+
+static void
+individual_share_my_desktop_menu_item_activate_cb (FolksIndividual *individual)
+{
+  EmpathyContact *contact;
+
+  contact = empathy_contact_from_folks_individual (individual);
+
+  g_return_if_fail (EMPATHY_IS_CONTACT (contact));
+
+  empathy_share_my_desktop_share_with_contact (contact);
+
+  g_object_unref (contact);
+}
+
+/* FIXME  we should check if the individual supports vnc stream tube */
+GtkWidget *
+empathy_individual_share_my_desktop_menu_item_new (FolksIndividual *individual)
+{
+  GtkWidget *item;
+  GtkWidget *image;
+  EmpathyContact *contact;
+
+  g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL);
+
+  contact = empathy_contact_from_folks_individual (individual);
+
+  g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
+
+  item = gtk_image_menu_item_new_with_mnemonic (_("Share My Desktop"));
+  image = gtk_image_new_from_icon_name (GTK_STOCK_NETWORK, GTK_ICON_SIZE_MENU);
+  gtk_widget_set_sensitive (item,
+      empathy_contact_can_use_stream_tube (contact));
+  gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
+  gtk_widget_show (image);
+
+  g_signal_connect_swapped (item, "activate",
+      G_CALLBACK (individual_share_my_desktop_menu_item_activate_cb),
+      individual);
+
+  g_object_unref (contact);
+
+  return item;
+}
+
+#if HAVE_FAVOURITE_CONTACTS
+static void
+favourite_menu_item_toggled_cb (GtkCheckMenuItem *item,
+  FolksIndividual *individual)
+{
+  EmpathyIndividualManager *manager;
+  FolksIndividualList *list;
+
+  manager = empathy_individual_manager_dup_singleton ();
+  list = EMPATHY_INDIVIDUAL_MANAGER (manager);
+
+  if (gtk_check_menu_item_get_active (item))
+    empathy_individual_manager_add_to_favourites (list, individual);
+  else
+    empathy_individual_manager_remove_from_favourites (list, individual);
+
+  g_object_unref (manager);
+}
+
+GtkWidget *
+empathy_individual_favourite_menu_item_new (FolksIndividual *individual)
+{
+  GtkWidget *item;
+  EmpathyIndividualManager *manager;
+
+  item = gtk_check_menu_item_new_with_label (_("Favorite"));
+
+  manager = empathy_individual_manager_dup_singleton ();
+  gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item),
+      empathy_individual_manager_is_favourite (
+          EMPATHY_INDIVIDUAL_MANAGER (manager), individual));
+
+  g_signal_connect (item, "toggled",
+      G_CALLBACK (favourite_menu_item_toggled_cb), individual);
+
+  g_object_unref (manager);
+  return item;
+}
+#endif
+
+static void
+individual_info_menu_item_activate_cb (FolksIndividual *individual)
+{
+  EmpathyContact *contact;
+
+  contact = empathy_contact_from_folks_individual (individual);
+  empathy_contact_information_dialog_show (contact, NULL);
+}
+
+GtkWidget *
+empathy_individual_info_menu_item_new (FolksIndividual *individual)
+{
+  GtkWidget *item;
+  GtkWidget *image;
+
+  g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL);
+  g_return_val_if_fail (empathy_folks_individual_contains_contact (individual),
+      NULL);
+
+  item = gtk_image_menu_item_new_with_mnemonic (_("Infor_mation"));
+  image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_CONTACT_INFORMATION,
+                GTK_ICON_SIZE_MENU);
+  gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
+  gtk_widget_show (image);
+
+  g_signal_connect_swapped (item, "activate",
+          G_CALLBACK (individual_info_menu_item_activate_cb),
+          individual);
+
+  return item;
+}
+
+static void
+individual_edit_menu_item_activate_cb (FolksIndividual *individual)
+{
+  EmpathyContact *contact;
+
+  contact = empathy_contact_from_folks_individual (individual);
+  empathy_contact_edit_dialog_show (contact, NULL);
+}
+
+GtkWidget *
+empathy_individual_edit_menu_item_new (FolksIndividual *individual)
+{
+  EmpathyIndividualManager *manager;
+  GtkWidget *item;
+  GtkWidget *image;
+  gboolean enable = FALSE;
+  EmpathyContact *contact;
+
+  g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL);
+
+  contact = empathy_contact_from_folks_individual (individual);
+
+  g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
+
+  if (empathy_individual_manager_initialized ())
+    {
+      TpConnection *connection;
+      EmpathyIndividualManagerFlags flags;
+
+      manager = empathy_individual_manager_dup_singleton ();
+      connection = empathy_contact_get_connection (contact);
+      flags = empathy_individual_manager_get_flags_for_connection (
+          manager, connection);
+
+      enable = (flags & EMPATHY_INDIVIDUAL_MANAGER_CAN_ALIAS ||
+                flags & EMPATHY_INDIVIDUAL_MANAGER_CAN_GROUP);
+
+      g_object_unref (manager);
+    }
+
+  item = gtk_image_menu_item_new_with_mnemonic (
+      C_("Edit individual (contextual menu)", "_Edit"));
+  image = gtk_image_new_from_icon_name (GTK_STOCK_EDIT, GTK_ICON_SIZE_MENU);
+  gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
+  gtk_widget_show (image);
+
+  gtk_widget_set_sensitive (item, enable);
+
+  g_signal_connect_swapped (item, "activate",
+      G_CALLBACK (individual_edit_menu_item_activate_cb), individual);
+
+  g_object_unref (contact);
+
+  return item;
+}
+
+typedef struct
+{
+  FolksIndividual *individual;
+  EmpathyChatroom *chatroom;
+} RoomSubMenuData;
+
+static RoomSubMenuData *
+room_sub_menu_data_new (FolksIndividual *individual,
+      EmpathyChatroom *chatroom)
+{
+  RoomSubMenuData *data;
+
+  data = g_slice_new (RoomSubMenuData);
+  data->individual = g_object_ref (individual);
+  data->chatroom = g_object_ref (chatroom);
+  return data;
+}
+
+static void
+room_sub_menu_data_free (RoomSubMenuData *data)
+{
+  g_object_unref (data->individual);
+  g_object_unref (data->chatroom);
+  g_slice_free (RoomSubMenuData, data);
+}
+
+static void
+room_sub_menu_activate_cb (GtkWidget *item,
+         RoomSubMenuData *data)
+{
+  EmpathyTpChat *chat;
+  EmpathyContact *contact;
+
+  chat = empathy_chatroom_get_tp_chat (data->chatroom);
+  if (chat == NULL)
+    {
+      /* channel was invalidated. Ignoring */
+      return;
+    }
+
+  contact = empathy_contact_from_folks_individual (data->individual);
+
+  g_return_if_fail (EMPATHY_IS_CONTACT (contact));
+
+  /* send invitation */
+  empathy_contact_list_add (EMPATHY_CONTACT_LIST (chat),
+      contact, _("Inviting you to this room"));
+
+  g_object_unref (contact);
+}
+
+static GtkWidget *
+create_room_sub_menu (FolksIndividual *individual,
+                      EmpathyChatroom *chatroom)
+{
+  GtkWidget *item;
+  RoomSubMenuData *data;
+
+  item = gtk_menu_item_new_with_label (empathy_chatroom_get_name (chatroom));
+  data = room_sub_menu_data_new (individual, chatroom);
+  g_signal_connect_data (item, "activate",
+      G_CALLBACK (room_sub_menu_activate_cb), data,
+      (GClosureNotify) room_sub_menu_data_free, 0);
+
+  return item;
+}
+
+GtkWidget *
+empathy_individual_invite_menu_item_new (FolksIndividual *individual)
+{
+  GtkWidget *item;
+  GtkWidget *image;
+  GtkWidget *room_item;
+  EmpathyChatroomManager *mgr;
+  GList *rooms, *l;
+  GtkWidget *submenu = NULL;
+  EmpathyContact *contact;
+
+  g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL);
+
+  contact = empathy_contact_from_folks_individual (individual);
+
+  g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
+
+  item = gtk_image_menu_item_new_with_mnemonic (_("_Invite to Chat Room"));
+  image = gtk_image_new_from_icon_name (EMPATHY_IMAGE_GROUP_MESSAGE,
+      GTK_ICON_SIZE_MENU);
+  gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
+
+  mgr = empathy_chatroom_manager_dup_singleton (NULL);
+  rooms = empathy_chatroom_manager_get_chatrooms (mgr,
+      empathy_contact_get_account (contact));
+
+  for (l = rooms; l != NULL; l = g_list_next (l))
+    {
+      EmpathyChatroom *chatroom = l->data;
+
+      if (empathy_chatroom_get_tp_chat (chatroom) != NULL)
+        {
+          if (G_UNLIKELY (submenu == NULL))
+            submenu = gtk_menu_new ();
+
+          room_item = create_room_sub_menu (individual, chatroom);
+          gtk_menu_shell_append ((GtkMenuShell *) submenu, room_item);
+          gtk_widget_show (room_item);
+        }
+    }
+
+  if (submenu)
+    gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
+  else
+    gtk_widget_set_sensitive (item, FALSE);
+
+  gtk_widget_show (image);
+
+  g_object_unref (contact);
+  g_object_unref (mgr);
+  g_list_free (rooms);
+
+  return item;
+}
diff --git a/libempathy-gtk/empathy-individual-menu.h b/libempathy-gtk/empathy-individual-menu.h
index 5d22897..37b93ea 100644
--- a/libempathy-gtk/empathy-individual-menu.h
+++ b/libempathy-gtk/empathy-individual-menu.h
@@ -38,6 +38,26 @@ typedef enum {
 	EMPATHY_INDIVIDUAL_FEATURE_ALL = (1 << 6) - 1,
 } EmpathyIndividualFeatureFlags;
 
+GtkWidget * empathy_individual_menu_new (FolksIndividual *individual,
+    EmpathyIndividualFeatureFlags features);
+GtkWidget * empathy_individual_add_menu_item_new  (FolksIndividual *individual);
+GtkWidget * empathy_individual_chat_menu_item_new (FolksIndividual *individual);
+GtkWidget * empathy_individual_audio_call_menu_item_new (
+    FolksIndividual *individual);
+GtkWidget * empathy_individual_video_call_menu_item_new (
+    FolksIndividual *individual);
+GtkWidget * empathy_individual_log_menu_item_new  (FolksIndividual *individual);
+GtkWidget * empathy_individual_info_menu_item_new (FolksIndividual *individual);
+GtkWidget * empathy_individual_edit_menu_item_new (FolksIndividual *individual);
+GtkWidget * empathy_individual_invite_menu_item_new (
+    FolksIndividual *individual);
+GtkWidget * empathy_individual_file_transfer_menu_item_new (
+    FolksIndividual *individual);
+GtkWidget * empathy_individual_share_my_desktop_menu_item_new (
+    FolksIndividual *individual);
+GtkWidget * empathy_individual_favourite_menu_item_new (
+    FolksIndividual *individual);
+
 G_END_DECLS
 
 #endif /* __EMPATHY_INDIVIDUAL_MENU_H__ */
diff --git a/libempathy-gtk/empathy-individual-store.c b/libempathy-gtk/empathy-individual-store.c
index 0e3dd25..3390f31 100644
--- a/libempathy-gtk/empathy-individual-store.c
+++ b/libempathy-gtk/empathy-individual-store.c
@@ -117,10 +117,11 @@ G_DEFINE_TYPE (EmpathyIndividualStore, empathy_individual_store,
 static void
 add_individual_to_store (GtkTreeStore *self,
     GtkTreeIter *iter,
+    GtkTreeIter *parent,
     FolksIndividual *individual,
     EmpathyIndividualManagerFlags flags)
 {
-  gtk_tree_store_set (self, iter,
+  gtk_tree_store_insert_with_values (self, iter, parent, 0,
       EMPATHY_INDIVIDUAL_STORE_COL_NAME,
       folks_individual_get_alias (individual),
       EMPATHY_INDIVIDUAL_STORE_COL_INDIVIDUAL, individual,
@@ -132,7 +133,8 @@ add_individual_to_store (GtkTreeStore *self,
       EMPATHY_INDIVIDUAL_STORE_COL_CAN_VIDEO_CALL,
       folks_individual_get_capabilities (individual) &
       FOLKS_CAPABILITIES_FLAGS_VIDEO,
-      EMPATHY_INDIVIDUAL_STORE_COL_FLAGS, flags, -1);
+      EMPATHY_INDIVIDUAL_STORE_COL_FLAGS, flags,
+      -1);
 }
 
 static gboolean
@@ -391,10 +393,7 @@ individual_store_add_individual (EmpathyIndividualStore *self,
               &iter_group, NULL, NULL, TRUE);
         }
 
-      gtk_tree_store_insert_after (GTK_TREE_STORE (self), &iter,
-          parent, NULL);
-
-      add_individual_to_store (GTK_TREE_STORE (self), &iter,
+      add_individual_to_store (GTK_TREE_STORE (self), &iter, parent,
           individual, flags);
     }
 
@@ -406,10 +405,7 @@ individual_store_add_individual (EmpathyIndividualStore *self,
       individual_store_get_group (self, l->data, &iter_group, NULL, NULL,
           FALSE);
 
-      gtk_tree_store_insert_after (GTK_TREE_STORE (self), &iter,
-          &iter_group, NULL);
-
-      add_individual_to_store (GTK_TREE_STORE (self), &iter,
+      add_individual_to_store (GTK_TREE_STORE (self), &iter, &iter_group,
           individual, flags);
     }
   g_list_free (groups);
@@ -426,10 +422,7 @@ individual_store_add_individual (EmpathyIndividualStore *self,
       individual_store_get_group (self, EMPATHY_INDIVIDUAL_STORE_FAVORITE,
           &iter_group, NULL, NULL, TRUE);
 
-      gtk_tree_store_insert_after (GTK_TREE_STORE (self), &iter,
-          &iter_group, NULL);
-
-      add_individual_to_store (GTK_TREE_STORE (self), &iter,
+      add_individual_to_store (GTK_TREE_STORE (self), &iter, &iter_group,
           individual, flags);
     }
 #endif
@@ -456,7 +449,8 @@ individual_store_contact_set_active (EmpathyIndividualStore *self,
       GtkTreePath *path;
 
       gtk_tree_store_set (GTK_TREE_STORE (self), l->data,
-          EMPATHY_INDIVIDUAL_STORE_COL_IS_ACTIVE, active, -1);
+          EMPATHY_INDIVIDUAL_STORE_COL_IS_ACTIVE, active,
+          -1);
 
       DEBUG ("Set item %s", active ? "active" : "inactive");
 
@@ -686,21 +680,22 @@ individual_store_contact_update (EmpathyIndividualStore *self,
           EMPATHY_INDIVIDUAL_STORE_COL_ICON_STATUS, pixbuf_status,
           EMPATHY_INDIVIDUAL_STORE_COL_PIXBUF_AVATAR_VISIBLE, show_avatar,
           EMPATHY_INDIVIDUAL_STORE_COL_NAME,
-          folks_individual_get_alias (individual),
+            folks_individual_get_alias (individual),
           EMPATHY_INDIVIDUAL_STORE_COL_PRESENCE_TYPE,
-          folks_individual_get_presence_type (individual),
+            folks_individual_get_presence_type (individual),
           EMPATHY_INDIVIDUAL_STORE_COL_STATUS,
-          folks_individual_get_presence_message (individual),
+            folks_individual_get_presence_message (individual),
           EMPATHY_INDIVIDUAL_STORE_COL_CAN_AUDIO_CALL,
-          folks_individual_get_capabilities (individual) &
-          FOLKS_CAPABILITIES_FLAGS_AUDIO,
+            folks_individual_get_capabilities (individual) &
+              FOLKS_CAPABILITIES_FLAGS_AUDIO,
           EMPATHY_INDIVIDUAL_STORE_COL_CAN_VIDEO_CALL,
-          folks_individual_get_capabilities (individual) &
-          FOLKS_CAPABILITIES_FLAGS_VIDEO,
+            folks_individual_get_capabilities (individual) &
+              FOLKS_CAPABILITIES_FLAGS_VIDEO,
           EMPATHY_INDIVIDUAL_STORE_COL_COMPACT, priv->is_compact,
           EMPATHY_INDIVIDUAL_STORE_COL_IS_GROUP, FALSE,
           EMPATHY_INDIVIDUAL_STORE_COL_IS_ONLINE, now_online,
-          EMPATHY_INDIVIDUAL_STORE_COL_IS_SEPARATOR, FALSE, -1);
+          EMPATHY_INDIVIDUAL_STORE_COL_IS_SEPARATOR, FALSE,
+          -1);
     }
 
   if (priv->show_active && do_set_active)
diff --git a/libempathy-gtk/empathy-individual-view.c b/libempathy-gtk/empathy-individual-view.c
index 83b0196..b6df6d7 100644
--- a/libempathy-gtk/empathy-individual-view.c
+++ b/libempathy-gtk/empathy-individual-view.c
@@ -770,20 +770,17 @@ individual_view_popup_menu_idle_cb (gpointer user_data)
   GtkWidget *menu;
 
   menu = empathy_individual_view_get_individual_menu (data->view);
-  if (!menu)
-    {
-      menu = empathy_individual_view_get_group_menu (data->view);
-    }
+  if (menu == NULL)
+    menu = empathy_individual_view_get_group_menu (data->view);
 
-  if (menu)
+  if (menu != NULL)
     {
-      g_signal_connect (menu, "deactivate",
-          G_CALLBACK (gtk_menu_detach), NULL);
-      gtk_menu_attach_to_widget (GTK_MENU (menu),
-          GTK_WIDGET (data->view), NULL);
+      g_signal_connect (menu, "deactivate", G_CALLBACK (gtk_menu_detach), NULL);
+      gtk_menu_attach_to_widget (GTK_MENU (menu), GTK_WIDGET (data->view),
+          NULL);
       gtk_widget_show (menu);
-      gtk_menu_popup (GTK_MENU (menu),
-          NULL, NULL, NULL, NULL, data->button, data->time);
+      gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, data->button,
+          data->time);
       g_object_ref_sink (menu);
       g_object_unref (menu);
     }
@@ -2064,8 +2061,7 @@ empathy_individual_view_get_individual_menu (EmpathyIndividualView *view)
     }
   flags = empathy_individual_view_get_flags (view);
 
-  /* TODO: implement (create the menu here */
-  DEBUG ("individual menu not implemented");
+  menu = empathy_individual_menu_new (individual, priv->individual_features);
 
   /* Remove contact */
   if (priv->view_features &
diff --git a/libempathy/empathy-individual-manager.c b/libempathy/empathy-individual-manager.c
index 4b27e74..0af191a 100644
--- a/libempathy/empathy-individual-manager.c
+++ b/libempathy/empathy-individual-manager.c
@@ -288,3 +288,33 @@ empathy_individual_manager_remove (EmpathyIndividualManager *self,
   /* TODO: implement */
   DEBUG (G_STRLOC ": individual removal not implemented");
 }
+
+EmpathyIndividualManagerFlags
+empathy_individual_manager_get_flags_for_connection (
+    EmpathyIndividualManager *self,
+    TpConnection *connection)
+{
+  EmpathyIndividualManagerPriv *priv;
+  EmpathyContactListFlags list_flags;
+  EmpathyIndividualManagerFlags flags;
+
+  g_return_val_if_fail (EMPATHY_IS_INDIVIDUAL_MANAGER (self),
+      EMPATHY_INDIVIDUAL_MANAGER_NO_FLAGS);
+
+  priv = GET_PRIV (self);
+
+  list_flags = empathy_contact_manager_get_flags_for_connection (
+    priv->contact_manager, connection);
+
+  flags = EMPATHY_INDIVIDUAL_MANAGER_NO_FLAGS;
+  if (list_flags & EMPATHY_CONTACT_LIST_CAN_ADD)
+    flags |= EMPATHY_INDIVIDUAL_MANAGER_CAN_ADD;
+  if (list_flags & EMPATHY_CONTACT_LIST_CAN_REMOVE)
+    flags |= EMPATHY_INDIVIDUAL_MANAGER_CAN_REMOVE;
+  if (list_flags & EMPATHY_CONTACT_LIST_CAN_ALIAS)
+    flags |= EMPATHY_INDIVIDUAL_MANAGER_CAN_ALIAS;
+  if (list_flags & EMPATHY_CONTACT_LIST_CAN_GROUP)
+    flags |= EMPATHY_INDIVIDUAL_MANAGER_CAN_GROUP;
+
+  return flags;
+}
diff --git a/libempathy/empathy-individual-manager.h b/libempathy/empathy-individual-manager.h
index 1823dec..be95ab3 100644
--- a/libempathy/empathy-individual-manager.h
+++ b/libempathy/empathy-individual-manager.h
@@ -37,6 +37,7 @@ G_BEGIN_DECLS
 #define EMPATHY_INDIVIDUAL_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EMPATHY_TYPE_INDIVIDUAL_MANAGER, EmpathyIndividualManagerClass))
     typedef enum
 {
+  EMPATHY_INDIVIDUAL_MANAGER_NO_FLAGS = 0,
   EMPATHY_INDIVIDUAL_MANAGER_CAN_ADD = 1 << 0,
   EMPATHY_INDIVIDUAL_MANAGER_CAN_REMOVE = 1 << 1,
   EMPATHY_INDIVIDUAL_MANAGER_CAN_ALIAS = 1 << 2,
@@ -78,5 +79,10 @@ gboolean empathy_individual_manager_is_favourite (
     EmpathyIndividualManager *manager,
     FolksIndividual *individual);
 
+EmpathyIndividualManagerFlags
+empathy_individual_manager_get_flags_for_connection (
+    EmpathyIndividualManager *manager,
+    TpConnection *connection);
+
 G_END_DECLS
 #endif /* __EMPATHY_INDIVIDUAL_MANAGER_H__ */
diff --git a/libempathy/empathy-utils.c b/libempathy/empathy-utils.c
index 56da323..df2a41a 100644
--- a/libempathy/empathy-utils.c
+++ b/libempathy/empathy-utils.c
@@ -569,6 +569,30 @@ empathy_folks_presence_type_to_tp (FolksPresenceType type)
   return (TpConnectionPresenceType) type;
 }
 
+gboolean
+empathy_folks_individual_contains_contact (FolksIndividual *individual)
+{
+  GList *personas, *l;
+
+  g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), FALSE);
+
+  personas = folks_individual_get_personas (individual);
+  for (l = personas; l != NULL; l = l->next)
+    {
+      TpfPersona *persona = l->data;
+
+      if (TPF_IS_PERSONA (persona))
+        {
+          TpContact *contact = tpf_persona_get_contact (persona);
+
+          if (TP_IS_CONTACT (contact))
+            return TRUE;
+        }
+    }
+
+  return FALSE;
+}
+
 EmpathyContact *
 empathy_contact_from_folks_individual (FolksIndividual *individual)
 {
diff --git a/libempathy/empathy-utils.h b/libempathy/empathy-utils.h
index 1ba7e53..c6de97a 100644
--- a/libempathy/empathy-utils.h
+++ b/libempathy/empathy-utils.h
@@ -91,6 +91,7 @@ void empathy_connect_new_account (TpAccount *account,
     TpAccountManager *account_manager);
 
 TpConnectionPresenceType empathy_folks_presence_type_to_tp (FolksPresenceType type);
+gboolean empathy_folks_individual_contains_contact (FolksIndividual *individual);
 EmpathyContact * empathy_contact_from_folks_individual (FolksIndividual *individual);
 
 G_END_DECLS
diff --git a/src/empathy-main-window.c b/src/empathy-main-window.c
index 9117c1b..0e596fe 100644
--- a/src/empathy-main-window.c
+++ b/src/empathy-main-window.c
@@ -182,6 +182,9 @@ main_window_flash_foreach (GtkTreeModel *model,
 				&individual,
 			    -1);
 
+	if (individual == NULL)
+		return FALSE;
+
 	contact = empathy_contact_from_folks_individual (individual);
 	if (contact != data->event->contact) {
 		if (contact) {



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