2 #include "empathy-roster-contact.h"
4 #include <glib/gi18n-lib.h>
6 #include "empathy-images.h"
7 #include "empathy-ui-utils.h"
8 #include "empathy-utils.h"
10 G_DEFINE_TYPE (EmpathyRosterContact, empathy_roster_contact, GTK_TYPE_ALIGNMENT)
12 #define AVATAR_SIZE 48
29 static guint signals[LAST_SIGNAL];
32 struct _EmpathyRosterContactPriv
34 FolksIndividual *individual;
38 GtkWidget *first_line_alig;
40 GtkWidget *presence_msg;
41 GtkWidget *presence_icon;
42 GtkWidget *phone_icon;
44 /* If not NULL, used instead of the individual's presence icon */
51 get_alias (EmpathyRosterContact *self)
53 return folks_alias_details_get_alias (FOLKS_ALIAS_DETAILS (
54 self->priv->individual));
58 empathy_roster_contact_get_property (GObject *object,
63 EmpathyRosterContact *self = EMPATHY_ROSTER_CONTACT (object);
67 case PROP_INDIVIDIUAL:
68 g_value_set_object (value, self->priv->individual);
71 g_value_set_string (value, self->priv->group);
74 g_value_set_boolean (value, self->priv->online);
77 g_value_set_string (value, get_alias (self));
80 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
86 empathy_roster_contact_set_property (GObject *object,
91 EmpathyRosterContact *self = EMPATHY_ROSTER_CONTACT (object);
95 case PROP_INDIVIDIUAL:
96 g_assert (self->priv->individual == NULL); /* construct only */
97 self->priv->individual = g_value_dup_object (value);
100 g_assert (self->priv->group == NULL); /* construct only */
101 self->priv->group = g_value_dup_string (value);
104 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
110 avatar_loaded_cb (GObject *source,
111 GAsyncResult *result,
114 TpWeakRef *wr = user_data;
115 EmpathyRosterContact *self;
118 self = tp_weak_ref_dup_object (wr);
122 pixbuf = empathy_pixbuf_avatar_from_individual_scaled_finish (
123 FOLKS_INDIVIDUAL (source), result, NULL);
127 pixbuf = empathy_pixbuf_from_icon_name_sized (
128 EMPATHY_IMAGE_AVATAR_DEFAULT, AVATAR_SIZE);
131 gtk_image_set_from_pixbuf (GTK_IMAGE (self->priv->avatar), pixbuf);
132 g_object_unref (pixbuf);
134 g_object_unref (self);
137 tp_weak_ref_destroy (wr);
141 update_avatar (EmpathyRosterContact *self)
143 empathy_pixbuf_avatar_from_individual_scaled_async (self->priv->individual,
144 AVATAR_SIZE, AVATAR_SIZE, NULL, avatar_loaded_cb,
145 tp_weak_ref_new (self, NULL, NULL));
149 avatar_changed_cb (FolksIndividual *individual,
151 EmpathyRosterContact *self)
153 update_avatar (self);
157 update_alias (EmpathyRosterContact *self)
159 gtk_label_set_text (GTK_LABEL (self->priv->alias), get_alias (self));
161 g_object_notify (G_OBJECT (self), "alias");
165 alias_changed_cb (FolksIndividual *individual,
167 EmpathyRosterContact *self)
173 update_presence_msg (EmpathyRosterContact *self)
178 msg = folks_presence_details_get_presence_message (
179 FOLKS_PRESENCE_DETAILS (self->priv->individual));
181 if (tp_str_empty (msg))
183 /* Just display the alias in the center of the row */
184 gtk_alignment_set (GTK_ALIGNMENT (self->priv->first_line_alig),
187 gtk_widget_hide (self->priv->presence_msg);
191 FolksPresenceType type;
193 type = folks_presence_details_get_presence_type (
194 FOLKS_PRESENCE_DETAILS (self->priv->individual));
195 if (type == FOLKS_PRESENCE_TYPE_ERROR)
199 /* Add a prefix explaining that something goes wrong when trying to
200 * fetch contact's presence. */
201 tmp = g_strdup_printf (_("Server cannot find contact: %s"), msg);
202 gtk_label_set_text (GTK_LABEL (self->priv->presence_msg), tmp);
208 gtk_label_set_text (GTK_LABEL (self->priv->presence_msg), msg);
211 gtk_alignment_set (GTK_ALIGNMENT (self->priv->first_line_alig),
213 gtk_misc_set_alignment (GTK_MISC (self->priv->presence_msg), 0, 0.25);
215 gtk_widget_show (self->priv->presence_msg);
218 types = (GStrv) empathy_individual_get_client_types (self->priv->individual);
220 gtk_widget_set_visible (self->priv->phone_icon,
221 empathy_client_types_contains_mobile_device (types));
225 presence_message_changed_cb (FolksIndividual *individual,
227 EmpathyRosterContact *self)
229 update_presence_msg (self);
233 update_presence_icon (EmpathyRosterContact *self)
237 if (self->priv->event_icon == NULL)
238 icon = empathy_icon_name_for_individual (self->priv->individual);
240 icon = self->priv->event_icon;
242 gtk_image_set_from_icon_name (GTK_IMAGE (self->priv->presence_icon), icon,
247 update_online (EmpathyRosterContact *self)
249 FolksPresenceType presence;
252 presence = folks_presence_details_get_presence_type (
253 FOLKS_PRESENCE_DETAILS (self->priv->individual));
257 case FOLKS_PRESENCE_TYPE_UNSET:
258 case FOLKS_PRESENCE_TYPE_OFFLINE:
259 case FOLKS_PRESENCE_TYPE_UNKNOWN:
260 case FOLKS_PRESENCE_TYPE_ERROR:
264 case FOLKS_PRESENCE_TYPE_AVAILABLE:
265 case FOLKS_PRESENCE_TYPE_AWAY:
266 case FOLKS_PRESENCE_TYPE_EXTENDED_AWAY:
267 case FOLKS_PRESENCE_TYPE_HIDDEN:
268 case FOLKS_PRESENCE_TYPE_BUSY:
273 g_warning ("Unknown FolksPresenceType: %d", presence);
277 if (self->priv->online == online)
280 self->priv->online = online;
281 g_object_notify (G_OBJECT (self), "online");
285 presence_status_changed_cb (FolksIndividual *individual,
287 EmpathyRosterContact *self)
289 update_presence_icon (self);
290 update_online (self);
294 empathy_roster_contact_constructed (GObject *object)
296 EmpathyRosterContact *self = EMPATHY_ROSTER_CONTACT (object);
297 void (*chain_up) (GObject *) =
298 ((GObjectClass *) empathy_roster_contact_parent_class)->constructed;
300 if (chain_up != NULL)
303 g_assert (FOLKS_IS_INDIVIDUAL (self->priv->individual));
305 tp_g_signal_connect_object (self->priv->individual, "notify::avatar",
306 G_CALLBACK (avatar_changed_cb), self, 0);
307 tp_g_signal_connect_object (self->priv->individual, "notify::alias",
308 G_CALLBACK (alias_changed_cb), self, 0);
309 tp_g_signal_connect_object (self->priv->individual,
310 "notify::presence-message",
311 G_CALLBACK (presence_message_changed_cb), self, 0);
312 tp_g_signal_connect_object (self->priv->individual, "notify::presence-status",
313 G_CALLBACK (presence_status_changed_cb), self, 0);
315 update_avatar (self);
317 update_presence_msg (self);
318 update_presence_icon (self);
320 update_online (self);
324 empathy_roster_contact_dispose (GObject *object)
326 EmpathyRosterContact *self = EMPATHY_ROSTER_CONTACT (object);
327 void (*chain_up) (GObject *) =
328 ((GObjectClass *) empathy_roster_contact_parent_class)->dispose;
330 g_clear_object (&self->priv->individual);
332 if (chain_up != NULL)
337 empathy_roster_contact_finalize (GObject *object)
339 EmpathyRosterContact *self = EMPATHY_ROSTER_CONTACT (object);
340 void (*chain_up) (GObject *) =
341 ((GObjectClass *) empathy_roster_contact_parent_class)->finalize;
343 g_free (self->priv->group);
344 g_free (self->priv->event_icon);
346 if (chain_up != NULL)
351 empathy_roster_contact_class_init (
352 EmpathyRosterContactClass *klass)
354 GObjectClass *oclass = G_OBJECT_CLASS (klass);
357 oclass->get_property = empathy_roster_contact_get_property;
358 oclass->set_property = empathy_roster_contact_set_property;
359 oclass->constructed = empathy_roster_contact_constructed;
360 oclass->dispose = empathy_roster_contact_dispose;
361 oclass->finalize = empathy_roster_contact_finalize;
363 spec = g_param_spec_object ("individual", "Individual",
365 FOLKS_TYPE_INDIVIDUAL,
366 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
367 g_object_class_install_property (oclass, PROP_INDIVIDIUAL, spec);
369 spec = g_param_spec_string ("group", "Group",
370 "Group of this widget, or NULL",
372 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
373 g_object_class_install_property (oclass, PROP_GROUP, spec);
375 spec = g_param_spec_boolean ("online", "Online",
376 "TRUE if Individual is online",
378 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
379 g_object_class_install_property (oclass, PROP_ONLINE, spec);
381 spec = g_param_spec_string ("alias", "Alias",
382 "The Alias of the individual displayed in the widget",
384 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
385 g_object_class_install_property (oclass, PROP_ALIAS, spec);
387 g_type_class_add_private (klass, sizeof (EmpathyRosterContactPriv));
391 empathy_roster_contact_init (EmpathyRosterContact *self)
393 GtkWidget *main_box, *box, *first_line_box;
394 GtkStyleContext *context;
396 self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
397 EMPATHY_TYPE_ROSTER_CONTACT, EmpathyRosterContactPriv);
399 main_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
402 self->priv->avatar = gtk_image_new ();
404 gtk_widget_set_size_request (self->priv->avatar, AVATAR_SIZE, AVATAR_SIZE);
406 gtk_box_pack_start (GTK_BOX (main_box), self->priv->avatar, FALSE, FALSE, 0);
407 gtk_widget_show (self->priv->avatar);
409 box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
411 /* Alias and phone icon */
412 self->priv->first_line_alig = gtk_alignment_new (0, 0.5, 1, 1);
413 first_line_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
415 self->priv->alias = gtk_label_new (NULL);
416 gtk_label_set_ellipsize (GTK_LABEL (self->priv->alias), PANGO_ELLIPSIZE_END);
417 gtk_box_pack_start (GTK_BOX (first_line_box), self->priv->alias,
419 gtk_misc_set_alignment (GTK_MISC (self->priv->alias), 0, 0.5);
420 gtk_widget_show (self->priv->alias);
422 self->priv->phone_icon = gtk_image_new_from_icon_name ("phone-symbolic",
424 gtk_misc_set_alignment (GTK_MISC (self->priv->phone_icon), 0, 0.5);
425 gtk_box_pack_start (GTK_BOX (first_line_box), self->priv->phone_icon,
428 gtk_container_add (GTK_CONTAINER (self->priv->first_line_alig),
430 gtk_widget_show (self->priv->first_line_alig);
432 gtk_box_pack_start (GTK_BOX (box), self->priv->first_line_alig,
434 gtk_widget_show (first_line_box);
436 gtk_box_pack_start (GTK_BOX (main_box), box, TRUE, TRUE, 0);
437 gtk_widget_show (box);
440 self->priv->presence_msg = gtk_label_new (NULL);
441 gtk_label_set_ellipsize (GTK_LABEL (self->priv->presence_msg),
442 PANGO_ELLIPSIZE_END);
443 gtk_box_pack_start (GTK_BOX (box), self->priv->presence_msg, TRUE, TRUE, 0);
444 gtk_widget_show (self->priv->presence_msg);
446 context = gtk_widget_get_style_context (self->priv->presence_msg);
447 gtk_style_context_add_class (context, GTK_STYLE_CLASS_DIM_LABEL);
450 self->priv->presence_icon = gtk_image_new ();
452 gtk_box_pack_start (GTK_BOX (main_box), self->priv->presence_icon,
454 gtk_widget_show (self->priv->presence_icon);
456 gtk_container_add (GTK_CONTAINER (self), main_box);
457 gtk_widget_show (main_box);
461 empathy_roster_contact_new (FolksIndividual *individual,
464 g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL);
466 return g_object_new (EMPATHY_TYPE_ROSTER_CONTACT,
467 "individual", individual,
477 empathy_roster_contact_get_individual (EmpathyRosterContact *self)
479 return self->priv->individual;
483 empathy_roster_contact_is_online (EmpathyRosterContact *self)
485 return self->priv->online;
489 empathy_roster_contact_get_group (EmpathyRosterContact *self)
491 return self->priv->group;
495 empathy_roster_contact_set_event_icon (EmpathyRosterContact *self,
498 if (!tp_strdiff (self->priv->event_icon, icon))
501 g_free (self->priv->event_icon);
502 self->priv->event_icon = g_strdup (icon);
504 update_presence_icon (self);
508 empathy_roster_contact_get_avatar_pixbuf (EmpathyRosterContact *self)
510 return gtk_image_get_pixbuf (GTK_IMAGE (self->priv->avatar));