]> git.0d.be Git - empathy.git/blobdiff - libempathy-gtk/empathy-individual-store.c
Merge branch 'gnome-3-8'
[empathy.git] / libempathy-gtk / empathy-individual-store.c
index 630d8d284f9346abafd5c836eeb3f1f122edb29e..9b685ee5f7dbba3547d31e579d879682c947c924 100644 (file)
  */
 
 #include "config.h"
+#include "empathy-individual-store.h"
 
-#include <string.h>
-
-#include <glib.h>
 #include <glib/gi18n-lib.h>
-#include <gtk/gtk.h>
-
-#include <folks/folks.h>
-#include <folks/folks-telepathy.h>
-#include <telepathy-glib/util.h>
+#include <tp-account-widgets/tpaw-utils.h>
 
-#include <libempathy/empathy-utils.h>
-#include <libempathy/empathy-enum-types.h>
-#include <libempathy/empathy-individual-manager.h>
-
-#include "empathy-individual-store.h"
-#include "empathy-ui-utils.h"
 #include "empathy-gtk-enum-types.h"
+#include "empathy-ui-utils.h"
+#include "empathy-utils.h"
 
 #define DEBUG_FLAG EMPATHY_DEBUG_CONTACT
-#include <libempathy/empathy-debug.h>
+#include "empathy-debug.h"
 
 /* Active users are those which have recently changed state
  * (e.g. online, offline or from normal to a busy state).
 
 struct _EmpathyIndividualStorePriv
 {
-  EmpathyIndividualManager *manager;
   gboolean show_avatars;
   gboolean show_groups;
   gboolean is_compact;
   gboolean show_protocols;
-  gboolean show_active;
   EmpathyIndividualStoreSort sort_criterium;
   guint inhibit_active;
-  guint setup_idle_id;
   gboolean dispose_has_run;
   GHashTable *status_icons;
   /* List of owned GCancellables for each pending avatar load operation */
@@ -76,6 +63,7 @@ struct _EmpathyIndividualStorePriv
   GHashTable                  *folks_individual_cache;
   /* Hash: char *groupname -> GtkTreeIter * */
   GHashTable                  *empathy_group_cache;
+  gboolean show_active;
 };
 
 typedef struct
