[empathy] Add empathy_contact_dup_best_for_action()



commit c1b7707c628cb16b44d2159fff993b44e1a5b946
Author: Philip Withnall <philip withnall collabora co uk>
Date:   Thu Sep 2 13:26:31 2010 +0100

    Add empathy_contact_dup_best_for_action()
    
    This takes a FolksIndividual and returns an EmpathyContact corresponding to
    the FolksPersona in the Individual which is most suited to having a given
    action performed on it. Helps: bgo#628338

 libempathy/empathy-contact.c |  140 ++++++++++++++++++++++++++++++++++++++++++
 libempathy/empathy-contact.h |   14 ++++
 2 files changed, 154 insertions(+), 0 deletions(-)
---
diff --git a/libempathy/empathy-contact.c b/libempathy/empathy-contact.c
index c4be981..0bba883 100644
--- a/libempathy/empathy-contact.c
+++ b/libempathy/empathy-contact.c
@@ -29,6 +29,8 @@
 #include <telepathy-glib/interfaces.h>
 #include <telepathy-glib/util.h>
 
+#include <telepathy-logger/log-manager.h>
+
 #include <folks/folks.h>
 #include <folks/folks-telepathy.h>
 
@@ -1125,6 +1127,54 @@ empathy_contact_can_use_rfb_stream_tube (EmpathyContact *contact)
   return priv->capabilities & EMPATHY_CAPABILITIES_RFB_STREAM_TUBE;
 }
 
+static gboolean
+contact_has_log (EmpathyContact *contact)
+{
+  TplLogManager *manager;
+  gboolean have_log;
+
+  manager = tpl_log_manager_dup_singleton ();
+  have_log = tpl_log_manager_exists (manager,
+      empathy_contact_get_account (contact), empathy_contact_get_id (contact),
+      FALSE);
+  g_object_unref (manager);
+
+  return have_log;
+}
+
+gboolean
+empathy_contact_can_do_action (EmpathyContact *self,
+    EmpathyActionType action_type)
+{
+  gboolean sensitivity = FALSE;
+
+  switch (action_type)
+    {
+      case EMPATHY_ACTION_CHAT:
+        sensitivity = TRUE;
+        break;
+      case EMPATHY_ACTION_AUDIO_CALL:
+        sensitivity = empathy_contact_can_voip_audio (self);
+        break;
+      case EMPATHY_ACTION_VIDEO_CALL:
+        sensitivity = empathy_contact_can_voip_video (self);
+        break;
+      case EMPATHY_ACTION_VIEW_LOGS:
+        sensitivity = contact_has_log (self);
+        break;
+      case EMPATHY_ACTION_SEND_FILE:
+        sensitivity = empathy_contact_can_send_files (self);
+        break;
+      case EMPATHY_ACTION_SHARE_MY_DESKTOP:
+        sensitivity = empathy_contact_can_use_rfb_stream_tube (self);
+        break;
+      default:
+        g_assert_not_reached ();
+    }
+
+  return (sensitivity ? TRUE : FALSE);
+}
+
 static gchar *
 contact_get_avatar_filename (EmpathyContact *contact,
                              const gchar *token)
@@ -1686,3 +1736,93 @@ empathy_contact_dup_from_tp_contact (TpContact *tp_contact)
   return contact;
 }
 
