static void
remove_individual (EmpathyIndividualManager *self, FolksIndividual *individual)
{
  EmpathyIndividualManagerPriv *priv = GET_PRIV (self);

  g_signal_handlers_disconnect_by_func (individual,
      individual_group_changed_cb, self);
  g_signal_handlers_disconnect_by_func (individual,
      individual_notify_is_favourite_cb, self);

  g_hash_table_remove (priv->individuals, folks_individual_get_id (individual));
}
static void
add_individual (EmpathyIndividualManager *self, FolksIndividual *individual)
{
  EmpathyIndividualManagerPriv *priv = GET_PRIV (self);

  g_hash_table_insert (priv->individuals,
      g_strdup (folks_individual_get_id (individual)),
      g_object_ref (individual));

  g_signal_connect (individual, "group-changed",
      G_CALLBACK (individual_group_changed_cb), self);
  g_signal_connect (individual, "notify::is-favourite",
      G_CALLBACK (individual_notify_is_favourite_cb), self);
}
void
empathy_individual_manager_unlink_individual (EmpathyIndividualManager *self,
    FolksIndividual *individual)
{
  EmpathyIndividualManagerPriv *priv;

  g_return_if_fail (EMPATHY_IS_INDIVIDUAL_MANAGER (self));
  g_return_if_fail (FOLKS_IS_INDIVIDUAL (individual));

  priv = GET_PRIV (self);

  DEBUG ("Unlinking individual '%s'", folks_individual_get_id (individual));

  folks_individual_aggregator_unlink_individual (priv->aggregator, individual,
      (GAsyncReadyCallback) unlink_individual_cb, NULL);
}
/**
 * Removes the inner contact from the server (and thus the Individual). Not
 * meant for de-shelling inner personas from an Individual.
 */
void
empathy_individual_manager_remove (EmpathyIndividualManager *self,
    FolksIndividual *individual,
    const gchar *message)
{
  EmpathyIndividualManagerPriv *priv;

  g_return_if_fail (EMPATHY_IS_INDIVIDUAL_MANAGER (self));
  g_return_if_fail (FOLKS_IS_INDIVIDUAL (individual));

  priv = GET_PRIV (self);

  DEBUG ("removing individual %s (%s)",
      folks_individual_get_id (individual),
      folks_alias_details_get_alias (FOLKS_ALIAS_DETAILS (individual)));

  folks_individual_aggregator_remove_individual (priv->aggregator, individual,
      aggregator_remove_individual_cb, self);
}
示例#5
0
/* Retrieve the EmpathyContact corresponding to the first TpContact contained
 * within the given Individual. Note that this is a temporary convenience. See
 * the TODO above. */
EmpathyContact *
empathy_contact_dup_from_folks_individual (FolksIndividual *individual)
{
  GeeSet *personas;
  GeeIterator *iter;
  EmpathyContact *contact = NULL;

  g_return_val_if_fail (FOLKS_IS_INDIVIDUAL (individual), NULL);

  personas = folks_individual_get_personas (individual);
  iter = gee_iterable_iterator (GEE_ITERABLE (personas));
  while (gee_iterator_next (iter) && (contact == NULL))
    {
      TpfPersona *persona = gee_iterator_get (iter);

      if (empathy_folks_persona_is_interesting (FOLKS_PERSONA (persona)))
        {
          TpContact *tp_contact;

          tp_contact = tpf_persona_get_contact (persona);
          if (tp_contact != NULL)
            {
              contact = empathy_contact_dup_from_tp_contact (tp_contact);
              empathy_contact_set_persona (contact, FOLKS_PERSONA (persona));
            }
        }
      g_clear_object (&persona);
    }
  g_clear_object (&iter);

  if (contact == NULL)
    {
      DEBUG ("Can't create an EmpathyContact for Individual %s",
          folks_individual_get_id (individual));
    }

  return contact;
}
/* This is emitted for *all* individuals in the individual aggregator (not
 * just the ones we keep a reference to), to allow for the case where a new
 * individual doesn't contain an EmpathyContact, but later has a persona added
 * which does. */