@@ -89,7 +77,6 @@ typedef struct
 enum
 {
   PROP_0,
-  PROP_INDIVIDUAL_MANAGER,
   PROP_SHOW_AVATARS,
   PROP_SHOW_PROTOCOLS,
   PROP_SHOW_GROUPS,
@@ -104,48 +91,6 @@ static void individual_store_contact_update (EmpathyIndividualStore *self,
 G_DEFINE_TYPE (EmpathyIndividualStore, empathy_individual_store,
     GTK_TYPE_TREE_STORE);
 
-static const gchar * const *
-individual_get_client_types (FolksIndividual *individual)
-{
-  GeeSet *personas;
-  GeeIterator *iter;
-  const gchar * const *types = NULL;
-  FolksPresenceType presence_type = FOLKS_PRESENCE_TYPE_UNSET;
-
-  personas = folks_individual_get_personas (individual);
-  iter = gee_iterable_iterator (GEE_ITERABLE (personas));
-  while (gee_iterator_next (iter))
-    {
-      FolksPresenceDetails *presence;
-      FolksPersona *persona = gee_iterator_get (iter);
-
-      /* We only want personas which have presence and a TpContact */
-      if (!empathy_folks_persona_is_interesting (persona))
-        goto while_finish;
-
-      presence = FOLKS_PRESENCE_DETAILS (persona);
-
-      if (folks_presence_details_typecmp (
-              folks_presence_details_get_presence_type (presence),
-              presence_type) > 0)
-        {
-          TpContact *tp_contact;
-
-          presence_type = folks_presence_details_get_presence_type (presence);
-
-          tp_contact = tpf_persona_get_contact (TPF_PERSONA (persona));
-          if (tp_contact != NULL)
-            types = tp_contact_get_client_types (tp_contact);
-        }
-
-while_finish:
-      g_clear_object (&persona);
-    }
-  g_clear_object (&iter);
-
-  return types;
-}
-
 static void
 add_individual_to_store (GtkTreeStore *store,
     GtkTreeIter *iter,
@@ -160,7 +105,7 @@ add_individual_to_store (GtkTreeStore *store,
   empathy_individual_can_audio_video_call (individual, &can_audio_call,
       &can_video_call, NULL);
 
-  types = individual_get_client_types (individual);
+  types = empathy_individual_get_client_types (individual);
 
   gtk_tree_store_insert_with_values (store, iter, parent, 0,
       EMPATHY_INDIVIDUAL_STORE_COL_NAME,
@@ -255,8 +200,9 @@ individual_store_get_group (EmpathyIndividualStore *self,
     }
 }
 
-static GList *
-individual_store_find_contact (EmpathyIndividualStore *self,
+GList *
+/* (transfer full) free with empathy_individual_store_free_iters() */
+empathy_individual_store_find_contact (EmpathyIndividualStore *self,
     FolksIndividual *individual)
 {
   GQueue *row_refs_queue;
@@ -278,15 +224,15 @@ individual_store_find_contact (EmpathyIndividualStore *self,
   return iters_list;
 }
 
-static void
-free_iters (GList *iters)
+void
+empathy_individual_store_free_iters (GList *iters)
 {
   g_list_foreach (iters, (GFunc) gtk_tree_iter_free, NULL);
   g_list_free (iters);
 }
 
-static void
-individual_store_remove_individual (EmpathyIndividualStore *self,
+void
+empathy_individual_store_remove_individual (EmpathyIndividualStore *self,
     FolksIndividual *individual)
 {
   GtkTreeModel *model;
@@ -330,98 +276,104 @@ individual_store_remove_individual (EmpathyIndividualStore *self,
   g_hash_table_remove (self->priv->folks_individual_cache, individual);
 }
 
-static void
-individual_store_add_individual (EmpathyIndividualStore *self,
+void
+empathy_individual_store_add_individual (EmpathyIndividualStore *self,
     FolksIndividual *individual)
 {
-  GtkTreeIter iter;
-  GeeIterator *group_iter = NULL;
+  GtkTreeIter iter, iter_group;
+  GeeSet *group_set = NULL;
+  gboolean grouped = FALSE;
 
-  if (EMP_STR_EMPTY (folks_alias_details_get_alias (
+  if (TPAW_STR_EMPTY (folks_alias_details_get_alias (
           FOLKS_ALIAS_DETAILS (individual))))
     return;
 
-  if (self->priv->show_groups)
+  if (!self->priv->show_groups)
     {
-      GeeSet *group_set = NULL;
-
-      group_set = folks_group_details_get_groups (
-          FOLKS_GROUP_DETAILS (individual));
+      /* add our individual to the toplevel of the store */
+      add_individual_to_store (GTK_TREE_STORE (self), &iter, NULL,
+          individual);
 
-      if (gee_collection_get_size (GEE_COLLECTION (group_set)) > 0)
-        group_iter = gee_iterable_iterator (GEE_ITERABLE (group_set));
+      goto finally;
     }
 
-  /* fall-back groups, in case there are no named groups */
-  if (group_iter == NULL)
+  group_set = folks_group_details_get_groups (
+      FOLKS_GROUP_DETAILS (individual));
+
+  if (gee_collection_get_size (GEE_COLLECTION (group_set)) > 0)
     {
-      GtkTreeIter iter_group, *parent;
+      /* add the contact to its groups */
+      GeeIterator *group_iter =
+        gee_iterable_iterator (GEE_ITERABLE (group_set));
+
+      while (group_iter != NULL && gee_iterator_next (group_iter))
+        {
+          gchar *group_name = gee_iterator_get (group_iter);
+
+          individual_store_get_group (self, group_name, &iter_group,
+              NULL, NULL, FALSE);
+
+          add_individual_to_store (GTK_TREE_STORE (self), &iter, &iter_group,
+              individual);
+          grouped = TRUE;
+
+          g_free (group_name);
+        }
+
+      g_clear_object (&group_iter);
+    }
+  else
+    {
+      /* fall-back groups, in case there are no named groups */
       EmpathyContact *contact;
       TpConnection *connection;
-      gchar *protocol_name = NULL;
-
-      parent = &iter_group;
+      const gchar *protocol_name = NULL;
 
       contact = empathy_contact_dup_from_folks_individual (individual);
       if (contact != NULL)
         {
           connection = empathy_contact_get_connection (contact);
-          tp_connection_parse_object_path (connection, &protocol_name, NULL);
+          protocol_name = tp_connection_get_protocol_name (connection);
         }
 
-      if (!self->priv->show_groups)
-        parent = NULL;
-      else if (!tp_strdiff (protocol_name, "local-xmpp"))
+      if (!tp_strdiff (protocol_name, "local-xmpp"))
         {
           /* these are People Nearby */
           individual_store_get_group (self,
               EMPATHY_INDIVIDUAL_STORE_PEOPLE_NEARBY, &iter_group, NULL, NULL,
               TRUE);
+          add_individual_to_store (GTK_TREE_STORE (self), &iter, &iter_group,
+              individual);
+          grouped = TRUE;
         }
-      else
-        {
-          individual_store_get_group (self,
-              EMPATHY_INDIVIDUAL_STORE_UNGROUPED,
-              &iter_group, NULL, NULL, TRUE);
-        }
-
-      add_individual_to_store (GTK_TREE_STORE (self), &iter, parent,
-          individual);
 
-      g_free (protocol_name);
       g_clear_object (&contact);
     }
 
-  /* Else add to each group. */
-  while (group_iter != NULL && gee_iterator_next (group_iter))
+  if (folks_favourite_details_get_is_favourite (
+        FOLKS_FAVOURITE_DETAILS (individual)))
     {
-      gchar *group_name = gee_iterator_get (group_iter);
-      GtkTreeIter iter_group;
-
-      individual_store_get_group (self, group_name, &iter_group, NULL, NULL,
-          FALSE);
+      /* Add contact to the fake 'Favorites' group */
+      individual_store_get_group (self, EMPATHY_INDIVIDUAL_STORE_FAVORITE,
+          &iter_group, NULL, NULL, TRUE);
 
       add_individual_to_store (GTK_TREE_STORE (self), &iter, &iter_group,
           individual);
-
-      g_free (group_name);
+      grouped = TRUE;
     }
-  g_clear_object (&group_iter);
 
-  if (self->priv->show_groups &&
-      folks_favourite_details_get_is_favourite (
-          FOLKS_FAVOURITE_DETAILS (individual)))
+  if (!grouped)
     {
-      /* Add contact to the fake 'Favorites' group */
-      GtkTreeIter iter_group;
-
-      individual_store_get_group (self, EMPATHY_INDIVIDUAL_STORE_FAVORITE,
+      /* Else add the contact to 'Ungrouped' */
+      individual_store_get_group (self,
+          EMPATHY_INDIVIDUAL_STORE_UNGROUPED,
           &iter_group, NULL, NULL, TRUE);
-
       add_individual_to_store (GTK_TREE_STORE (self), &iter, &iter_group,
           individual);
     }
 
+
+finally:
   individual_store_contact_update (self, individual);
 }
 
@@ -436,7 +388,7 @@ individual_store_contact_set_active (EmpathyIndividualStore *self,
 
   model = GTK_TREE_MODEL (self);
 
-  iters = individual_store_find_contact (self, individual);
+  iters = empathy_individual_store_find_contact (self, individual);
   for (l = iters; l; l = l->next)
     {
       GtkTreePath *path;
@@ -445,8 +397,6 @@ individual_store_contact_set_active (EmpathyIndividualStore *self,
           EMPATHY_INDIVIDUAL_STORE_COL_IS_ACTIVE, active,
           -1);
 
-      DEBUG ("Set item %s", active ? "active" : "inactive");
-
       if (set_changed)
         {
           path = gtk_tree_model_get_path (model, l->data);
@@ -455,7 +405,7 @@ individual_store_contact_set_active (EmpathyIndividualStore *self,
         }
     }
 
-  free_iters (iters);
+  empathy_individual_store_free_iters (iters);
 }
 
 static void individual_store_contact_active_free (ShowActiveData *data);
@@ -485,10 +435,6 @@ individual_store_contact_active_new (EmpathyIndividualStore *self,
 {
   ShowActiveData *data;
 
-  DEBUG ("Individual'%s' now active, and %s be removed",
-      folks_alias_details_get_alias (FOLKS_ALIAS_DETAILS (individual)),
-      remove_ ? "WILL" : "WILL NOT");
-
   data = g_slice_new0 (ShowActiveData);
 
   /* We don't actually want to force either the IndividualStore or the
@@ -533,12 +479,9 @@ individual_store_contact_active_cb (ShowActiveData *data)
       DEBUG ("Individual'%s' active timeout, removing item",
           folks_alias_details_get_alias (
             FOLKS_ALIAS_DETAILS (data->individual)));
-      individual_store_remove_individual (data->self, data->individual);
+      empathy_individual_store_remove_individual (data->self, data->individual);
     }
 
-  DEBUG ("Individual'%s' no longer active",
-      folks_alias_details_get_alias (FOLKS_ALIAS_DETAILS (data->individual)));
-
   individual_store_contact_set_active (data->self,
       data->individual, FALSE, TRUE);
 
@@ -565,16 +508,22 @@ individual_avatar_pixbuf_received_cb (FolksIndividual *individual,
 
   if (error != NULL)
     {
-      DEBUG ("failed to retrieve pixbuf for individual %s: %s",
-          folks_alias_details_get_alias (FOLKS_ALIAS_DETAILS (individual)),
-          error->message);
+      /* No need to display an error if the individal just doesn't have an
+       * avatar */
+      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+        {
+          DEBUG ("failed to retrieve pixbuf for individual %s: %s",
+              folks_alias_details_get_alias (FOLKS_ALIAS_DETAILS (individual)),
+              error->message);
+        }
+
       g_clear_error (&error);
     }
   else if (data->store != NULL)
     {
       GList *iters, *l;
 
-      iters = individual_store_find_contact (data->store, individual);
+      iters = empathy_individual_store_find_contact (data->store, individual);
       for (l = iters; l; l = l->next)
         {
           gtk_tree_store_set (GTK_TREE_STORE (data->store), l->data,
@@ -582,7 +531,7 @@ individual_avatar_pixbuf_received_cb (FolksIndividual *individual,
               -1);
         }
 
-      free_iters (iters);
+      empathy_individual_store_free_iters (iters);
     }
 
   /* Free things */
@@ -619,7 +568,7 @@ individual_store_contact_update (EmpathyIndividualStore *self,
 
   model = GTK_TREE_MODEL (self);
 
-  iters = individual_store_find_contact (self, individual);
+  iters = empathy_individual_store_find_contact (self, individual);
   if (!iters)
     {
       in_list = FALSE;
@@ -638,20 +587,15 @@ individual_store_contact_update (EmpathyIndividualStore *self,
       DEBUG ("Individual'%s' in list:NO, should be:YES",
           folks_alias_details_get_alias (FOLKS_ALIAS_DETAILS (individual)));
 
-      individual_store_add_individual (self, individual);
+      empathy_individual_store_add_individual (self, individual);
 
       if (self->priv->show_active)
         {
           do_set_active = TRUE;
-
-          DEBUG ("Set active (individual added)");
         }
     }
   else
     {
-      DEBUG ("Individual'%s' in list:YES, should be:YES",
-          folks_alias_details_get_alias (FOLKS_ALIAS_DETAILS (individual)));
-
       /* Get online state before. */
       if (iters && g_list_length (iters) > 0)
         {
@@ -666,17 +610,12 @@ individual_store_contact_update (EmpathyIndividualStore *self,
             {
               do_set_active = TRUE;
               do_set_refresh = TRUE;
-
-              DEBUG ("Set active (individual updated %s)",
-                  was_online ? "online  -> offline" : "offline -> online");
             }
           else
             {
               /* Was TRUE for presence updates. */
               /* do_set_active = FALSE;  */
               do_set_refresh = TRUE;
-
-              DEBUG ("Set active (individual updated)");
             }
         }
 
@@ -714,7 +653,7 @@ individual_store_contact_update (EmpathyIndividualStore *self,
       empathy_individual_can_audio_video_call (individual, &can_audio_call,
           &can_video_call, NULL);
 
-      types = individual_get_client_types (individual);
+      types = empathy_individual_get_client_types (individual);
 
       gtk_tree_store_set (GTK_TREE_STORE (self), l->data,
           EMPATHY_INDIVIDUAL_STORE_COL_ICON_STATUS, pixbuf_status,
@@ -757,7 +696,7 @@ individual_store_contact_update (EmpathyIndividualStore *self,
    * timeout removes the user from the contact list, really we
    * should remove the first timeout.
    */
-  free_iters (iters);
+  empathy_individual_store_free_iters (iters);
 }
 
 static void
@@ -765,9 +704,6 @@ individual_store_individual_updated_cb (FolksIndividual *individual,
     GParamSpec *param,
     EmpathyIndividualStore *self)
 {
-  DEBUG ("Individual'%s' updated, checking roster is in sync...",
-      folks_alias_details_get_alias (FOLKS_ALIAS_DETAILS (individual)));
-
   individual_store_contact_update (self, individual);
 }
 
@@ -778,9 +714,6 @@ individual_store_contact_updated_cb (EmpathyContact *contact,
 {
   FolksIndividual *individual;
 
-  DEBUG ("Contact '%s' updated, checking roster is in sync...",
-      empathy_contact_get_alias (contact));
-
   individual = g_object_get_data (G_OBJECT (contact), "individual");
   if (individual == NULL)
     return;
@@ -796,9 +729,6 @@ individual_personas_changed_cb (FolksIndividual *individual,
 {
   GeeIterator *iter;
 
-  DEBUG ("Individual '%s' personas-changed.",
-      folks_individual_get_id (individual));
-
   iter = gee_iterable_iterator (GEE_ITERABLE (removed));
   /* FIXME: libfolks hasn't grown capabilities support yet, so we have to go
    * through the EmpathyContacts for them. */
@@ -868,8 +798,8 @@ individual_store_favourites_changed_cb (FolksIndividual *individual,
       folks_favourite_details_get_is_favourite (
         FOLKS_FAVOURITE_DETAILS (individual)) ? "now" : "no longer");
 
-  individual_store_remove_individual (self, individual);
-  individual_store_add_individual (self, individual);
+  empathy_individual_store_remove_individual (self, individual);
+  empathy_individual_store_add_individual (self, individual);
 }
 
 void
@@ -878,7 +808,7 @@ individual_store_add_individual_and_connect (EmpathyIndividualStore *self,
 {
   GeeSet *empty_set = gee_set_empty (G_TYPE_NONE, NULL, NULL);
 
-  individual_store_add_individual (self, individual);
+  empathy_individual_store_add_individual (self, individual);
 
   g_signal_connect (individual, "notify::avatar",
       (GCallback) individual_store_individual_updated_cb, self);
@@ -899,8 +829,8 @@ individual_store_add_individual_and_connect (EmpathyIndividualStore *self,
   g_clear_object (&empty_set);
 }
 
-static void
-individual_store_disconnect_individual (EmpathyIndividualStore *self,
+void
+empathy_individual_store_disconnect_individual (EmpathyIndividualStore *self,
     FolksIndividual *individual)
 {
   GeeSet *empty_set = gee_set_empty (G_TYPE_NONE, NULL, NULL);
@@ -923,124 +853,15 @@ individual_store_remove_individual_and_disconnect (
     EmpathyIndividualStore *self,
     FolksIndividual *individual)
 {
-  individual_store_disconnect_individual (self, individual);
-  individual_store_remove_individual (self, individual);
-}
-
-static void
-individual_store_members_changed_cb (EmpathyIndividualManager *manager,
-    const gchar *message,
-    GList *added,
-    GList *removed,
-    guint reason,
-    EmpathyIndividualStore *self)
-{
-  GList *l;
-
-  for (l = added; l; l = l->next)
-    {
-      DEBUG ("Individual %s %s", folks_individual_get_id (l->data), "added");
-
-      individual_store_add_individual_and_connect (self, l->data);
-    }
-  for (l = removed; l; l = l->next)
-    {
-      DEBUG ("Individual %s %s",
-          folks_individual_get_id (l->data), "removed");
-
-      individual_store_remove_individual_and_disconnect (self, l->data);
-    }
-}
-
-static void
-individual_store_groups_changed_cb (EmpathyIndividualManager *manager,
-    FolksIndividual *individual,
-    gchar *group,
-    gboolean is_member,
-    EmpathyIndividualStore *self)
-{
-  gboolean show_active;
-
-  DEBUG ("Updating groups for individual %s",
-      folks_individual_get_id (individual));
-
-  /* We do this to make sure the groups are correct, if not, we
-   * would have to check the groups already set up for each
-   * contact and then see what has been updated.
-   */
-  show_active = self->priv->show_active;
-  self->priv->show_active = FALSE;
-  individual_store_remove_individual (self, individual);
-  individual_store_add_individual (self, individual);
-  self->priv->show_active = show_active;
-}
-
-static gboolean
-individual_store_manager_setup (gpointer user_data)
-{
-  EmpathyIndividualStore *self = user_data;
-  GList *individuals;
-
-  /* Signal connection. */
-
-  /* TODO: implement */
-  DEBUG ("handling individual renames unimplemented");
-
-  g_signal_connect (self->priv->manager,
-      "members-changed",
-      G_CALLBACK (individual_store_members_changed_cb), self);
-
-  g_signal_connect (self->priv->manager,
-      "groups-changed",
-      G_CALLBACK (individual_store_groups_changed_cb), self);
-
-  /* Add contacts already created. */
-  individuals = empathy_individual_manager_get_members (self->priv->manager);
-  if (individuals != NULL && FOLKS_IS_INDIVIDUAL (individuals->data))
-    {
-      individual_store_members_changed_cb (self->priv->manager, "initial add",
-          individuals, NULL, 0, self);
-      g_list_free (individuals);
-    }
-
-  self->priv->setup_idle_id = 0;
-  return FALSE;
-}
-
-static void
-individual_store_set_individual_manager (EmpathyIndividualStore *self,
-    EmpathyIndividualManager *manager)
-{
-  self->priv->manager = g_object_ref (manager);
-
-  /* Let a chance to have all properties set before populating */
-  self->priv->setup_idle_id = g_idle_add (individual_store_manager_setup, self);
-}
-
-static void
-individual_store_member_renamed_cb (EmpathyIndividualManager *manager,
-    FolksIndividual *old_individual,
-    FolksIndividual *new_individual,
-    guint reason,
-    const gchar *message,
-    EmpathyIndividualStore *self)
-{
-  DEBUG ("Individual %s renamed to %s",
-      folks_individual_get_id (old_individual),
-      folks_individual_get_id (new_individual));
-
-  /* add the new contact */
-  individual_store_add_individual_and_connect (self, new_individual);
-
-  /* remove old contact */
-  individual_store_remove_individual_and_disconnect (self, old_individual);
+  empathy_individual_store_disconnect_individual (self, individual);
+  empathy_individual_store_remove_individual (self, individual);
 }
 
 static void
 individual_store_dispose (GObject *object)
 {
   EmpathyIndividualStore *self = EMPATHY_INDIVIDUAL_STORE (object);
-  GList *individuals, *l;
+  GList *l;
 
   if (self->priv->dispose_has_run)
     return;
@@ -1054,35 +875,14 @@ individual_store_dispose (GObject *object)
     }
   g_list_free (self->priv->avatar_cancellables);
 
-  individuals = empathy_individual_manager_get_members (self->priv->manager);
-  for (l = individuals; l; l = l->next)
-    {
-      individual_store_disconnect_individual (EMPATHY_INDIVIDUAL_STORE (object),
-          FOLKS_INDIVIDUAL (l->data));
-    }
-  g_list_free (individuals);
-
-  g_signal_handlers_disconnect_by_func (self->priv->manager,
-      G_CALLBACK (individual_store_member_renamed_cb), object);
-  g_signal_handlers_disconnect_by_func (self->priv->manager,
-      G_CALLBACK (individual_store_members_changed_cb), object);
-  g_signal_handlers_disconnect_by_func (self->priv->manager,
-      G_CALLBACK (individual_store_groups_changed_cb), object);
-  g_object_unref (self->priv->manager);
-
   if (self->priv->inhibit_active)
     {
       g_source_remove (self->priv->inhibit_active);
     }
 
-  if (self->priv->setup_idle_id != 0)
-    {
-      g_source_remove (self->priv->setup_idle_id);
-    }
-
-  g_hash_table_destroy (self->priv->status_icons);
-  g_hash_table_destroy (self->priv->folks_individual_cache);
-  g_hash_table_destroy (self->priv->empathy_group_cache);
+  g_hash_table_unref (self->priv->status_icons);
+  g_hash_table_unref (self->priv->folks_individual_cache);
+  g_hash_table_unref (self->priv->empathy_group_cache);
   G_OBJECT_CLASS (empathy_individual_store_parent_class)->dispose (object);
 }
 
@@ -1096,9 +896,6 @@ individual_store_get_property (GObject *object,
 
   switch (param_id)
     {
-    case PROP_INDIVIDUAL_MANAGER:
-      g_value_set_object (value, self->priv->manager);
-      break;
     case PROP_SHOW_AVATARS:
       g_value_set_boolean (value, self->priv->show_avatars);
       break;
@@ -1128,10 +925,6 @@ individual_store_set_property (GObject *object,
 {
   switch (param_id)
     {
-    case PROP_INDIVIDUAL_MANAGER:
-      individual_store_set_individual_manager (EMPATHY_INDIVIDUAL_STORE
-          (object), g_value_get_object (value));
-      break;
     case PROP_SHOW_AVATARS:
       empathy_individual_store_set_show_avatars (EMPATHY_INDIVIDUAL_STORE
           (object), g_value_get_boolean (value));
@@ -1167,13 +960,6 @@ empathy_individual_store_class_init (EmpathyIndividualStoreClass *klass)
   object_class->get_property = individual_store_get_property;
   object_class->set_property = individual_store_set_property;
 
-  g_object_class_install_property (object_class,
-      PROP_INDIVIDUAL_MANAGER,
-      g_param_spec_object ("individual-manager",
-          "The individual manager",
-          "The individual manager",
-          EMPATHY_TYPE_INDIVIDUAL_MANAGER,
-          G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
   g_object_class_install_property (object_class,
       PROP_SHOW_AVATARS,
       g_param_spec_boolean ("show-avatars",
@@ -1338,8 +1124,8 @@ individual_store_contact_sort (FolksIndividual *individual_a,
       g_assert (account_b != NULL);
 
       /* protocol */
-      ret_val = g_strcmp0 (tp_account_get_protocol (account_a),
-          tp_account_get_protocol (account_b));
+      ret_val = g_strcmp0 (tp_account_get_protocol_name (account_a),
+          tp_account_get_protocol_name (account_b));
 
       if (ret_val != 0)
         goto out;
@@ -1541,23 +1327,6 @@ empathy_individual_store_init (EmpathyIndividualStore *self)
   individual_store_setup (self);
 }
 
-EmpathyIndividualStore *
-empathy_individual_store_new (EmpathyIndividualManager *manager)
-{
-  g_return_val_if_fail (EMPATHY_IS_INDIVIDUAL_MANAGER (manager), NULL);
-
-  return g_object_new (EMPATHY_TYPE_INDIVIDUAL_STORE,
-      "individual-manager", manager, NULL);
-}
-
-EmpathyIndividualManager *
-empathy_individual_store_get_manager (EmpathyIndividualStore *self)
-{
-  g_return_val_if_fail (EMPATHY_IS_INDIVIDUAL_STORE (self), FALSE);
-
-  return self->priv->manager;
-}
-
 gboolean
 empathy_individual_store_get_show_avatars (EmpathyIndividualStore *self)
 {
@@ -1660,8 +1429,12 @@ void
 empathy_individual_store_set_show_groups (EmpathyIndividualStore *self,
     gboolean show_groups)
 {
+  EmpathyIndividualStoreClass *klass;
+
   g_return_if_fail (EMPATHY_IS_INDIVIDUAL_STORE (self));
 
+  klass = EMPATHY_INDIVIDUAL_STORE_GET_CLASS ( self);
+
   if (self->priv->show_groups == show_groups)
     {
       return;
@@ -1669,7 +1442,7 @@ empathy_individual_store_set_show_groups (EmpathyIndividualStore *self,
 
   self->priv->show_groups = show_groups;
 
-  if (self->priv->setup_idle_id == 0)
+  if (!klass->initial_loading (self))
     {
       /* Remove all contacts and add them back, not optimized but
        * that's the easy way :)
@@ -1677,19 +1450,13 @@ empathy_individual_store_set_show_groups (EmpathyIndividualStore *self,
        * This is only done if there's not a pending setup idle
        * callback, otherwise it will race and the contacts will get
        * added twice */
-      GList *contacts;
 
       gtk_tree_store_clear (GTK_TREE_STORE (self));
       /* Also clear the cache */
       g_hash_table_remove_all (self->priv->folks_individual_cache);
       g_hash_table_remove_all (self->priv->empathy_group_cache);
 
-      contacts = empathy_individual_manager_get_members (self->priv->manager);
-
-      individual_store_members_changed_cb (self->priv->manager,
-          "re-adding members: toggled group visibility",
-          contacts, NULL, 0, self);
-      g_list_free (contacts);
+      klass->reload_individuals (self);
     }
 
   g_object_notify (G_OBJECT (self), "show-groups");
@@ -1927,3 +1694,16 @@ empathy_individual_store_get_individual_status_icon (
 
   return pixbuf_status;
 }
+
+void
+empathy_individual_store_refresh_individual (EmpathyIndividualStore *self,
+    FolksIndividual *individual)
+{
+  gboolean show_active;
+
+  show_active = self->priv->show_active;
+  self->priv->show_active = FALSE;
+  empathy_individual_store_remove_individual (self, individual);
+  empathy_individual_store_add_individual (self, individual);
+  self->priv->show_active = show_active;
+}