[empathy] add EMPATHY_INDIVIDUAL_FEATURE_BLOCK



commit a401d8ed46a4284c140cd44a2cc5cbf53d07e286
Author: Guillaume Desmottes <guillaume desmottes collabora co uk>
Date:   Thu Dec 1 14:27:55 2011 +0100

    add EMPATHY_INDIVIDUAL_FEATURE_BLOCK
    
    https://bugzilla.gnome.org/show_bug.cgi?id=665038

 libempathy-gtk/empathy-individual-menu.c |  215 ++++++++++++++++++++++++++++++
 libempathy-gtk/empathy-individual-menu.h |    1 +
 2 files changed, 216 insertions(+), 0 deletions(-)
---
diff --git a/libempathy-gtk/empathy-individual-menu.c b/libempathy-gtk/empathy-individual-menu.c
index 2882a9e..3938b01 100644
--- a/libempathy-gtk/empathy-individual-menu.c
+++ b/libempathy-gtk/empathy-individual-menu.c
@@ -44,6 +44,7 @@
 #include "empathy-log-window.h"
 #include "empathy-contact-dialogs.h"
 #include "empathy-gtk-enum-types.h"
+#include "empathy-individual-dialogs.h"
 #include "empathy-individual-edit-dialog.h"
 #include "empathy-individual-information-dialog.h"
 #include "empathy-ui-utils.h"
@@ -443,6 +444,207 @@ add_phone_numbers (EmpathyIndividualMenu *self)
     }
 }
 
