]> git.0d.be Git - empathy.git/blobdiff - libempathy-gtk/empathy-roster-contact.c
sort contacts by most recent event
[empathy.git] / libempathy-gtk / empathy-roster-contact.c
index 2db024a3d8a9a5283483a4794dc60c3e89a264aa..d98ca13fca064cc8c6810687e1d3d6d9cd5bd08a 100644 (file)
@@ -2,12 +2,13 @@
 #include "empathy-roster-contact.h"
 
 #include <glib/gi18n-lib.h>
+#include <tp-account-widgets/tpaw-images.h>
+#include <tp-account-widgets/tpaw-pixbuf-utils.h>
 
-#include "empathy-images.h"
 #include "empathy-ui-utils.h"
 #include "empathy-utils.h"
 
-G_DEFINE_TYPE (EmpathyRosterContact, empathy_roster_contact, GTK_TYPE_ALIGNMENT)
+G_DEFINE_TYPE (EmpathyRosterContact, empathy_roster_contact, GTK_TYPE_LIST_BOX_ROW)
 
 #define AVATAR_SIZE 48
 
@@ -17,6 +18,7 @@ enum
   PROP_GROUP,
   PROP_ONLINE,
   PROP_ALIAS,
+  PROP_MOST_RECENT_EVENT,
   N_PROPS
 };
 