static void
individual_notify_personas_cb (FolksIndividual *individual,
    GParamSpec *pspec,
    EmpathyIndividualManager *self)
{
  EmpathyIndividualManagerPriv *priv = GET_PRIV (self);

  const gchar *id = folks_individual_get_id (individual);
  gboolean has_contact = empathy_folks_individual_contains_contact (individual);
  gboolean had_contact = (g_hash_table_lookup (priv->individuals,
      id) != NULL) ? TRUE : FALSE;

  if (had_contact == TRUE && has_contact == FALSE)
    {
      GList *removed = NULL;

      /* The Individual has lost its EmpathyContact */
      removed = g_list_prepend (removed, individual);
      g_signal_emit (self, signals[MEMBERS_CHANGED], 0, NULL, NULL, removed,
          TP_CHANNEL_GROUP_CHANGE_REASON_NONE /* FIXME */);
      g_list_free (removed);

      remove_individual (self, individual);
    }
  else if (had_contact == FALSE && has_contact == TRUE)
    {
      GList *added = NULL;

      /* The Individual has gained its first EmpathyContact */
      add_individual (self, individual);

      added = g_list_prepend (added, individual);
      g_signal_emit (self, signals[MEMBERS_CHANGED], 0, NULL, added, NULL,
          TP_CHANNEL_GROUP_CHANGE_REASON_NONE /* FIXME */);
      g_list_free (added);
    }
}
static void
aggregator_individuals_changed_cb (FolksIndividualAggregator *aggregator,
    GeeMultiMap *changes,
    EmpathyIndividualManager *self)
{
  EmpathyIndividualManagerPriv *priv = GET_PRIV (self);
  GeeIterator *iter;
  GeeSet *removed;
  GeeCollection *added;
  GList *added_set = NULL, *added_filtered = NULL, *removed_list = NULL;

  /* We're not interested in the relationships between the added and removed
   * individuals, so just extract collections of them. Note that the added
   * collection may contain duplicates, while the removed set won't. */
  removed = gee_multi_map_get_keys (changes);
  added = gee_multi_map_get_values (changes);

  /* Handle the removals first, as one of the added Individuals might have the
   * same ID as one of the removed Individuals (due to linking). */
  iter = gee_iterable_iterator (GEE_ITERABLE (removed));
  while (gee_iterator_next (iter))
    {
      FolksIndividual *ind = gee_iterator_get (iter);

      if (ind == NULL)
        continue;

      g_signal_handlers_disconnect_by_func (ind,
          individual_notify_personas_cb, self);

      if (g_hash_table_lookup (priv->individuals,
          folks_individual_get_id (ind)) != NULL)
        {
          remove_individual (self, ind);
          removed_list = g_list_prepend (removed_list, ind);
        }

      g_clear_object (&ind);
    }
  g_clear_object (&iter);

  /* Filter the individuals for ones which contain EmpathyContacts */
  iter = gee_iterable_iterator (GEE_ITERABLE (added));
  while (gee_iterator_next (iter))
    {
      FolksIndividual *ind = gee_iterator_get (iter);

      /* Make sure we handle each added individual only once. */
      if (ind == NULL || g_list_find (added_set, ind) != NULL)
        continue;
      added_set = g_list_prepend (added_set, ind);

      g_signal_connect (ind, "notify::personas",
          G_CALLBACK (individual_notify_personas_cb), self);

      if (empathy_folks_individual_contains_contact (ind) == TRUE)
        {
          add_individual (self, ind);
          added_filtered = g_list_prepend (added_filtered, ind);
        }

      g_clear_object (&ind);
    }
  g_clear_object (&iter);

  g_list_free (added_set);

  g_object_unref (added);
  g_object_unref (removed);

  /* Bail if we have no individuals left */
  if (added_filtered == NULL && removed == NULL)
    return;

  added_filtered = g_list_reverse (added_filtered);

  g_signal_emit (self, signals[MEMBERS_CHANGED], 0, NULL,
      added_filtered, removed_list,
      TP_CHANNEL_GROUP_CHANGE_REASON_NONE,
      TRUE);

  g_list_free (added_filtered);
  g_list_free (removed_list);
}