3 #include "empathy-roster-contact.h"
5 #include <telepathy-glib/util.h>
7 #include <libempathy/empathy-utils.h>
9 #include <libempathy-gtk/empathy-images.h>
10 #include <libempathy-gtk/empathy-ui-utils.h>
12 G_DEFINE_TYPE (EmpathyRosterContact, empathy_roster_contact, GTK_TYPE_ALIGNMENT)
14 #define AVATAR_SIZE 48
30 static guint signals[LAST_SIGNAL];
33 struct _EmpathyRosterContactPriv
35 FolksIndividual *individual;
38 GtkWidget *first_line_alig;
40 GtkWidget *presence_msg;
41 GtkWidget *presence_icon;
42 GtkWidget *phone_icon;
48 get_alias (EmpathyRosterContact *self)
50 return folks_alias_details_get_alias (FOLKS_ALIAS_DETAILS (
51 self->priv->individual));
55 empathy_roster_contact_get_property (GObject *object,
60 EmpathyRosterContact *self = EMPATHY_ROSTER_CONTACT (object);
64 case PROP_INDIVIDIUAL:
65 g_value_set_object (value, self->priv->individual);
68 g_value_set_boolean (value, self->priv->online);
71 g_value_set_string (value, get_alias (self));
74 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
80 empathy_roster_contact_set_property (GObject *object,
85 EmpathyRosterContact *self = EMPATHY_ROSTER_CONTACT (object);
89 case PROP_INDIVIDIUAL:
90 g_assert (self->priv->individual == NULL); /* construct only */
91 self->priv->individual = g_value_dup_object (value);
94 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
100 avatar_loaded_cb (GObject *source,
101 GAsyncResult *result,
104 TpWeakRef *wr = user_data;
105 EmpathyRosterContact *self;
108 self = tp_weak_ref_dup_object (wr);
112 pixbuf = empathy_pixbuf_avatar_from_individual_scaled_finish (
113 FOLKS_INDIVIDUAL (source), result, NULL);
117 pixbuf = empathy_pixbuf_from_icon_name_sized (
118 EMPATHY_IMAGE_AVATAR_DEFAULT, AVATAR_SIZE);
121 gtk_image_set_from_pixbuf (GTK_IMAGE (self->priv->avatar), pixbuf);
122 g_object_unref (pixbuf);
124 g_object_unref (self);
127 tp_weak_ref_destroy (wr);
131 update_avatar (EmpathyRosterContact *self)
133 empathy_pixbuf_avatar_from_individual_scaled_async (self->priv->individual,
134 AVATAR_SIZE, AVATAR_SIZE, NULL, avatar_loaded_cb,
135 tp_weak_ref_new (self, NULL, NULL));
139 avatar_changed_cb (FolksIndividual *individual,
141 EmpathyRosterContact *self)
143 update_avatar (self);
147 update_alias (EmpathyRosterContact *self)
149 gtk_label_set_text (GTK_LABEL (self->priv->alias), get_alias (self));
151 g_object_notify (G_OBJECT (self), "alias");
155 alias_changed_cb (FolksIndividual *individual,
157 EmpathyRosterContact *self)
163 is_phone (FolksIndividual *individual)
165 const gchar * const *types;
167 types = empathy_individual_get_client_types (individual);
171 if (g_strv_length ((GStrv) types) <= 0)
174 return !tp_strdiff (types[0], "phone");
178 update_presence_msg (EmpathyRosterContact *self)
182 msg = folks_presence_details_get_presence_message (
183 FOLKS_PRESENCE_DETAILS (self->priv->individual));
185 if (tp_str_empty (msg))
187 /* Just display the alias in the center of the row */
188 gtk_alignment_set (GTK_ALIGNMENT (self->priv->first_line_alig),
191 gtk_widget_hide (self->priv->presence_msg);
195 gtk_label_set_text (GTK_LABEL (self->priv->presence_msg), msg);
197 gtk_alignment_set (GTK_ALIGNMENT (self->priv->first_line_alig),
199 gtk_misc_set_alignment (GTK_MISC (self->priv->presence_msg), 0, 0.25);
201 gtk_widget_show (self->priv->presence_msg);
204 gtk_widget_set_visible (self->priv->phone_icon,
205 is_phone (self->priv->individual));
209 presence_message_changed_cb (FolksIndividual *individual,
211 EmpathyRosterContact *self)
213 update_presence_msg (self);
217 update_presence_icon (EmpathyRosterContact *self)
221 icon = empathy_icon_name_for_individual (self->priv->individual);
223 gtk_image_set_from_icon_name (GTK_IMAGE (self->priv->presence_icon), icon,
228 update_online (EmpathyRosterContact *self)
230 FolksPresenceType presence;
233 presence = folks_presence_details_get_presence_type (
234 FOLKS_PRESENCE_DETAILS (self->priv->individual));
238 case FOLKS_PRESENCE_TYPE_UNSET:
239 case FOLKS_PRESENCE_TYPE_OFFLINE:
240 case FOLKS_PRESENCE_TYPE_UNKNOWN:
241 case FOLKS_PRESENCE_TYPE_ERROR:
245 case FOLKS_PRESENCE_TYPE_AVAILABLE:
246 case FOLKS_PRESENCE_TYPE_AWAY:
247 case FOLKS_PRESENCE_TYPE_EXTENDED_AWAY:
248 case FOLKS_PRESENCE_TYPE_HIDDEN:
249 case FOLKS_PRESENCE_TYPE_BUSY:
254 g_warning ("Unknown FolksPresenceType: %d", presence);
258 if (self->priv->online == online)
261 self->priv->online = online;
262 g_object_notify (G_OBJECT (self), "online");
266 presence_status_changed_cb (FolksIndividual *individual,
268 EmpathyRosterContact *self)
270 update_presence_icon (self);
271 update_online (self);
275 empathy_roster_contact_constructed (GObject *object)
277 EmpathyRosterContact *self = EMPATHY_ROSTER_CONTACT (object);
278 void (*chain_up) (GObject *) =
279 ((GObjectClass *) empathy_roster_contact_parent_class)->constructed;
281 if (chain_up != NULL)
284 g_assert (FOLKS_IS_INDIVIDUAL (self->priv->individual));
286 tp_g_signal_connect_object (self->priv->individual, "notify::avatar",
287 G_CALLBACK (avatar_changed_cb), self, 0);
288 tp_g_signal_connect_object (self->priv->individual, "notify::alias",
289 G_CALLBACK (alias_changed_cb), self, 0);
290 tp_g_signal_connect_object (self->priv->individual,
291 "notify::presence-message",
292 G_CALLBACK (presence_message_changed_cb), self, 0);
293 tp_g_signal_connect_object (self->priv->individual, "notify::presence-status",
294 G_CALLBACK (presence_status_changed_cb), self, 0);
296 update_avatar (self);
298 update_presence_msg (self);
299 update_presence_icon (self);
301 update_online (self);
305 empathy_roster_contact_dispose (GObject *object)
307 EmpathyRosterContact *self = EMPATHY_ROSTER_CONTACT (object);
308 void (*chain_up) (GObject *) =
309 ((GObjectClass *) empathy_roster_contact_parent_class)->dispose;
311 g_clear_object (&self->priv->individual);
313 if (chain_up != NULL)
318 empathy_roster_contact_finalize (GObject *object)
320 //EmpathyRosterContact *self = EMPATHY_ROSTER_CONTACT (object);
321 void (*chain_up) (GObject *) =
322 ((GObjectClass *) empathy_roster_contact_parent_class)->finalize;
324 if (chain_up != NULL)
329 empathy_roster_contact_class_init (
330 EmpathyRosterContactClass *klass)
332 GObjectClass *oclass = G_OBJECT_CLASS (klass);
335 oclass->get_property = empathy_roster_contact_get_property;
336 oclass->set_property = empathy_roster_contact_set_property;
337 oclass->constructed = empathy_roster_contact_constructed;
338 oclass->dispose = empathy_roster_contact_dispose;
339 oclass->finalize = empathy_roster_contact_finalize;
341 spec = g_param_spec_object ("individual", "Individual",
343 FOLKS_TYPE_INDIVIDUAL,
344 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
345 g_object_class_install_property (oclass, PROP_INDIVIDIUAL, spec);
347 spec = g_param_spec_boolean ("online", "Online",
348 "TRUE if Individual is online",
350 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
351 g_object_class_install_property (oclass, PROP_ONLINE, spec);
353 spec = g_param_spec_string ("alias", "Alias",
354 "The Alias of the individual displayed in the widget",
356 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
357 g_object_class_install_property (oclass, PROP_ALIAS, spec);
359 g_type_class_add_private (klass, sizeof (EmpathyRosterContactPriv));
363 empathy_roster_contact_init (EmpathyRosterContact *self)
365 GtkWidget *main_box, *box, *first_line_box;
366 GtkStyleContext *context;
368 self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
369 EMPATHY_TYPE_ROSTER_CONTACT, EmpathyRosterContactPriv);
371 gtk_widget_set_size_request (GTK_WIDGET (self), 300, 64);
373 main_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
376 self->priv->avatar = gtk_image_new ();
378 gtk_box_pack_start (GTK_BOX (main_box), self->priv->avatar, FALSE, FALSE, 0);
379 gtk_widget_show (self->priv->avatar);
381 box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
383 /* Alias and phone icon */
384 self->priv->first_line_alig = gtk_alignment_new (0, 0.5, 1, 1);
385 first_line_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
387 self->priv->alias = gtk_label_new (NULL);
388 gtk_box_pack_start (GTK_BOX (first_line_box), self->priv->alias,
390 gtk_widget_show (self->priv->alias);
392 self->priv->phone_icon = gtk_image_new_from_icon_name ("phone-symbolic",
394 gtk_misc_set_alignment (GTK_MISC (self->priv->phone_icon), 0, 0.5);
395 gtk_box_pack_start (GTK_BOX (first_line_box), self->priv->phone_icon,
398 gtk_container_add (GTK_CONTAINER (self->priv->first_line_alig),
400 gtk_widget_show (self->priv->first_line_alig);
402 gtk_box_pack_start (GTK_BOX (box), self->priv->first_line_alig,
404 gtk_widget_show (first_line_box);
406 gtk_box_pack_start (GTK_BOX (main_box), box, TRUE, TRUE, 0);
407 gtk_widget_show (box);
410 self->priv->presence_msg = gtk_label_new (NULL);
411 gtk_box_pack_start (GTK_BOX (box), self->priv->presence_msg, TRUE, TRUE, 0);
412 gtk_widget_show (self->priv->presence_msg);
414 context = gtk_widget_get_style_context (self->priv->presence_msg);
415 gtk_style_context_add_class (context, GTK_STYLE_CLASS_DIM_LABEL);
418 self->priv->presence_icon = gtk_image_new ();
420 gtk_box_pack_start (GTK_BOX (main_box), self->priv->presence_icon,
422 gtk_widget_show (self->priv->presence_icon);
424 gtk_container_add (GTK_CONTAINER (self), main_box);
425 gtk_widget_show (main_box);
429 empathy_roster_contact_new (FolksIndividual *individual)
431 g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL);
433 return g_object_new (EMPATHY_TYPE_ROSTER_CONTACT,
434 "individual", individual,
443 empathy_roster_contact_get_individual (EmpathyRosterContact *self)
445 return self->priv->individual;
449 empathy_roster_contact_is_online (EmpathyRosterContact *self)
451 return self->priv->online;