+static int
+presence_sort_func (EmpathyContact *a, EmpathyContact *b)
+{
+  FolksPresence *presence_a, *presence_b;
+
+  presence_a = FOLKS_PRESENCE (empathy_contact_get_persona (a));
+  presence_b = FOLKS_PRESENCE (empathy_contact_get_persona (b));
+
+  /* We negate the result because we're sorting in reverse order (i.e. such that
+   * the Personas with the highest presence are at the beginning of the list. */
+  return -folks_presence_typecmp (folks_presence_get_presence_type (presence_a),
+      folks_presence_get_presence_type (presence_b));
+}
+
+static GCompareFunc
+get_sort_func_for_action (EmpathyActionType action_type)
+{
+  switch (action_type)
+    {
+      case EMPATHY_ACTION_CHAT:
+      case EMPATHY_ACTION_AUDIO_CALL:
+      case EMPATHY_ACTION_VIDEO_CALL:
+      case EMPATHY_ACTION_VIEW_LOGS:
+      case EMPATHY_ACTION_SEND_FILE:
+      case EMPATHY_ACTION_SHARE_MY_DESKTOP:
+      default:
+        return (GCompareFunc) presence_sort_func;
+    }
+}
+
+/**
+ * empathy_contact_dup_best_for_action:
+ * @individual: a #FolksIndividual
+ * @action_type: the type of action to be performed on the contact
+ *
+ * Chooses a #FolksPersona from the given @individual which is best-suited for
+ * the given @action_type. "Best-suited" is determined by choosing the persona
+ * with the highest presence out of all the personas which can perform the given
+ * @action_type (e.g. are capable of video calling).
+ *
+ * Return value: an #EmpathyContact for the best persona, or %NULL;
+ * unref with g_object_unref()
+ */
+EmpathyContact *
+empathy_contact_dup_best_for_action (FolksIndividual *individual,
+    EmpathyActionType action_type)
+{
+  GList *personas, *contacts, *l;
+  EmpathyContact *best_contact = NULL;
+
+  /* Build a list of EmpathyContacts that we can sort */
+  personas = folks_individual_get_personas (individual);
+  contacts = NULL;
+
+  for (l = personas; l != NULL; l = l->next)
+    {
+      TpContact *tp_contact;
+      EmpathyContact *contact;
+
+      if (!TPF_IS_PERSONA (l->data))
+        continue;
+
+      tp_contact = tpf_persona_get_contact (TPF_PERSONA (l->data));
+      contact = empathy_contact_dup_from_tp_contact (tp_contact);
+      empathy_contact_set_persona (contact, FOLKS_PERSONA (l->data));
+
+      /* Only choose the contact if they're actually capable of the specified
+       * action. */
+      if (!empathy_contact_can_do_action (contact, action_type))
+        {
+          g_object_unref (contact);
+          continue;
+        }
+
+      contacts = g_list_prepend (contacts, contact);
+    }
+
+  /* Sort the contacts by some heuristic based on the action type, then take
+   * the top contact. */
+  if (contacts != NULL)
+    {
+      contacts = g_list_sort (contacts, get_sort_func_for_action (action_type));
+      best_contact = g_object_ref (contacts->data);
+    }
+
+  g_list_foreach (contacts, (GFunc) g_object_unref, NULL);
+  g_list_free (contacts);
+
+  return best_contact;
+}
diff --git a/libempathy/empathy-contact.h b/libempathy/empathy-contact.h
index c1ef55d..005cf1e 100644
--- a/libempathy/empathy-contact.h
+++ b/libempathy/empathy-contact.h
@@ -100,6 +100,17 @@ gboolean empathy_contact_can_voip_video (EmpathyContact *contact);
 gboolean empathy_contact_can_send_files (EmpathyContact *contact);
 gboolean empathy_contact_can_use_rfb_stream_tube (EmpathyContact *contact);
 
+typedef enum {
+  EMPATHY_ACTION_CHAT,
+  EMPATHY_ACTION_AUDIO_CALL,
+  EMPATHY_ACTION_VIDEO_CALL,
+  EMPATHY_ACTION_VIEW_LOGS,
+  EMPATHY_ACTION_SEND_FILE,
+  EMPATHY_ACTION_SHARE_MY_DESKTOP,
+} EmpathyActionType;
+
+gboolean empathy_contact_can_do_action (EmpathyContact *self,
+    EmpathyActionType action_type);
 
 #define EMPATHY_TYPE_AVATAR (empathy_avatar_get_type ())
 GType empathy_avatar_get_type (void) G_GNUC_CONST;
@@ -118,6 +129,9 @@ gboolean empathy_contact_equal (gconstpointer contact1,
     gconstpointer contact2);
 
 EmpathyContact *empathy_contact_dup_from_tp_contact (TpContact *tp_contact);
+EmpathyContact * empathy_contact_dup_best_for_action (
+    FolksIndividual *individual,
+    EmpathyActionType action_type);
 
 G_END_DECLS
 



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