]> git.0d.be Git - empathy.git/blobdiff - libempathy-gtk/empathy-individual-widget.c
Merge branch 'sasl'
[empathy.git] / libempathy-gtk / empathy-individual-widget.c
index a42c5a999bd8057c2e1d07051c3c2d0d2c67b4bd..863ce021e31e764f6827592960ad8289ff8d6cd1 100644 (file)
@@ -45,7 +45,6 @@
 #include "empathy-groups-widget.h"
 #include "empathy-gtk-enum-types.h"
 #include "empathy-individual-widget.h"
-#include "empathy-kludge-label.h"
 #include "empathy-string-parser.h"
 #include "empathy-ui-utils.h"
 
@@ -79,7 +78,7 @@ typedef struct {
   EmpathyIndividualWidgetFlags flags;
 
   /* weak pointer to the contact whose contact details we're displaying */
-  TpContact *contact_info_contact;
+  TpContact *contact;
 
   /* unowned Persona (borrowed from priv->individual) -> GtkTable child */
   GHashTable *persona_tables;
@@ -107,6 +106,9 @@ typedef struct {
   /* Groups */
   GtkWidget *groups_widget;
 
+  /* Client types */
+  GtkWidget *hbox_client_types;
+
   /* Details */
   GtkWidget *vbox_details;
   GtkWidget *table_details;
@@ -123,6 +125,9 @@ enum {
   PROP_FLAGS
 };
 
+static void client_types_update (EmpathyIndividualWidget *self);
+static void remove_weak_contact (EmpathyIndividualWidget *self);
+
 static void
 details_set_up (EmpathyIndividualWidget *self)
 {
@@ -194,6 +199,53 @@ contact_info_field_cmp (TpContactInfoField *field1,
   return contact_info_field_name_cmp (field1->field_name, field2->field_name);
 }
 
+static void
+update_weak_contact (EmpathyIndividualWidget *self)
+{
+  EmpathyIndividualWidgetPriv *priv = GET_PRIV (self);
+  TpContact *tp_contact = NULL;
+
+  remove_weak_contact (self);
+
+  if (priv->individual != NULL)
+    {
+      /* FIXME: We take the most available TpContact we find and only
+       * use its details. It would be a lot better if we would get the
+       * details for every TpContact in the Individual and merge them
+       * all, but that requires vCard support in libfolks for it to
+       * not be hideously complex.  (bgo#627399) */
+      GList *personas, *l;
+      FolksPresenceType presence_type = FOLKS_PRESENCE_TYPE_UNSET;
+
+      personas = folks_individual_get_personas (priv->individual);
+      for (l = personas; l != NULL; l = l->next)
+        {
+          FolksPresence *presence;
+
+          /* We only want personas which implement FolksPresence */
+          if (!FOLKS_IS_PRESENCE (l->data))
+            continue;
+
+          presence = FOLKS_PRESENCE (l->data);
+
+          if (folks_presence_typecmp (folks_presence_get_presence_type (presence),
+                  presence_type) > 0
+              && TPF_IS_PERSONA (presence))
+            {
+              presence_type = folks_presence_get_presence_type (presence);
+              tp_contact = tpf_persona_get_contact (TPF_PERSONA (l->data));
+            }
+        }
+    }
+
+  if (tp_contact != NULL)
+    {
+      priv->contact = tp_contact;
+      g_object_add_weak_pointer (G_OBJECT (tp_contact),
+          (gpointer *) &priv->contact);
+    }
+}
+
 typedef struct {
   EmpathyIndividualWidget *widget; /* weak */
   TpContact *contact; /* owned */
@@ -258,8 +310,8 @@ details_update_show (EmpathyIndividualWidget *self,
           g_free (markup);
         }
 
-      if (!(priv->flags & EMPATHY_INDIVIDUAL_WIDGET_FOR_TOOLTIP))
-        gtk_label_set_selectable (GTK_LABEL (w), TRUE);
+      gtk_label_set_selectable (GTK_LABEL (w),
+          (priv->flags & EMPATHY_INDIVIDUAL_WIDGET_FOR_TOOLTIP) ? FALSE : TRUE);
 
       gtk_table_attach_defaults (GTK_TABLE (priv->table_details),
           w, 1, 2, n_rows, n_rows + 1);
@@ -325,18 +377,6 @@ details_request_cb (TpContact *contact,
 
       tp_clear_object (&priv->details_cancellable);
 
-      /* We need a (weak) pointer to the contact so that we can disconnect the
-       * signal handler on deconstruction. */
-      if (priv->contact_info_contact != NULL)
-        {
-          g_object_remove_weak_pointer (G_OBJECT (priv->contact_info_contact),
-            (gpointer *) &priv->contact_info_contact);
-        }
-
-      priv->contact_info_contact = contact;
-      g_object_add_weak_pointer (G_OBJECT (contact),
-          (gpointer *) &priv->contact_info_contact);
-
       g_signal_connect (contact, "notify::contact-info",
           (GCallback) details_notify_cb, self);
     }
@@ -350,15 +390,18 @@ details_feature_prepared_cb (TpConnection *connection,
     DetailsData *data)
 {
   EmpathyIndividualWidget *self = data->widget;
-  EmpathyIndividualWidgetPriv *priv = GET_PRIV (self);
+  EmpathyIndividualWidgetPriv *priv = NULL;
 
-  if (tp_proxy_prepare_finish (connection, res, NULL) == FALSE)
+  if (tp_proxy_prepare_finish (connection, res, NULL) == FALSE || self == NULL)
     {
-      gtk_widget_hide (priv->vbox_details);
+      if (self != NULL)
+        gtk_widget_hide (GET_PRIV (self)->vbox_details);
       details_data_free (data);
       return;
     }
 
+  priv = GET_PRIV (self);
+
   /* Request the Individual's info */
   gtk_widget_show (priv->vbox_details);
   gtk_widget_show (priv->hbox_details_requested);
@@ -385,28 +428,10 @@ details_update (EmpathyIndividualWidget *self)
 
   gtk_widget_hide (priv->vbox_details);
 
-  if (priv->individual != NULL)
-    {
-      /* FIXME: We take the first TpContact we find and only use its details.
-       * It would be a lot better if we would get the details for every
-       * TpContact in the Individual and merge them all, but that requires
-       * vCard support in libfolks for it to not be hideously complex.
-       * (bgo#627399) */
-      GList *personas, *l;
-
-      personas = folks_individual_get_personas (priv->individual);
-      for (l = personas; l != NULL; l = l->next)
-        {
-          if (TPF_IS_PERSONA (l->data))
-            {
-              tp_contact = tpf_persona_get_contact (TPF_PERSONA (l->data));
-              if (tp_contact != NULL)
-                break;
-            }
-        }
-    }
+  if (priv->contact == NULL)
+    update_weak_contact (self);
 
-  if (tp_contact != NULL)
+  if (priv->contact != NULL)
     {
       GQuark features[] = { TP_CONNECTION_FEATURE_CONTACT_INFO, 0 };
       TpConnection *connection;
@@ -415,7 +440,7 @@ details_update (EmpathyIndividualWidget *self)
       data = g_slice_new (DetailsData);
       data->widget = self;
       g_object_add_weak_pointer (G_OBJECT (self), (gpointer *) &data->widget);
-      data->contact = g_object_ref (tp_contact);
+      data->contact = g_object_ref (priv->contact);
 
       /* First, make sure the CONTACT_INFO feature is ready on the connection */
       connection = tp_contact_get_connection (tp_contact);
@@ -434,7 +459,7 @@ groups_update (EmpathyIndividualWidget *self)
     {
       empathy_groups_widget_set_groupable (
           EMPATHY_GROUPS_WIDGET (priv->groups_widget),
-          FOLKS_GROUPS (priv->individual));
+          FOLKS_GROUPABLE (priv->individual));
       gtk_widget_show (priv->groups_widget);
     }
   else
@@ -530,7 +555,8 @@ location_update (EmpathyIndividualWidget *self)
   gboolean display_map = FALSE;
   GList *personas, *l;
 
-  if (!(priv->flags & EMPATHY_INDIVIDUAL_WIDGET_SHOW_LOCATION))
+  if (!(priv->flags & EMPATHY_INDIVIDUAL_WIDGET_SHOW_LOCATION) ||
+      priv->individual == NULL)
     {
       gtk_widget_hide (priv->vbox_location);
       return;
@@ -585,13 +611,17 @@ location_update (EmpathyIndividualWidget *self)
       gchar *text;
       gint64 stamp;
       time_t time_;
+      gchar *tmp;
 
       stamp = g_value_get_int64 (value);
       time_ = stamp;
 
       user_date = empathy_time_to_string_relative (time_);
 
-      text = g_strconcat ( _("<b>Location</b>, "), user_date, NULL);
+      tmp = g_strdup_printf ("<b>%s</b>", _("Location"));
+      /* translators: format is "Location, $date" */
+      text = g_strdup_printf (_("%s, %s"), tmp, user_date);
+      g_free (tmp);
       gtk_label_set_markup (GTK_LABEL (priv->label_location), text);
       g_free (user_date);
       g_free (text);
@@ -650,8 +680,9 @@ location_update (EmpathyIndividualWidget *self)
           gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
           gtk_widget_show (label);
 
-          if (!(priv->flags & EMPATHY_INDIVIDUAL_WIDGET_FOR_TOOLTIP))
-            gtk_label_set_selectable (GTK_LABEL (label), TRUE);
+          gtk_label_set_selectable (GTK_LABEL (label),
+              (priv->flags & EMPATHY_INDIVIDUAL_WIDGET_FOR_TOOLTIP) ? FALSE :
+                  TRUE);
         }
 
       g_free (svalue);
@@ -752,8 +783,8 @@ location_update (EmpathyIndividualWidget *self)
 
               /* Add a marker to the map */
               marker = champlain_marker_new_with_text (
-                  folks_alias_get_alias (FOLKS_ALIAS (persona)), NULL, NULL,
-                  NULL);
+                  folks_aliasable_get_alias (FOLKS_ALIASABLE (persona)), NULL,
+                  NULL, NULL);
               champlain_base_marker_set_position (
                   CHAMPLAIN_BASE_MARKER (marker), lat, lon);
               clutter_container_add (CLUTTER_CONTAINER (layer), marker, NULL);
@@ -777,6 +808,64 @@ location_update (EmpathyIndividualWidget *self)
     gtk_widget_show (priv->vbox_location);
 }
 
+static void
+client_types_notify_cb (TpContact *contact,
+    GParamSpec *pspec,
+    EmpathyIndividualWidget *self)
+{
+  client_types_update (self);
+}
+
+static void
+client_types_update (EmpathyIndividualWidget *self)
+{
+  EmpathyIndividualWidgetPriv *priv = GET_PRIV (self);
+  const gchar * const *types;
+
+  if (!(priv->flags & EMPATHY_INDIVIDUAL_WIDGET_SHOW_CLIENT_TYPES) ||
+      priv->individual == NULL)
+    {
+      gtk_widget_hide (priv->hbox_client_types);
+      return;
+    }
+
+  if (priv->contact == NULL)
+    update_weak_contact (self);
+
+  /* let's try that again... */
+  if (priv->contact == NULL)
+    return;
+
+  types = tp_contact_get_client_types (priv->contact);
+
+  if (types != NULL
+      && g_strv_length ((gchar **) types) > 0
+      && !tp_strdiff (types[0], "phone"))
+    {
+      gtk_widget_show (priv->hbox_client_types);
+    }
+  else
+    {
+      gtk_widget_hide (priv->hbox_client_types);
+    }
+
+  g_signal_connect (priv->contact, "notify::client-types",
+      (GCallback) client_types_notify_cb, self);
+}
+
+static void
+remove_weak_contact (EmpathyIndividualWidget *self)
+{
+  EmpathyIndividualWidgetPriv *priv = GET_PRIV (self);
+
+  if (priv->contact == NULL)
+    return;
+
+  g_object_remove_weak_pointer (G_OBJECT (priv->contact),
+      (gpointer *) &priv->contact);
+  priv->contact = NULL;
+}
+
 static EmpathyAvatar *
 persona_dup_avatar (FolksPersona *persona)
 {
@@ -1049,7 +1138,7 @@ entry_alias_focus_event_cb (GtkEditable *editable,
         }
       else
         {
-          folks_alias_set_alias (FOLKS_ALIAS (priv->individual), alias);
+          folks_aliasable_set_alias (FOLKS_ALIASABLE (priv->individual), alias);
         }
     }
 
@@ -1124,12 +1213,12 @@ notify_alias_cb (gpointer folks_object,
   if (GTK_IS_ENTRY (alias_widget))
     {
       gtk_entry_set_text (GTK_ENTRY (alias_widget),
-          folks_alias_get_alias (FOLKS_ALIAS (folks_object)));
+          folks_aliasable_get_alias (FOLKS_ALIASABLE (folks_object)));
     }
   else
     {
       gtk_label_set_label (GTK_LABEL (alias_widget),
-          folks_alias_get_alias (FOLKS_ALIAS (folks_object)));
+          folks_aliasable_get_alias (FOLKS_ALIASABLE (folks_object)));
     }
 }
 
@@ -1235,8 +1324,8 @@ alias_presence_avatar_favourite_set_up (EmpathyIndividualWidget *self,
   else
     {
       alias = gtk_label_new (NULL);
-      if (!(priv->flags & EMPATHY_INDIVIDUAL_WIDGET_FOR_TOOLTIP))
-        gtk_label_set_selectable (GTK_LABEL (alias), TRUE);
+      gtk_label_set_selectable (GTK_LABEL (alias),
+          (priv->flags & EMPATHY_INDIVIDUAL_WIDGET_FOR_TOOLTIP) ? FALSE : TRUE);
       gtk_misc_set_alignment (GTK_MISC (alias), 0.0, 0.5);
     }
 
@@ -1258,10 +1347,10 @@ alias_presence_avatar_favourite_set_up (EmpathyIndividualWidget *self,
       FALSE, 0);
   gtk_widget_show (image);
 
-  /* Set up status_label as a KludgeLabel */
-  label = empathy_kludge_label_new ("");
+  label = gtk_label_new ("");
   gtk_label_set_line_wrap_mode (GTK_LABEL (label), PANGO_WRAP_WORD_CHAR);
   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+  gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
 
   gtk_label_set_selectable (GTK_LABEL (label),
       (priv->flags & EMPATHY_INDIVIDUAL_WIDGET_FOR_TOOLTIP) ? FALSE : TRUE);
@@ -1364,6 +1453,8 @@ update_persona (EmpathyIndividualWidget *self, FolksPersona *persona)
 
   if (priv->flags & EMPATHY_INDIVIDUAL_WIDGET_EDIT_FAVOURITE)
     notify_is_favourite_cb (persona, NULL, self);
+
+  g_object_unref (contact);
 }
 
 static void
@@ -1397,7 +1488,8 @@ add_persona (EmpathyIndividualWidget *self,
   hbox = GTK_BOX (gtk_hbox_new (FALSE, 6));
 
   account_label = gtk_label_new (NULL);
-  gtk_label_set_selectable (GTK_LABEL (account_label), TRUE);
+  gtk_label_set_selectable (GTK_LABEL (account_label),
+      (priv->flags & EMPATHY_INDIVIDUAL_WIDGET_FOR_TOOLTIP) ? FALSE : TRUE);
   gtk_misc_set_alignment (GTK_MISC (account_label), 0.0, 0.5);
   gtk_widget_show (account_label);
 
@@ -1424,7 +1516,8 @@ add_persona (EmpathyIndividualWidget *self,
 
   /* Set up ID label */
   label = gtk_label_new (NULL);
-  gtk_label_set_selectable (GTK_LABEL (label), TRUE);
+  gtk_label_set_selectable (GTK_LABEL (label),
+      (priv->flags & EMPATHY_INDIVIDUAL_WIDGET_FOR_TOOLTIP) ? FALSE : TRUE);
   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
 
   g_object_set_data (G_OBJECT (table), "id-widget", label);
@@ -1593,76 +1686,85 @@ individual_table_destroy (EmpathyIndividualWidget *self)
 }
 
 static void
-notify_personas_cb (FolksIndividual *individual,
-    GParamSpec *pspec,
+personas_changed_cb (FolksIndividual *individual,
+    GList *added,
+    GList *removed,
     EmpathyIndividualWidget *self)
 {
   EmpathyIndividualWidgetPriv *priv = GET_PRIV (self);
-  GList *personas, *l, *children, *remove_personas = NULL;
-  GHashTableIter iter;
-  FolksPersona *persona;
-  GtkTable *table;
-  gboolean is_last;
-  guint old_num_personas, new_num_personas;
+  GList *personas, *l, *children;
+  gboolean show_personas, was_showing_personas, will_show_personas, is_last;
+  guint old_num_personas, new_num_personas = 0;
 
   personas = folks_individual_get_personas (individual);
+
+  /* Note that old_num_personas is the number of persona tables we were
+   * displaying, not the number of Personas which were in the Individual
+   * before. */
   old_num_personas = g_hash_table_size (priv->persona_tables);
-  new_num_personas = g_list_length (personas);
-
-  /* Remove Personas */
-  g_hash_table_iter_init (&iter, priv->persona_tables);
-  while (g_hash_table_iter_next (&iter, (gpointer *) &persona,
-      (gpointer *) &table))
-    {
-      /* FIXME: This is slow. bgo#626725 */
-      /* Old persona or we were displaying all personas and now just want to
-       * display the individual table.
-       * We can't remove the persona inside this loop, as that would invalidate
-       * the hash table iter. */
-      if (g_list_find (personas, persona) == NULL ||
-          (!(priv->flags & EMPATHY_INDIVIDUAL_WIDGET_SHOW_PERSONAS) &&
-           new_num_personas > 1))
-        {
-          remove_personas = g_list_prepend (remove_personas, persona);
-        }
+
+  for (l = personas; l != NULL; l = l->next)
+    {
+      if (TPF_IS_PERSONA (l->data))
+        new_num_personas++;
     }
 
-  for (l = remove_personas; l != NULL; l = l->next)
-    remove_persona (self, FOLKS_PERSONA (l->data));
-  g_list_free (remove_personas);
+  /*
+   * What we display for various conditions:
+   *  - "Personas": display the alias, avatar, presence account and identifier
+   *                for each of the Individual's Personas. (i.e. One table per
+   *                Persona.)
+   *  - "Individual": display the alias, avatar and presence for the Individual,
+   *                  and a label saying "Meta-contact containing x contacts".
+   *                  (i.e. One table in total.)
+   *
+   *              | SHOW_PERSONAS | !SHOW_PERSONAS
+   * -------------+---------------+---------------
+   * > 1 Persona  | Personas      | Individual
+   * -------------+---------------+---------------
+   * == 1 Persona | Personas      | Personas
+   */
+  show_personas = (priv->flags & EMPATHY_INDIVIDUAL_WIDGET_SHOW_PERSONAS) != 0;
+  was_showing_personas = show_personas || old_num_personas == 1;
+  will_show_personas = show_personas || new_num_personas == 1;
+
+  /* If both @added and @removed are NULL, we're being called manually, and we
+   * need to set up the tables for the first time. We do this simply by
+   * ensuring was_showing_personas and will_show_personas are different so that
+   * the code resets the UI.
+   */
+  if (added == NULL && removed == NULL)
+    was_showing_personas = !will_show_personas;
 
-  individual_table_destroy (self);
+  if (was_showing_personas && will_show_personas)
+    {
+      /* Remove outdated Personas */
+      for (l = removed; l != NULL; l = l->next)
+        remove_persona (self, FOLKS_PERSONA (l->data));
 
-  /* If we're !SHOW_PERSONAS and have more than one Persona, we only display
-   * the Individual's alias, avatar and presence, and a label saying
-   * "Meta-contact containing x contacts". (i.e. One table.)
-   * If we're SHOW_PERSONAS or have only one Persona, we display the
-   * alias, avatar, presence, account and identifier for each of the
-   * Individual's Personas. (i.e. One table per Persona.) */
-  if (!(priv->flags & EMPATHY_INDIVIDUAL_WIDGET_SHOW_PERSONAS) &&
-      new_num_personas > 1)
+      /* Add new Personas */
+      for (l = added; l != NULL; l = l->next)
+        add_persona (self, FOLKS_PERSONA (l->data));
+    }
+  else if (!was_showing_personas && will_show_personas)
     {
-      individual_table_set_up (self);
+      /* Remove the old Individual table */
+      individual_table_destroy (self);
+
+      /* Set up all the Persona tables instead */
+      for (l = personas; l != NULL; l = l->next)
+        add_persona (self, FOLKS_PERSONA (l->data));
     }
-  else
+  else if (was_showing_personas && !will_show_personas)
     {
-      /* Add Personas */
+      /* Remove all Personas */
       for (l = personas; l != NULL; l = l->next)
-        {
-          persona = FOLKS_PERSONA (l->data);
-
-          if (!TPF_IS_PERSONA (persona))
-            continue;
+        remove_persona (self, FOLKS_PERSONA (l->data));
+      for (l = removed; l != NULL; l = l->next)
+        remove_persona (self, FOLKS_PERSONA (l->data));
 
-          /* New persona or we were displaying the individual table and we
-           * now want to display all personas */
-          if ((!(priv->flags & EMPATHY_INDIVIDUAL_WIDGET_SHOW_PERSONAS) &&
-               new_num_personas <= 1) ||
-              g_hash_table_lookup (priv->persona_tables, persona) == NULL)
-            {
-              add_persona (self, persona);
-            }
-        }
+      /* Set up the Individual table instead */
+      individual_table_set_up (self);
     }
 
   /* Hide the last separator and show the others */
@@ -1682,6 +1784,14 @@ notify_personas_cb (FolksIndividual *individual,
   g_list_free (children);
 }
 
+static void
+individual_removed_cb (FolksIndividual *individual,
+    FolksIndividual *replacement_individual,
+    EmpathyIndividualWidget *self)
+{
+  empathy_individual_widget_set_individual (self, replacement_individual);
+}
+
 static void
 remove_individual (EmpathyIndividualWidget *self)
 {
@@ -1697,7 +1807,9 @@ remove_individual (EmpathyIndividualWidget *self)
       g_signal_handlers_disconnect_by_func (priv->individual,
           notify_avatar_cb, self);
       g_signal_handlers_disconnect_by_func (priv->individual,
-          notify_personas_cb, self);
+          personas_changed_cb, self);
+      g_signal_handlers_disconnect_by_func (priv->individual,
+          individual_removed_cb, self);
 
       if (priv->flags & EMPATHY_INDIVIDUAL_WIDGET_EDIT_FAVOURITE)
         {
@@ -1708,15 +1820,10 @@ remove_individual (EmpathyIndividualWidget *self)
       personas = folks_individual_get_personas (priv->individual);
       for (l = personas; l != NULL; l = l->next)
         remove_persona (self, FOLKS_PERSONA (l->data));
+      individual_table_destroy (self);
 
-      if (priv->contact_info_contact != NULL)
-        {
-          g_signal_handlers_disconnect_by_func (priv->contact_info_contact,
-              details_notify_cb, self);
-          g_object_remove_weak_pointer (G_OBJECT (priv->contact_info_contact),
-              (gpointer *) &priv->contact_info_contact);
-          priv->contact_info_contact = NULL;
-        }
+      if (priv->contact != NULL)
+        remove_weak_contact (self);
 
       tp_clear_object (&priv->individual);
     }
@@ -1741,8 +1848,10 @@ individual_update (EmpathyIndividualWidget *self)
           (GCallback) notify_presence_cb, self);
       g_signal_connect (priv->individual, "notify::avatar",
           (GCallback) notify_avatar_cb, self);
-      g_signal_connect (priv->individual, "notify::personas",
-          (GCallback) notify_personas_cb, self);
+      g_signal_connect (priv->individual, "personas-changed",
+          (GCallback) personas_changed_cb, self);
+      g_signal_connect (priv->individual, "removed",
+          (GCallback) individual_removed_cb, self);
 
       if (priv->flags & EMPATHY_INDIVIDUAL_WIDGET_EDIT_FAVOURITE)
         {
@@ -1751,7 +1860,7 @@ individual_update (EmpathyIndividualWidget *self)
         }
 
       /* Update individual table */
-      notify_personas_cb (priv->individual, NULL, self);
+      personas_changed_cb (priv->individual, NULL, NULL, self);
     }
 
   if (priv->individual == NULL)
@@ -1813,6 +1922,7 @@ empathy_individual_widget_init (EmpathyIndividualWidget *self)
       "vbox_details", &priv->vbox_details,
       "table_details", &priv->table_details,
       "hbox_details_requested", &priv->hbox_details_requested,
+      "hbox_client_types", &priv->hbox_client_types,
       NULL);
   g_free (filename);
 
@@ -2046,4 +2156,5 @@ empathy_individual_widget_set_individual (EmpathyIndividualWidget *self,
   groups_update (self);
   details_update (self);
   location_update (self);
+  client_types_update (self);
 }