From: Frédéric Péters Date: Sun, 3 May 2015 12:35:29 +0000 (+0200) Subject: sort contacts by most recent event X-Git-Url: https://git.0d.be/?p=empathy.git;a=commitdiff_plain;h=HEAD sort contacts by most recent event --- diff --git a/libempathy-gtk/empathy-roster-contact.c b/libempathy-gtk/empathy-roster-contact.c index df57a87f..d98ca13f 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, @@ -138,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) { @@ -291,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; @@ -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 6e05959f..1dc463a7 100644 --- a/libempathy-gtk/empathy-roster-contact.h +++ b/libempathy-gtk/empathy-roster-contact.h @@ -3,6 +3,7 @@ #include #include +#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 0dab3ba6..e463bd9f 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); @@ -625,6 +629,20 @@ contact_in_top (EmpathyRosterView *self, return FALSE; } +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);