@@ -32,12 +34,17 @@ static guint signals[LAST_SIGNAL];
 struct _EmpathyRosterContactPriv
 {
   FolksIndividual *individual;
+  EmpathyContact *contact;
   gchar *group;
 
+  TplLogManager *log_manager;
+  TplEvent *most_recent_event;
+
   GtkWidget *avatar;
   GtkWidget *first_line_alig;
   GtkWidget *alias;
   GtkWidget *presence_msg;
+  GtkWidget *most_recent_msg;
   GtkWidget *presence_icon;
   GtkWidget *phone_icon;
 
@@ -76,6 +83,9 @@ empathy_roster_contact_get_property (GObject *object,
       case PROP_ALIAS:
         g_value_set_string (value, get_alias (self));
         break;
+      case PROP_MOST_RECENT_EVENT:
+        g_value_set_object (value, self->priv->most_recent_event);
+        break;
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
         break;
@@ -106,6 +116,24 @@ empathy_roster_contact_set_property (GObject *object,
     }
 }
 
+gint64
+empathy_roster_contact_get_most_recent_timestamp (EmpathyRosterContact *contact)
+{
+  if (contact->priv->most_recent_event) {
+    return tpl_event_get_timestamp (contact->priv->most_recent_event);
+  }
+  return 0;
+}
+
+static const gchar*
+get_most_recent_message (EmpathyRosterContact *contact)
+{
+  if (contact->priv->most_recent_event) {
+    return tpl_text_event_get_message (TPL_TEXT_EVENT(contact->priv->most_recent_event));
+  }
+  return NULL;
+}
+
 static void
 avatar_loaded_cb (GObject *source,
     GAsyncResult *result,
@@ -124,8 +152,8 @@ avatar_loaded_cb (GObject *source,
 
   if (pixbuf == NULL)
     {
-      pixbuf = empathy_pixbuf_from_icon_name_sized (
-          EMPATHY_IMAGE_AVATAR_DEFAULT, AVATAR_SIZE);
+      pixbuf = tpaw_pixbuf_from_icon_name_sized (
+          TPAW_IMAGE_AVATAR_DEFAULT, AVATAR_SIZE);
     }
 
   gtk_image_set_from_pixbuf (GTK_IMAGE (self->priv->avatar), pixbuf);
@@ -137,6 +165,29 @@ out:
   tp_weak_ref_destroy (wr);
 }
 
+static void
+update_most_recent_msg (EmpathyRosterContact *self)
+{
+  const gchar* msg = get_most_recent_message (self);
+
+  if (tp_str_empty (msg))
+    {
+      gtk_alignment_set (GTK_ALIGNMENT (self->priv->first_line_alig),
+          0, 0.5, 1, 1);
+      gtk_widget_hide (self->priv->most_recent_msg);
+    }
+  else
+    {
+      gchar *tmp = g_strdup (msg);
+      if (strchr(tmp, '\n')) strchr(tmp, '\n')[0] = 0;
+      gtk_label_set_text (GTK_LABEL (self->priv->most_recent_msg), tmp);
+      gtk_alignment_set (GTK_ALIGNMENT (self->priv->first_line_alig),
+          0, 0.75, 1, 1);
+      gtk_misc_set_alignment (GTK_MISC (self->priv->most_recent_msg), 0, 0.25);
+      g_free (tmp);
+    }
+}
+
 static void
 update_avatar (EmpathyRosterContact *self)
 {
@@ -290,10 +341,36 @@ presence_status_changed_cb (FolksIndividual *individual,
   update_online (self);
 }
 
+static void
+get_filtered_events (GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+  EmpathyRosterContact *contact = EMPATHY_ROSTER_CONTACT (user_data);
+  GError *error;
+  GList *events;
+
+  error = NULL;
+  if (!tpl_log_manager_get_filtered_events_finish (contact->priv->log_manager, res, &events, &error))
+    {
+      g_warning ("Unable to get events: %s", error->message);
+      g_error_free (error);
+      goto out;
+    }
+
+  if (events) {
+    contact->priv->most_recent_event = TPL_EVENT (events->data);
+    g_object_notify (G_OBJECT (contact), "most-recent-event");
+    update_most_recent_msg (contact);
+  }
+
+ out:
+  return;
+}
+
 static void
 empathy_roster_contact_constructed (GObject *object)
 {
   EmpathyRosterContact *self = EMPATHY_ROSTER_CONTACT (object);
+  TplEntity *tpl_entity;
   void (*chain_up) (GObject *) =
       ((GObjectClass *) empathy_roster_contact_parent_class)->constructed;
 
@@ -302,6 +379,26 @@ empathy_roster_contact_constructed (GObject *object)
 
   g_assert (FOLKS_IS_INDIVIDUAL (self->priv->individual));
 
+  self->priv->contact = empathy_contact_dup_best_for_action (
+                  self->priv->individual,
+                  EMPATHY_ACTION_CHAT);
+
+  self->priv->log_manager = tpl_log_manager_dup_singleton ();
+
+  tpl_entity = tpl_entity_new_from_tp_contact (
+                  empathy_contact_get_tp_contact (self->priv->contact),
+                  TPL_ENTITY_CONTACT);
+  tpl_log_manager_get_filtered_events_async(
+                  self->priv->log_manager,
+                  empathy_contact_get_account (self->priv->contact),
+                  tpl_entity,
+                  TPL_EVENT_MASK_TEXT,
+                  1,
+                  NULL,
+                  NULL,
+                  get_filtered_events,
+                  object);
+
   tp_g_signal_connect_object (self->priv->individual, "notify::avatar",
       G_CALLBACK (avatar_changed_cb), self, 0);
   tp_g_signal_connect_object (self->priv->individual, "notify::alias",
@@ -342,6 +439,7 @@ empathy_roster_contact_finalize (GObject *object)
 
   g_free (self->priv->group);
   g_free (self->priv->event_icon);
+  g_object_unref (self->priv->log_manager);
 
   if (chain_up != NULL)
     chain_up (object);
@@ -384,18 +482,28 @@ empathy_roster_contact_class_init (
       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
   g_object_class_install_property (oclass, PROP_ALIAS, spec);
 
+  spec = g_param_spec_object ("most-recent-event", "Most recent event",
+      "Most recent event",
+      TPL_TYPE_EVENT,
+      G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+  g_object_class_install_property (oclass, PROP_MOST_RECENT_EVENT, spec);
+
   g_type_class_add_private (klass, sizeof (EmpathyRosterContactPriv));
 }
 
 static void
 empathy_roster_contact_init (EmpathyRosterContact *self)
 {
-  GtkWidget *main_box, *box, *first_line_box;
+  GtkWidget *alig, *main_box, *box, *first_line_box;
   GtkStyleContext *context;
 
   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
       EMPATHY_TYPE_ROSTER_CONTACT, EmpathyRosterContactPriv);
 
+  alig = gtk_alignment_new (0.5, 0.5, 1, 1);
+  gtk_widget_show (alig);
+  gtk_alignment_set_padding (GTK_ALIGNMENT (alig), 4, 4, 4, 12);
+
   main_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
 
   /* Avatar */
@@ -440,12 +548,24 @@ empathy_roster_contact_init (EmpathyRosterContact *self)
   self->priv->presence_msg = gtk_label_new (NULL);
   gtk_label_set_ellipsize (GTK_LABEL (self->priv->presence_msg),
       PANGO_ELLIPSIZE_END);
+  /*
   gtk_box_pack_start (GTK_BOX (box), self->priv->presence_msg, TRUE, TRUE, 0);
   gtk_widget_show (self->priv->presence_msg);
+  */
 
   context = gtk_widget_get_style_context (self->priv->presence_msg);
   gtk_style_context_add_class (context, GTK_STYLE_CLASS_DIM_LABEL);
 
+  /* Most recent message */
+  self->priv->most_recent_msg = gtk_label_new (NULL);
+  gtk_label_set_ellipsize (GTK_LABEL (self->priv->most_recent_msg),
+      PANGO_ELLIPSIZE_END);
+  gtk_box_pack_start (GTK_BOX (box), self->priv->most_recent_msg, TRUE, TRUE, 0);
+  gtk_widget_show (self->priv->most_recent_msg);
+
+  context = gtk_widget_get_style_context (self->priv->most_recent_msg);
+  gtk_style_context_add_class (context, GTK_STYLE_CLASS_DIM_LABEL);
+
   /* Presence icon */
   self->priv->presence_icon = gtk_image_new ();
 
@@ -453,7 +573,8 @@ empathy_roster_contact_init (EmpathyRosterContact *self)
       FALSE, FALSE, 0);
   gtk_widget_show (self->priv->presence_icon);
 
-  gtk_container_add (GTK_CONTAINER (self), main_box);
+  gtk_container_add (GTK_CONTAINER (self), alig);
+  gtk_container_add (GTK_CONTAINER (alig), main_box);
   gtk_widget_show (main_box);
 }
 
@@ -466,10 +587,6 @@ empathy_roster_contact_new (FolksIndividual *individual,
   return g_object_new (EMPATHY_TYPE_ROSTER_CONTACT,
       "individual", individual,
       "group", group,
-      "bottom-padding", 4,
-      "top-padding", 4,
-      "left-padding", 4,
-      "right-padding", 12,
       NULL);
 }
 
@@ -479,6 +596,12 @@ empathy_roster_contact_get_individual (EmpathyRosterContact *self)
   return self->priv->individual;
 }
 
+EmpathyContact *
+empathy_roster_contact_get_contact (EmpathyRosterContact *self)
+{
+  return self->priv->contact;
+}
+
 gboolean
 empathy_roster_contact_is_online (EmpathyRosterContact *self)
 {