[empathy/wip/ui-refresh: 163/166] view: sort contacts by most recent event



commit 259380b71c76e8e3c6801ab0ad1b74a489d88e6a
Author: Frédéric Péters <fpeters 0d be>
Date:   Sun May 3 14:35:29 2015 +0200

    view: sort contacts by most recent event

 libempathy-gtk/empathy-roster-contact.c |  121 +++++++++++++++++++++++++++++++
 libempathy-gtk/empathy-roster-contact.h |    5 ++
 libempathy-gtk/empathy-roster-view.c    |   22 +++++-
 src/empathy-roster-window.c             |   42 ++++-------
 4 files changed, 161 insertions(+), 29 deletions(-)
---
diff --git a/libempathy-gtk/empathy-roster-contact.c b/libempathy-gtk/empathy-roster-contact.c
index df57a87..d98ca13 100644
--- a/libempathy-gtk/empathy-roster-contact.c
+++ b/libempathy-gtk/empathy-roster-contact.c
@@ -18,6 +18,7 @@ enum
   PROP_GROUP,
   PROP_ONLINE,
   PROP_ALIAS,
+  PROP_MOST_RECENT_EVENT,
   N_PROPS
 };
 
@@ -33,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;
 
@@ -77,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;
@@ -107,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,
@@ -139,6 +166,29 @@ out:
 }
 
 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)
 {
   empathy_pixbuf_avatar_from_individual_scaled_async (self->priv->individual,
@@ -292,9 +342,35 @@ presence_status_changed_cb (FolksIndividual *individual,
 }
 
 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;
 
@@ -303,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",
@@ -343,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);
@@ -385,6 +482,12 @@ 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));
 }
 
@@ -445,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 ();
 
