3 #include "empathy-roster-contact.h"
5 #include <telepathy-glib/telepathy-glib.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
31 static guint signals[LAST_SIGNAL];
34 struct _EmpathyRosterContactPriv
36 FolksIndividual *individual;
40 GtkWidget *first_line_alig;
42 GtkWidget *presence_msg;
43 GtkWidget *presence_icon;
44 GtkWidget *phone_icon;
46 /* If not NULL, used instead of the individual's presence icon */
53 get_alias (EmpathyRosterContact *self)
55 return folks_alias_details_get_alias (FOLKS_ALIAS_DETAILS (
56 self->priv->individual));
60 empathy_roster_contact_get_property (GObject *object,
65 EmpathyRosterContact *self = EMPATHY_ROSTER_CONTACT (object);
69 case PROP_INDIVIDIUAL:
70 g_value_set_object (value, self->priv->individual);
73 g_value_set_string (value, self->priv->group);
76 g_value_set_boolean (value, self->priv->online);
79 g_value_set_string (value, get_alias (self));
82 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
88 empathy_roster_contact_set_property (GObject *object,
93 EmpathyRosterContact *self = EMPATHY_ROSTER_CONTACT (object);
97 case PROP_INDIVIDIUAL:
98 g_assert (self->priv->individual == NULL); /* construct only */
99 self->priv->individual = g_value_dup_object (value);
102 g_assert (self->priv->group == NULL); /* construct only */
103 self->priv->group = g_value_dup_string (value);
106 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
112 avatar_loaded_cb (GObject *source,
113 GAsyncResult *result,
116 TpWeakRef *wr = user_data;
117 EmpathyRosterContact *self;
120 self = tp_weak_ref_dup_object (wr);
124 pixbuf = empathy_pixbuf_avatar_from_individual_scaled_finish (
125 FOLKS_INDIVIDUAL (source), result, NULL);
129 pixbuf = empathy_pixbuf_from_icon_name_sized (
130 EMPATHY_IMAGE_AVATAR_DEFAULT, AVATAR_SIZE);
133 gtk_image_set_from_pixbuf (GTK_IMAGE (self->priv->avatar), pixbuf);
134 g_object_unref (pixbuf);
136 g_object_unref (self);
139 tp_weak_ref_destroy (wr);
143 update_avatar (EmpathyRosterContact *self)
145 empathy_pixbuf_avatar_from_individual_scaled_async (self->priv->individual,
146 AVATAR_SIZE, AVATAR_SIZE, NULL, avatar_loaded_cb,
147 tp_weak_ref_new (self, NULL, NULL));
151 avatar_changed_cb (FolksIndividual *individual,
153 EmpathyRosterContact *self)
155 update_avatar (self);
159 update_alias (EmpathyRosterContact *self)
161 gtk_label_set_text (GTK_LABEL (self->priv->alias), get_alias (self));
163 g_object_notify (G_OBJECT (self), "alias");
167 alias_changed_cb (FolksIndividual *individual,
169 EmpathyRosterContact *self)
175 is_phone (FolksIndividual *individual)
177 const gchar * const *types;
179 types = empathy_individual_get_client_types (individual);
183 if (g_strv_length ((GStrv) types) <= 0)
186 return !tp_strdiff (types[0], "phone");
190 update_presence_msg (EmpathyRosterContact *self)
194 msg = folks_presence_details_get_presence_message (
195 FOLKS_PRESENCE_DETAILS (self->priv->individual));
197 if (tp_str_empty (msg))
199 /* Just display the alias in the center of the row */
200 gtk_alignment_set (GTK_ALIGNMENT (self->priv->first_line_alig),
203 gtk_widget_hide (self->priv->presence_msg);
207 gtk_label_set_text (GTK_LABEL (self->priv->presence_msg), msg);
209 gtk_alignment_set (GTK_ALIGNMENT (self->priv->first_line_alig),
211 gtk_misc_set_alignment (GTK_MISC (self->priv->presence_msg), 0, 0.25);
213 gtk_widget_show (self->priv->presence_msg);
216 gtk_widget_set_visible (self->priv->phone_icon,
217 is_phone (self->priv->individual));
221 presence_message_changed_cb (FolksIndividual *individual,
223 EmpathyRosterContact *self)
225 update_presence_msg (self);
229 update_presence_icon (EmpathyRosterContact *self)
233 if (self->priv->event_icon == NULL)
234 icon = empathy_icon_name_for_individual (self->priv->individual);
236 icon = self->priv->event_icon;
238 gtk_image_set_from_icon_name (GTK_IMAGE (self->priv->presence_icon), icon,
243 update_online (EmpathyRosterContact *self)
245 FolksPresenceType presence;
248 presence = folks_presence_details_get_presence_type (
249 FOLKS_PRESENCE_DETAILS (self->priv->individual));
253 case FOLKS_PRESENCE_TYPE_UNSET:
254 case FOLKS_PRESENCE_TYPE_OFFLINE:
255 case FOLKS_PRESENCE_TYPE_UNKNOWN:
256 case FOLKS_PRESENCE_TYPE_ERROR:
260 case FOLKS_PRESENCE_TYPE_AVAILABLE:
261 case FOLKS_PRESENCE_TYPE_AWAY:
262 case FOLKS_PRESENCE_TYPE_EXTENDED_AWAY:
263 case FOLKS_PRESENCE_TYPE_HIDDEN:
264 case FOLKS_PRESENCE_TYPE_BUSY:
269 g_warning ("Unknown FolksPresenceType: %d", presence);
273 if (self->priv->online == online)
276 self->priv->online = online;
277 g_object_notify (G_OBJECT (self), "online");
281 presence_status_changed_cb (FolksIndividual *individual,
283 EmpathyRosterContact *self)
285 update_presence_icon (self);
286 update_online (self);
290 empathy_roster_contact_constructed (GObject *object)
292 EmpathyRosterContact *self = EMPATHY_ROSTER_CONTACT (object);
293 void (*chain_up) (GObject *) =
294 ((GObjectClass *) empathy_roster_contact_parent_class)->constructed;
296 if (chain_up != NULL)
299 g_assert (FOLKS_IS_INDIVIDUAL (self->priv->individual));
301 tp_g_signal_connect_object (self->priv->individual, "notify::avatar",
302 G_CALLBACK (avatar_changed_cb), self, 0);
303 tp_g_signal_connect_object (self->priv->individual, "notify::alias",
304 G_CALLBACK (alias_changed_cb), self, 0);
305 tp_g_signal_connect_object (self->priv->individual,
306 "notify::presence-message",
307 G_CALLBACK (presence_message_changed_cb), self, 0);
308 tp_g_signal_connect_object (self->priv->individual, "notify::presence-status",
309 G_CALLBACK (presence_status_changed_cb), self, 0);
311 update_avatar (self);
313 update_presence_msg (self);
314 update_presence_icon (self);
316 update_online (self);
320 empathy_roster_contact_dispose (GObject *object)
322 EmpathyRosterContact *self = EMPATHY_ROSTER_CONTACT (object);
323 void (*chain_up) (GObject *) =
324 ((GObjectClass *) empathy_roster_contact_parent_class)->dispose;
326 g_clear_object (&self->priv->individual);
328 if (chain_up != NULL)
333 empathy_roster_contact_finalize (GObject *object)
335 EmpathyRosterContact *self = EMPATHY_ROSTER_CONTACT (object);
336 void (*chain_up) (GObject *) =
337 ((GObjectClass *) empathy_roster_contact_parent_class)->finalize;
339 g_free (self->priv->group);
340 g_free (self->priv->event_icon);
342 if (chain_up != NULL)
347 empathy_roster_contact_class_init (
348 EmpathyRosterContactClass *klass)
350 GObjectClass *oclass = G_OBJECT_CLASS (klass);
353 oclass->get_property = empathy_roster_contact_get_property;
354 oclass->set_property = empathy_roster_contact_set_property;
355 oclass->constructed = empathy_roster_contact_constructed;
356 oclass->dispose = empathy_roster_contact_dispose;
357 oclass->finalize = empathy_roster_contact_finalize;
359 spec = g_param_spec_object ("individual", "Individual",
361 FOLKS_TYPE_INDIVIDUAL,
362 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
363 g_object_class_install_property (oclass, PROP_INDIVIDIUAL, spec);
365 spec = g_param_spec_string ("group", "Group",
366 "Group of this widget, or NULL",
368 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
369 g_object_class_install_property (oclass, PROP_GROUP, spec);
371 spec = g_param_spec_boolean ("online", "Online",
372 "TRUE if Individual is online",
374 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
375 g_object_class_install_property (oclass, PROP_ONLINE, spec);
377 spec = g_param_spec_string ("alias", "Alias",
378 "The Alias of the individual displayed in the widget",
380 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
381 g_object_class_install_property (oclass, PROP_ALIAS, spec);
383 g_type_class_add_private (klass, sizeof (EmpathyRosterContactPriv));
387 empathy_roster_contact_init (EmpathyRosterContact *self)
389 GtkWidget *main_box, *box, *first_line_box;
390 GtkStyleContext *context;
392 self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
393 EMPATHY_TYPE_ROSTER_CONTACT, EmpathyRosterContactPriv);
395 main_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
398 self->priv->avatar = gtk_image_new ();
400 gtk_widget_set_size_request (self->priv->avatar, AVATAR_SIZE, AVATAR_SIZE);
402 gtk_box_pack_start (GTK_BOX (main_box), self->priv->avatar, FALSE, FALSE, 0);
403 gtk_widget_show (self->priv->avatar);
405 box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
407 /* Alias and phone icon */
408 self->priv->first_line_alig = gtk_alignment_new (0, 0.5, 1, 1);
409 first_line_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
411 self->priv->alias = gtk_label_new (NULL);
412 gtk_label_set_ellipsize (GTK_LABEL (self->priv->alias), PANGO_ELLIPSIZE_END);
413 gtk_box_pack_start (GTK_BOX (first_line_box), self->priv->alias,
415 gtk_misc_set_alignment (GTK_MISC (self->priv->alias), 0, 0.5);
416 gtk_widget_show (self->priv->alias);
418 self->priv->phone_icon = gtk_image_new_from_icon_name ("phone-symbolic",
420 gtk_misc_set_alignment (GTK_MISC (self->priv->phone_icon), 0, 0.5);
421 gtk_box_pack_start (GTK_BOX (first_line_box), self->priv->phone_icon,
424 gtk_container_add (GTK_CONTAINER (self->priv->first_line_alig),
426 gtk_widget_show (self->priv->first_line_alig);
428 gtk_box_pack_start (GTK_BOX (box), self->priv->first_line_alig,
430 gtk_widget_show (first_line_box);
432 gtk_box_pack_start (GTK_BOX (main_box), box, TRUE, TRUE, 0);
433 gtk_widget_show (box);
436 self->priv->presence_msg = gtk_label_new (NULL);
437 gtk_label_set_ellipsize (GTK_LABEL (self->priv->presence_msg),
438 PANGO_ELLIPSIZE_END);
439 gtk_box_pack_start (GTK_BOX (box), self->priv->presence_msg, TRUE, TRUE, 0);
440 gtk_widget_show (self->priv->presence_msg);
442 context = gtk_widget_get_style_context (self->priv->presence_msg);
443 gtk_style_context_add_class (context, GTK_STYLE_CLASS_DIM_LABEL);
446 self->priv->presence_icon = gtk_image_new ();
448 gtk_box_pack_start (GTK_BOX (main_box), self->priv->presence_icon,
450 gtk_widget_show (self->priv->presence_icon);
452 gtk_container_add (GTK_CONTAINER (self), main_box);
453 gtk_widget_show (main_box);
457 empathy_roster_contact_new (FolksIndividual *individual,
460 g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL);
462 return g_object_new (EMPATHY_TYPE_ROSTER_CONTACT,
463 "individual", individual,
473 empathy_roster_contact_get_individual (EmpathyRosterContact *self)
475 return self->priv->individual;
479 empathy_roster_contact_is_online (EmpathyRosterContact *self)
481 return self->priv->online;
485 empathy_roster_contact_get_group (EmpathyRosterContact *self)
487 return self->priv->group;
491 empathy_roster_contact_set_event_icon (EmpathyRosterContact *self,
494 if (!tp_strdiff (self->priv->event_icon, icon))
497 g_free (self->priv->event_icon);
498 self->priv->event_icon = g_strdup (icon);
500 update_presence_icon (self);
504 empathy_roster_contact_get_avatar_pixbuf (EmpathyRosterContact *self)
506 return gtk_image_get_pixbuf (GTK_IMAGE (self->priv->avatar));