+/* return a list of TpContact supporting the blocking iface */
+static GList *
+get_contacts_supporting_blocking (FolksIndividual *individual)
+{
+  GeeSet *personas;
+  GeeIterator *iter;
+  GList *result = NULL;
+
+  personas = folks_individual_get_personas (individual);
+
+  iter = gee_iterable_iterator (GEE_ITERABLE (personas));
+  while (gee_iterator_next (iter))
+    {
+      TpfPersona *persona = gee_iterator_get (iter);
+      TpContact *contact;
+      TpConnection *conn;
+
+      if (!TPF_IS_PERSONA (persona))
+        continue;
+
+      contact = tpf_persona_get_contact (persona);
+      if (contact == NULL)
+        continue;
+
+      conn = tp_contact_get_connection (contact);
+
+      if (tp_proxy_has_interface_by_id (conn,
+        TP_IFACE_QUARK_CONNECTION_INTERFACE_CONTACT_BLOCKING))
+        result = g_list_prepend (result, contact);
+    }
+
+  g_clear_object (&iter);
+
+  return result;
+}
+
+typedef struct
+{
+  gboolean blocked;
+  GtkWidget *parent;
+} GotAvatarCtx;
+
+static GotAvatarCtx *
+got_avatar_ctx_new (gboolean blocked,
+    GtkWidget *parent)
+{
+  GotAvatarCtx *ctx = g_slice_new0 (GotAvatarCtx);
+
+  ctx->blocked = blocked;
+  ctx->parent = parent != NULL ? g_object_ref (parent) : NULL;
+  return ctx;
+}
+
+static void
+got_avatar_ctx_free (GotAvatarCtx *ctx)
+{
+  g_clear_object (&ctx->parent);
+  g_slice_free (GotAvatarCtx, ctx);
+}
+
+static void
+got_avatar (GObject *source_object,
+    GAsyncResult *result,
+    gpointer user_data)
+{
+  FolksIndividual *individual = FOLKS_INDIVIDUAL (source_object);
+  GotAvatarCtx *ctx = user_data;
+  GdkPixbuf *avatar;
+  GError *error = NULL;
+  gboolean abusive = FALSE;
+  EmpathyIndividualManager *manager;
+
+  avatar = empathy_pixbuf_avatar_from_individual_scaled_finish (individual,
+      result, &error);
+
+  if (error != NULL)
+    {
+      DEBUG ("Could not get avatar: %s", error->message);
+      g_error_free (error);
+    }
+
+  if (ctx->blocked) {
+    /* confirm the user really wishes to block the contact */
+    if (!empathy_block_individual_dialog_show (GTK_WINDOW (ctx->parent),
+          individual, avatar, &abusive))
+      goto out;
+  }
+
+  manager = empathy_individual_manager_dup_singleton ();
+
+  empathy_individual_manager_set_blocked (manager, individual,
+      ctx->blocked, abusive);
+
+  g_object_unref (manager);
+
+out:
+  g_clear_object (&avatar);
+  got_avatar_ctx_free (ctx);
+}
+
+static void
+empathy_individual_block_menu_item_toggled (GtkCheckMenuItem *item,
+    FolksIndividual *individual)
+{
+  GotAvatarCtx *ctx;
+  gboolean blocked;
+  GtkWidget *parent;
+
+  /* @item may be destroyed while the async call is running to get the things
+   * we need from it right now. */
+  blocked = gtk_check_menu_item_get_active (item);
+
+  parent = g_object_get_data (
+    G_OBJECT (gtk_widget_get_parent (GTK_WIDGET (item))),
+    "window");
+
+  ctx = got_avatar_ctx_new (blocked, parent);
+
+  empathy_pixbuf_avatar_from_individual_scaled_async (individual,
+      48, 48, NULL, got_avatar, ctx);
+}
+
+static void
+update_block_menu_item (GtkWidget *item,
+    FolksIndividual *individual)
+{
+  GList *contacts, *l;
+  gboolean is_blocked = FALSE;
+
+  contacts = get_contacts_supporting_blocking (individual);
+
+  /* Check the menu item if there is at least one persona blocked */
+  for (l = contacts; l != NULL; l = g_list_next (l))
+    {
+      TpContact *contact = l->data;
+
+      if (tp_contact_is_blocked (contact))
+        {
+          is_blocked = TRUE;
+          break;
+        }
+    }
+
+  g_signal_handlers_block_by_func (item,
+      empathy_individual_block_menu_item_toggled, individual);
+
+  gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), is_blocked);
+
+  g_signal_handlers_unblock_by_func (item,
+      empathy_individual_block_menu_item_toggled, individual);
+
+  g_list_free (contacts);
+}
+
+static void
+contact_blocked_changed_cb (TpContact *contact,
+    GParamSpec *spec,
+    GtkWidget *item)
+{
+  FolksIndividual *individual;
+
+  individual = g_object_get_data (G_OBJECT (item), "individual");
+
+  update_block_menu_item (item, individual);
+}
+
+static GtkWidget *
+empathy_individiual_block_menu_item_new (FolksIndividual *individual)
+{
+  GtkWidget *item;
+  GList *contacts, *l;
+
+  contacts = get_contacts_supporting_blocking (individual);
+
+  /* Can't block, no persona supports blocking */
+  if (contacts == NULL)
+    return NULL;
+
+  item = gtk_check_menu_item_new_with_mnemonic (_("_Block Contact"));
+
+  g_object_set_data_full (G_OBJECT (item), "individual",
+      g_object_ref (individual), g_object_unref);
+
+  for (l = contacts; l != NULL; l = g_list_next (l))
+    {
+      TpContact *contact = l->data;
+
+      tp_g_signal_connect_object (contact, "notify::is-blocked",
+          G_CALLBACK (contact_blocked_changed_cb), item, 0);
+    }
+
+  g_signal_connect (item, "toggled",
+      G_CALLBACK (empathy_individual_block_menu_item_toggled), individual);
+
+  update_block_menu_item (item, individual);
+
+  g_list_free (contacts);
+
+  return item;
+}
+
 static void
 constructed (GObject *object)
 {
@@ -581,6 +783,19 @@ constructed (GObject *object)
       gtk_menu_shell_append (shell, item);
       gtk_widget_show (item);
     }
+
+  /* Separator & Block */
+  if (features & EMPATHY_INDIVIDUAL_FEATURE_BLOCK &&
+      (item = empathy_individiual_block_menu_item_new (individual)) != NULL) {
+    GtkWidget *sep;
+
+    sep = gtk_separator_menu_item_new ();
+    gtk_menu_shell_append (shell, sep);
+    gtk_widget_show (sep);
+
+    gtk_menu_shell_append (shell, item);
+    gtk_widget_show (item);
+  }
 }
 
 static void
diff --git a/libempathy-gtk/empathy-individual-menu.h b/libempathy-gtk/empathy-individual-menu.h
index d5bced1..b4aad1e 100644
--- a/libempathy-gtk/empathy-individual-menu.h
+++ b/libempathy-gtk/empathy-individual-menu.h
@@ -41,6 +41,7 @@ typedef enum {
 	EMPATHY_INDIVIDUAL_FEATURE_SMS = 1 << 7,
 	EMPATHY_INDIVIDUAL_FEATURE_CALL_PHONE = 1 << 8,
 	EMPATHY_INDIVIDUAL_FEATURE_ADD_CONTACT = 1 << 9,
+	EMPATHY_INDIVIDUAL_FEATURE_BLOCK = 1 << 10,
 } EmpathyIndividualFeatureFlags;
 
 #define EMPATHY_TYPE_INDIVIDUAL_MENU (empathy_individual_menu_get_type ())



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