@@ -481,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)
 {
diff --git a/libempathy-gtk/empathy-roster-contact.h b/libempathy-gtk/empathy-roster-contact.h
index 6e05959..1dc463a 100644
--- a/libempathy-gtk/empathy-roster-contact.h
+++ b/libempathy-gtk/empathy-roster-contact.h
@@ -3,6 +3,7 @@
 
 #include <gtk/gtk.h>
 #include <folks/folks.h>
+#include "empathy-contact.h"
 
 G_BEGIN_DECLS
 
@@ -52,6 +53,8 @@ GtkWidget * empathy_roster_contact_new (FolksIndividual *individual,
 
 FolksIndividual * empathy_roster_contact_get_individual (EmpathyRosterContact *self);
 
+EmpathyContact * empathy_roster_contact_get_contact (EmpathyRosterContact *self);
+
 const gchar * empathy_roster_contact_get_group (EmpathyRosterContact *self);
 
 gboolean empathy_roster_contact_is_online (EmpathyRosterContact *self);
@@ -62,6 +65,8 @@ void empathy_roster_contact_set_event_icon (EmpathyRosterContact *self,
 GdkPixbuf * empathy_roster_contact_get_avatar_pixbuf (
     EmpathyRosterContact *self);
 
+gint64 empathy_roster_contact_get_most_recent_timestamp (EmpathyRosterContact *contact);
+
 G_END_DECLS
 
 #endif /* #ifndef __EMPATHY_ROSTER_CONTACT_H__*/
diff --git a/libempathy-gtk/empathy-roster-view.c b/libempathy-gtk/empathy-roster-view.c
index 0dab3ba..e463bd9 100644
--- a/libempathy-gtk/empathy-roster-view.c
+++ b/libempathy-gtk/empathy-roster-view.c
@@ -189,6 +189,10 @@ add_roster_contact (EmpathyRosterView *self,
   g_signal_connect (contact, "notify::alias",
       G_CALLBACK (roster_contact_changed_cb), self);
 
+  /* Need to resort if most recent event changed */
+  g_signal_connect (contact, "notify::most-recent-event",
+      G_CALLBACK (roster_contact_changed_cb), self);
+
   gtk_widget_show (contact);
   gtk_container_add (GTK_CONTAINER (self), contact);
 
@@ -626,6 +630,20 @@ contact_in_top (EmpathyRosterView *self,
 }
 
 static gint
+compare_roster_contacts_by_conversation_time (EmpathyRosterContact *a,
+    EmpathyRosterContact *b)
+{
+  gint64 ts_a, ts_b;
+
+  ts_a = empathy_roster_contact_get_most_recent_timestamp (a);
+  ts_b = empathy_roster_contact_get_most_recent_timestamp (b);
+
+  if (ts_a == ts_b) return 0;
+  if (ts_a > ts_b) return -1;
+  return 1;
+}
+
+static gint
 compare_roster_contacts_by_alias (EmpathyRosterContact *a,
     EmpathyRosterContact *b)
 {
@@ -654,7 +672,7 @@ compare_roster_contacts_no_group (EmpathyRosterView *self,
   if (top_a == top_b)
     /* Both contacts are in the top of the roster (or not). Sort them
      * alphabetically */
-    return compare_roster_contacts_by_alias (a, b);
+    return compare_roster_contacts_by_conversation_time (a, b);
   else if (top_a)
     return -1;
   else
@@ -691,7 +709,7 @@ compare_roster_contacts_with_groups (EmpathyRosterView *self,
 
   if (!tp_strdiff (group_a, group_b))
     /* Same group, compare the contacts */
-    return compare_roster_contacts_by_alias (a, b);
+    return compare_roster_contacts_by_conversation_time (a, b);
 
   /* Sort by group */
   return compare_group_names (group_a, group_b);
diff --git a/src/empathy-roster-window.c b/src/empathy-roster-window.c
index 8599f9e..6249d27 100644
--- a/src/empathy-roster-window.c
+++ b/src/empathy-roster-window.c
@@ -208,7 +208,7 @@ roster_window_auth_display (EmpathyRosterWindow *self,
   gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar), GTK_MESSAGE_QUESTION);
 
   gtk_widget_set_no_show_all (info_bar, TRUE);
-  gtk_box_pack_start (GTK_BOX (self->priv->auth_vbox), info_bar, FALSE, TRUE, 0);
+  gtk_container_add (GTK_CONTAINER (self->priv->auth_vbox), info_bar);
   gtk_widget_show (info_bar);
 
   icon_name = tp_account_get_icon_name (account);
@@ -228,8 +228,8 @@ roster_window_auth_display (EmpathyRosterWindow *self,
   g_free (str);
 
   content_area = gtk_info_bar_get_content_area (GTK_INFO_BAR (info_bar));
-  gtk_box_pack_start (GTK_BOX (content_area), image, FALSE, FALSE, 0);
-  gtk_box_pack_start (GTK_BOX (content_area), label, TRUE, TRUE, 0);
+  gtk_container_add (GTK_CONTAINER (content_area), image);
+  gtk_container_add (GTK_CONTAINER (content_area), label);
 
   image = gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_BUTTON);
   add_button = gtk_button_new ();
@@ -248,7 +248,7 @@ roster_window_auth_display (EmpathyRosterWindow *self,
   gtk_widget_show (action_grid);
 
   action_area = gtk_info_bar_get_action_area (GTK_INFO_BAR (info_bar));
-  gtk_box_pack_start (GTK_BOX (action_area), action_grid, FALSE, FALSE, 0);
+  gtk_container_add (GTK_CONTAINER (action_area), action_grid);
 
   gtk_grid_attach (GTK_GRID (action_grid), add_button, 0, 0, 1, 1);
   gtk_grid_attach (GTK_GRID (action_grid), close_button, 1, 0, 1, 1);
@@ -608,7 +608,7 @@ roster_window_error_create_info_bar (EmpathyRosterWindow *self,
   gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar), message_type);
 
   gtk_widget_set_no_show_all (info_bar, TRUE);
-  gtk_box_pack_start (GTK_BOX (self->priv->errors_vbox), info_bar, FALSE, TRUE, 0);
+  gtk_container_add (GTK_CONTAINER (self->priv->errors_vbox), info_bar);
   gtk_widget_show (info_bar);
 
   icon_name = tp_account_get_icon_name (account);
@@ -623,8 +623,8 @@ roster_window_error_create_info_bar (EmpathyRosterWindow *self,
   gtk_widget_show (label);
 
   content_area = gtk_info_bar_get_content_area (GTK_INFO_BAR (info_bar));
-  gtk_box_pack_start (GTK_BOX (content_area), image, FALSE, FALSE, 0);
-  gtk_box_pack_start (GTK_BOX (content_area), label, TRUE, TRUE, 0);
+  gtk_container_add (GTK_CONTAINER (content_area), image);
+  gtk_container_add (GTK_CONTAINER (content_area), label);
 
   action_area = gtk_info_bar_get_action_area (GTK_INFO_BAR (info_bar));
   gtk_orientable_set_orientation (GTK_ORIENTABLE (action_area),
@@ -879,7 +879,7 @@ roster_window_setup_balance (EmpathyRosterWindow *self,
 
   /* protocol icon */
   image = gtk_image_new ();
-  gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, TRUE, 0);
+  gtk_container_add (GTK_CONTAINER (hbox), image);
   g_object_bind_property (account, "icon-name", image, "icon-name",
       G_BINDING_SYNC_CREATE);
 
@@ -887,14 +887,14 @@ roster_window_setup_balance (EmpathyRosterWindow *self,
   label = gtk_label_new ("");
   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
   gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
-  gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
+  gtk_container_add (GTK_CONTAINER (hbox), label);
   g_object_bind_property (account, "display-name", label, "label",
       G_BINDING_SYNC_CREATE);
 
   /* balance label */
   label = gtk_label_new ("");
   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
-  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
+  gtk_container_add (GTK_CONTAINER (hbox), label);
 
   /* top up button */
   uri = tp_connection_get_balance_uri (conn);
@@ -909,7 +909,7 @@ roster_window_setup_balance (EmpathyRosterWindow *self,
             GTK_ICON_SIZE_SMALL_TOOLBAR));
       gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
       gtk_widget_set_tooltip_text (button, _("Top up account"));
-      gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
+      gtk_container_add (GTK_CONTAINER (hbox), button);
 
       g_signal_connect_data (button, "clicked",
           G_CALLBACK (empathy_url_show),
@@ -917,7 +917,7 @@ roster_window_setup_balance (EmpathyRosterWindow *self,
           0);
     }
 
-  gtk_box_pack_start (GTK_BOX (self->priv->balance_vbox), hbox, FALSE, TRUE, 0);
+  gtk_container_add (GTK_CONTAINER (self->priv->balance_vbox), hbox);
   gtk_widget_show_all (hbox);
 
   g_object_set_data (G_OBJECT (account), "balance-money-label", label);
@@ -2306,14 +2306,6 @@ roster_window_most_available_presence_changed_cb (TpAccountManager *manager,
 }
 
 static void
-show_offline_changed_cb (GSettings *settings,
-    const gchar *key,
-    EmpathyRosterWindow *self)
-{
-  set_notebook_page (self);
-}
-
-static void
 empathy_roster_window_init (EmpathyRosterWindow *self)
 {
   GtkBuilder *gui;
@@ -2429,9 +2421,7 @@ empathy_roster_window_init (EmpathyRosterWindow *self)
   /* Set up presence chooser */
   self->priv->presence_chooser = empathy_presence_chooser_new ();
   gtk_widget_show (self->priv->presence_chooser);
-  gtk_box_pack_start (GTK_BOX (self->priv->presence_toolbar),
-      self->priv->presence_chooser,
-      TRUE, TRUE, 0);
+  gtk_container_add (GTK_CONTAINER (self->priv->presence_toolbar), self->priv->presence_chooser);
 
   /* Set up the throbber */
   self->priv->throbber = gtk_spinner_new ();
@@ -2440,9 +2430,7 @@ empathy_roster_window_init (EmpathyRosterWindow *self)
   g_signal_connect (self->priv->throbber, "button-press-event",
     G_CALLBACK (roster_window_throbber_button_press_event_cb),
     self);
-  gtk_box_pack_start (GTK_BOX (self->priv->presence_toolbar),
-      self->priv->throbber,
-      FALSE, TRUE, 0);
+  gtk_container_add (GTK_CONTAINER (self->priv->presence_toolbar), self->priv->throbber);
 
   self->priv->individual_manager = empathy_individual_manager_dup_singleton ();
 
@@ -2506,7 +2494,7 @@ empathy_roster_window_init (EmpathyRosterWindow *self)
 
   self->priv->chat_window = GTK_WIDGET (empathy_chat_window_new ());
   gtk_widget_show (GTK_WIDGET (self->priv->chat_window) );
-  gtk_box_pack_start (GTK_BOX (chat_vbox), self->priv->chat_window, TRUE, TRUE, 0);
+  gtk_container_add (GTK_CONTAINER (chat_vbox), self->priv->chat_window);
 
   /* Enable event handling */
   self->priv->call_observer = empathy_call_observer_dup_singleton ();


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