~ubuntu-branches/ubuntu/natty/empathy/natty

« back to all changes in this revision

Viewing changes to .pc/00git_folks_api.patch/libempathy/empathy-individual-manager.c

  • Committer: Bazaar Package Importer
  • Author(s): Robert Ancell, Omer Akram
  • Date: 2011-01-06 14:32:31 UTC
  • Revision ID: james.westby@ubuntu.com-20110106143231-ol0gyfqi7h1ch8kv
Tags: 2.32.2-0ubuntu3
* debian/patches/00git_folks_api.patch:
  - Update to latest folks API

[ Omer Akram ]
* debian/patches/enable_pidgin_imported_contacts.patch:
  - Enable pidgin imported accounts by default. (LP: #622215)
* debian/patches/reword_subscription_dailog_to_be_less_technical.patch:
  - Reword subscription request dialog to be less technical. (LP: #670197)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 
2
/*
 
3
 * Copyright (C) 2007-2010 Collabora Ltd.
 
4
 *
 
5
 * This library is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU Lesser General Public
 
7
 * License as published by the Free Software Foundation; either
 
8
 * version 2.1 of the License, or (at your option) any later version.
 
9
 *
 
10
 * This library is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
 * Lesser General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU Lesser General Public
 
16
 * License along with this library; if not, write to the Free Software
 
17
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
18
 *
 
19
 * Authors: Xavier Claessens <xclaesse@gmail.com>
 
20
 *          Travis Reitter <travis.reitter@collabora.co.uk>
 
21
 */
 
22
 
 
23
#include <config.h>
 
24
 
 
25
#include <string.h>
 
26
 
 
27
#include <telepathy-glib/account-manager.h>
 
28
#include <telepathy-glib/enums.h>
 
29
#include <telepathy-glib/proxy-subclass.h>
 
30
#include <telepathy-glib/util.h>
 
31
 
 
32
#include <folks/folks.h>
 
33
 
 
34
#include <extensions/extensions.h>
 
35
 
 
36
#include "empathy-individual-manager.h"
 
37
#include "empathy-contact-manager.h"
 
38
#include "empathy-contact-list.h"
 
39
#include "empathy-marshal.h"
 
40
#include "empathy-utils.h"
 
41
 
 
42
#define DEBUG_FLAG EMPATHY_DEBUG_CONTACT
 
43
#include "empathy-debug.h"
 
44
 
 
45
#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyIndividualManager)
 
46
 
 
47
/* This class only stores and refs Individuals who contain an EmpathyContact.
 
48
 *
 
49
 * This class merely forwards along signals from the aggregator and individuals
 
50
 * and wraps aggregator functions for other client code. */
 
51
typedef struct
 
52
{
 
53
  FolksIndividualAggregator *aggregator;
 
54
  EmpathyContactManager *contact_manager;
 
55
  GHashTable *individuals; /* Individual.id -> Individual */
 
56
} EmpathyIndividualManagerPriv;
 
57
 
 
58
enum
 
59
{
 
60
  FAVOURITES_CHANGED,
 
61
  GROUPS_CHANGED,
 
62
  MEMBERS_CHANGED,
 
63
  LAST_SIGNAL
 
64
};
 
65
 
 
66
static guint signals[LAST_SIGNAL] = { 0 };
 
67
 
 
68
G_DEFINE_TYPE (EmpathyIndividualManager, empathy_individual_manager,
 
69
    G_TYPE_OBJECT);
 
70
 
 
71
static EmpathyIndividualManager *manager_singleton = NULL;
 
72
 
 
73
static void
 
74
individual_group_changed_cb (FolksIndividual *individual,
 
75
    gchar *group,
 
76
    gboolean is_member,
 
77
    EmpathyIndividualManager *self)
 
78
{
 
79
  g_signal_emit (self, signals[GROUPS_CHANGED], 0, individual, group,
 
80
      is_member);
 
81
}
 
82
 
 
83
static void
 
84
individual_notify_is_favourite_cb (FolksIndividual *individual,
 
85
    GParamSpec *pspec,
 
86
    EmpathyIndividualManager *self)
 
87
{
 
88
  gboolean is_favourite = folks_favourite_get_is_favourite (
 
89
      FOLKS_FAVOURITE (individual));
 
90
  g_signal_emit (self, signals[FAVOURITES_CHANGED], 0, individual,
 
91
      is_favourite);
 
92
}
 
93
 
 
94
static void
 
95
add_individual (EmpathyIndividualManager *self, FolksIndividual *individual)
 
96
{
 
97
  EmpathyIndividualManagerPriv *priv = GET_PRIV (self);
 
98
 
 
99
  g_hash_table_insert (priv->individuals,
 
100
      (gpointer) folks_individual_get_id (individual),
 
101
      g_object_ref (individual));
 
102
 
 
103
  g_signal_connect (individual, "group-changed",
 
104
      G_CALLBACK (individual_group_changed_cb), self);
 
105
  g_signal_connect (individual, "notify::is-favourite",
 
106
      G_CALLBACK (individual_notify_is_favourite_cb), self);
 
107
}
 
108
 
 
109
static void
 
110
remove_individual (EmpathyIndividualManager *self, FolksIndividual *individual)
 
111
{
 
112
  EmpathyIndividualManagerPriv *priv = GET_PRIV (self);
 
113
 
 
114
  g_signal_handlers_disconnect_by_func (individual,
 
115
      individual_group_changed_cb, self);
 
116
  g_signal_handlers_disconnect_by_func (individual,
 
117
      individual_notify_is_favourite_cb, self);
 
118
 
 
119
  g_hash_table_remove (priv->individuals, folks_individual_get_id (individual));
 
120
}
 
121
 
 
122
/* This is emitted for *all* individuals in the individual aggregator (not
 
123
 * just the ones we keep a reference to), to allow for the case where a new
 
124
 * individual doesn't contain an EmpathyContact, but later has a persona added
 
125
 * which does. */
 
126
static void
 
127
individual_notify_personas_cb (FolksIndividual *individual,
 
128
    GParamSpec *pspec,
 
129
    EmpathyIndividualManager *self)
 
130
{
 
131
  EmpathyIndividualManagerPriv *priv = GET_PRIV (self);
 
132
 
 
133
  const gchar *id = folks_individual_get_id (individual);
 
134
  gboolean has_contact = empathy_folks_individual_contains_contact (individual);
 
135
  gboolean had_contact = (g_hash_table_lookup (priv->individuals,
 
136
      id) != NULL) ? TRUE : FALSE;
 
137
 
 
138
  if (had_contact == TRUE && has_contact == FALSE)
 
139
    {
 
140
      GList *removed = NULL;
 
141
 
 
142
      /* The Individual has lost its EmpathyContact */
 
143
      removed = g_list_prepend (removed, individual);
 
144
      g_signal_emit (self, signals[MEMBERS_CHANGED], 0, NULL, NULL, removed,
 
145
          TP_CHANNEL_GROUP_CHANGE_REASON_NONE /* FIXME */);
 
146
      g_list_free (removed);
 
147
 
 
148
      remove_individual (self, individual);
 
149
    }
 
150
  else if (had_contact == FALSE && has_contact == TRUE)
 
151
    {
 
152
      GList *added = NULL;
 
153
 
 
154
      /* The Individual has gained its first EmpathyContact */
 
155
      add_individual (self, individual);
 
156
 
 
157
      added = g_list_prepend (added, individual);
 
158
      g_signal_emit (self, signals[MEMBERS_CHANGED], 0, NULL, added, NULL,
 
159
          TP_CHANNEL_GROUP_CHANGE_REASON_NONE /* FIXME */);
 
160
      g_list_free (added);
 
161
    }
 
162
}
 
163
 
 
164
static void
 
165
aggregator_individuals_changed_cb (FolksIndividualAggregator *aggregator,
 
166
    GList *added,
 
167
    GList *removed,
 
168
    const char *message,
 
169
    FolksPersona *actor,
 
170
    guint reason,
 
171
    EmpathyIndividualManager *self)
 
172
{
 
173
  EmpathyIndividualManagerPriv *priv = GET_PRIV (self);
 
174
  GList *l, *added_filtered = NULL;
 
175
 
 
176
  /* Handle the removals first, as one of the added Individuals might have the
 
177
   * same ID as one of the removed Individuals (due to linking). */
 
178
  for (l = removed; l; l = l->next)
 
179
    {
 
180
      FolksIndividual *ind = FOLKS_INDIVIDUAL (l->data);
 
181
 
 
182
      g_signal_handlers_disconnect_by_func (ind,
 
183
          individual_notify_personas_cb, self);
 
184
 
 
185
      if (g_hash_table_lookup (priv->individuals,
 
186
          folks_individual_get_id (ind)) != NULL)
 
187
        remove_individual (self, ind);
 
188
    }
 
189
 
 
190
  /* Filter the individuals for ones which contain EmpathyContacts */
 
191
  for (l = added; l; l = l->next)
 
192
    {
 
193
      FolksIndividual *ind = FOLKS_INDIVIDUAL (l->data);
 
194
 
 
195
      g_signal_connect (ind, "notify::personas",
 
196
          G_CALLBACK (individual_notify_personas_cb), self);
 
197
 
 
198
      if (empathy_folks_individual_contains_contact (ind) == TRUE)
 
199
        {
 
200
          add_individual (self, ind);
 
201
          added_filtered = g_list_prepend (added_filtered, ind);
 
202
        }
 
203
    }
 
204
 
 
205
  /* Bail if we have no individuals left */
 
206
  if (added_filtered == NULL && removed == NULL)
 
207
    return;
 
208
 
 
209
  added_filtered = g_list_reverse (added_filtered);
 
210
 
 
211
  g_signal_emit (self, signals[MEMBERS_CHANGED], 0, message,
 
212
      added_filtered, removed,
 
213
      tp_channel_group_change_reason_from_folks_groups_change_reason (reason),
 
214
      TRUE);
 
215
 
 
216
  g_list_free (added_filtered);
 
217
}
 
218
 
 
219
static void
 
220
individual_manager_dispose (GObject *object)
 
221
{
 
222
  EmpathyIndividualManagerPriv *priv = GET_PRIV (object);
 
223
 
 
224
  g_hash_table_destroy (priv->individuals);
 
225
  tp_clear_object (&priv->contact_manager);
 
226
  tp_clear_object (&priv->aggregator);
 
227
 
 
228
  G_OBJECT_CLASS (empathy_individual_manager_parent_class)->dispose (object);
 
229
}
 
230
 
 
231
static GObject *
 
232
individual_manager_constructor (GType type,
 
233
    guint n_props,
 
234
    GObjectConstructParam *props)
 
235
{
 
236
  GObject *retval;
 
237
 
 
238
  if (manager_singleton)
 
239
    {
 
240
      retval = g_object_ref (manager_singleton);
 
241
    }
 
242
  else
 
243
    {
 
244
      retval =
 
245
          G_OBJECT_CLASS (empathy_individual_manager_parent_class)->
 
246
          constructor (type, n_props, props);
 
247
 
 
248
      manager_singleton = EMPATHY_INDIVIDUAL_MANAGER (retval);
 
249
      g_object_add_weak_pointer (retval, (gpointer) & manager_singleton);
 
250
    }
 
251
 
 
252
  return retval;
 
253
}
 
254
 
 
255
/**
 
256
 * empathy_individual_manager_initialized:
 
257
 *
 
258
 * Reports whether or not the singleton has already been created.
 
259
 *
 
260
 * There can be instances where you want to access the #EmpathyIndividualManager
 
261
 * only if it has been set up for this process.
 
262
 *
 
263
 * Returns: %TRUE if the #EmpathyIndividualManager singleton has previously
 
264
 * been initialized.
 
265
 */
 
266
gboolean
 
267
empathy_individual_manager_initialized (void)
 
268
{
 
269
  return (manager_singleton != NULL);
 
270
}
 
271
 
 
272
static void
 
273
empathy_individual_manager_class_init (EmpathyIndividualManagerClass *klass)
 
274
{
 
275
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
276
 
 
277
  object_class->dispose = individual_manager_dispose;
 
278
  object_class->constructor = individual_manager_constructor;
 
279
 
 
280
  signals[GROUPS_CHANGED] =
 
281
      g_signal_new ("groups-changed",
 
282
          G_TYPE_FROM_CLASS (klass),
 
283
          G_SIGNAL_RUN_LAST,
 
284
          0,
 
285
          NULL, NULL,
 
286
          _empathy_marshal_VOID__OBJECT_STRING_BOOLEAN,
 
287
          G_TYPE_NONE, 3, FOLKS_TYPE_INDIVIDUAL, G_TYPE_STRING, G_TYPE_BOOLEAN);
 
288
 
 
289
  signals[FAVOURITES_CHANGED] =
 
290
      g_signal_new ("favourites-changed",
 
291
          G_TYPE_FROM_CLASS (klass),
 
292
          G_SIGNAL_RUN_LAST,
 
293
          0,
 
294
          NULL, NULL,
 
295
          _empathy_marshal_VOID__OBJECT_BOOLEAN,
 
296
          G_TYPE_NONE, 2, FOLKS_TYPE_INDIVIDUAL, G_TYPE_BOOLEAN);
 
297
 
 
298
  signals[MEMBERS_CHANGED] =
 
299
      g_signal_new ("members-changed",
 
300
          G_TYPE_FROM_CLASS (klass),
 
301
          G_SIGNAL_RUN_LAST,
 
302
          0,
 
303
          NULL, NULL,
 
304
          _empathy_marshal_VOID__STRING_OBJECT_OBJECT_UINT,
 
305
          G_TYPE_NONE,
 
306
          4, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_UINT);
 
307
 
 
308
  g_type_class_add_private (object_class,
 
309
      sizeof (EmpathyIndividualManagerPriv));
 
310
}
 
311
 
 
312
static void
 
313
empathy_individual_manager_init (EmpathyIndividualManager *self)
 
314
{
 
315
  EmpathyIndividualManagerPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
 
316
      EMPATHY_TYPE_INDIVIDUAL_MANAGER, EmpathyIndividualManagerPriv);
 
317
 
 
318
  self->priv = priv;
 
319
  priv->contact_manager = empathy_contact_manager_dup_singleton ();
 
320
  priv->individuals = g_hash_table_new_full (g_str_hash, g_str_equal,
 
321
      NULL, g_object_unref);
 
322
 
 
323
  priv->aggregator = folks_individual_aggregator_new ();
 
324
  g_signal_connect (priv->aggregator, "individuals-changed",
 
325
      G_CALLBACK (aggregator_individuals_changed_cb), self);
 
326
  folks_individual_aggregator_prepare (priv->aggregator, NULL, NULL);
 
327
}
 
328
 
 
329
EmpathyIndividualManager *
 
330
empathy_individual_manager_dup_singleton (void)
 
331
{
 
332
  return g_object_new (EMPATHY_TYPE_INDIVIDUAL_MANAGER, NULL);
 
333
}
 
334
 
 
335
GList *
 
336
empathy_individual_manager_get_members (EmpathyIndividualManager *self)
 
337
{
 
338
  EmpathyIndividualManagerPriv *priv = GET_PRIV (self);
 
339
 
 
340
  g_return_val_if_fail (EMPATHY_IS_INDIVIDUAL_MANAGER (self), NULL);
 
341
 
 
342
  return g_hash_table_get_values (priv->individuals);
 
343
}
 
344
 
 
345
FolksIndividual *
 
346
empathy_individual_manager_lookup_member (EmpathyIndividualManager *self,
 
347
    const gchar *id)
 
348
{
 
349
  EmpathyIndividualManagerPriv *priv = GET_PRIV (self);
 
350
 
 
351
  g_return_val_if_fail (EMPATHY_IS_INDIVIDUAL_MANAGER (self), NULL);
 
352
 
 
353
  return g_hash_table_lookup (priv->individuals, id);
 
354
}
 
355
 
 
356
static void
 
357
aggregator_add_persona_from_details_cb (GObject *source,
 
358
    GAsyncResult *result,
 
359
    gpointer user_data)
 
360
{
 
361
  FolksIndividualAggregator *aggregator = FOLKS_INDIVIDUAL_AGGREGATOR (source);
 
362
  EmpathyContact *contact = EMPATHY_CONTACT (user_data);
 
363
  FolksPersona *persona;
 
364
  GError *error = NULL;
 
365
 
 
366
  persona = folks_individual_aggregator_add_persona_from_details_finish (
 
367
      aggregator, result, &error);
 
368
  if (error != NULL)
 
369
    {
 
370
      g_warning ("failed to add individual from contact: %s", error->message);
 
371
      g_clear_error (&error);
 
372
    }
 
373
 
 
374
  /* The persona can be NULL even if there wasn't an error, if the persona was
 
375
   * already in the contact list */
 
376
  if (persona != NULL)
 
377
    {
 
378
      /* Set the contact's persona */
 
379
      empathy_contact_set_persona (contact, persona);
 
380
      g_object_unref (persona);
 
381
    }
 
382
 
 
383
  g_object_unref (contact);
 
384
}
 
385
 
 
386
void
 
387
empathy_individual_manager_add_from_contact (EmpathyIndividualManager *self,
 
388
    EmpathyContact *contact)
 
389
{
 
390
  EmpathyIndividualManagerPriv *priv;
 
391
  GHashTable* details;
 
392
  TpAccount *account;
 
393
  const gchar *store_id;
 
394
 
 
395
  g_return_if_fail (EMPATHY_IS_INDIVIDUAL_MANAGER (self));
 
396
  g_return_if_fail (EMPATHY_IS_CONTACT (contact));
 
397
 
 
398
  priv = GET_PRIV (self);
 
399
 
 
400
  /* We need to ref the contact since otherwise its linked TpHandle will be
 
401
   * destroyed. */
 
402
  g_object_ref (contact);
 
403
 
 
404
  DEBUG ("adding individual from contact %s (%s)",
 
405
      empathy_contact_get_id (contact), empathy_contact_get_alias (contact));
 
406
 
 
407
  account = empathy_contact_get_account (contact);
 
408
  store_id = tp_proxy_get_object_path (TP_PROXY (account));
 
409
 
 
410
  details = tp_asv_new (
 
411
      "contact", G_TYPE_STRING, empathy_contact_get_id (contact),
 
412
      NULL);
 
413
 
 
414
  folks_individual_aggregator_add_persona_from_details (
 
415
      priv->aggregator, NULL, "telepathy", store_id, details,
 
416
      aggregator_add_persona_from_details_cb, contact);
 
417
 
 
418
  g_hash_table_destroy (details);
 
419
}
 
420
 
 
421
static void
 
422
aggregator_remove_individual_cb (GObject *source,
 
423
    GAsyncResult *result,
 
424
    gpointer user_data)
 
425
{
 
426
  FolksIndividualAggregator *aggregator = FOLKS_INDIVIDUAL_AGGREGATOR (source);
 
427
  GError *error = NULL;
 
428
 
 
429
  folks_individual_aggregator_remove_individual_finish (
 
430
      aggregator, result, &error);
 
431
  if (error != NULL)
 
432
    {
 
433
      g_warning ("failed to remove individual: %s", error->message);
 
434
      g_clear_error (&error);
 
435
    }
 
436
}
 
437
 
 
438
/**
 
439
 * Removes the inner contact from the server (and thus the Individual). Not
 
440
 * meant for de-shelling inner personas from an Individual.
 
441
 */
 
442
void
 
443
empathy_individual_manager_remove (EmpathyIndividualManager *self,
 
444
    FolksIndividual *individual,
 
445
    const gchar *message)
 
446
{
 
447
  EmpathyIndividualManagerPriv *priv;
 
448
 
 
449
  g_return_if_fail (EMPATHY_IS_INDIVIDUAL_MANAGER (self));
 
450
  g_return_if_fail (FOLKS_IS_INDIVIDUAL (individual));
 
451
 
 
452
  priv = GET_PRIV (self);
 
453
 
 
454
  DEBUG ("removing individual %s (%s)",
 
455
      folks_individual_get_id (individual),
 
456
      folks_aliasable_get_alias (FOLKS_ALIASABLE (individual)));
 
457
 
 
458
  folks_individual_aggregator_remove_individual (priv->aggregator, individual,
 
459
      aggregator_remove_individual_cb, self);
 
460
}
 
461
 
 
462
static void
 
463
groups_change_group_cb (GObject *source,
 
464
    GAsyncResult *result,
 
465
    gpointer user_data)
 
466
{
 
467
  FolksGroupable *groupable = FOLKS_GROUPABLE (source);
 
468
  GError *error = NULL;
 
469
 
 
470
  folks_groupable_change_group_finish (groupable, result, &error);
 
471
  if (error != NULL)
 
472
    {
 
473
      g_warning ("failed to change group: %s", error->message);
 
474
      g_clear_error (&error);
 
475
    }
 
476
}
 
477
 
 
478
static void
 
479
remove_group_cb (const gchar *id,
 
480
    FolksIndividual *individual,
 
481
    const gchar *group)
 
482
{
 
483
  folks_groupable_change_group (FOLKS_GROUPABLE (individual), group, FALSE,
 
484
      groups_change_group_cb, NULL);
 
485
}
 
486
 
 
487
void
 
488
empathy_individual_manager_remove_group (EmpathyIndividualManager *manager,
 
489
    const gchar *group)
 
490
{
 
491
  EmpathyIndividualManagerPriv *priv;
 
492
 
 
493
  g_return_if_fail (EMPATHY_IS_INDIVIDUAL_MANAGER (manager));
 
494
  g_return_if_fail (group != NULL);
 
495
 
 
496
  priv = GET_PRIV (manager);
 
497
 
 
498
  DEBUG ("removing group %s", group);
 
499
 
 
500
  /* Remove every individual from the group */
 
501
  g_hash_table_foreach (priv->individuals, (GHFunc) remove_group_cb,
 
502
      (gpointer) group);
 
503
}
 
504
 
 
505
EmpathyIndividualManagerFlags
 
506
empathy_individual_manager_get_flags_for_connection (
 
507
    EmpathyIndividualManager *self,
 
508
    TpConnection *connection)
 
509
{
 
510
  EmpathyIndividualManagerPriv *priv;
 
511
  EmpathyContactListFlags list_flags;
 
512
  EmpathyIndividualManagerFlags flags;
 
513
 
 
514
  g_return_val_if_fail (EMPATHY_IS_INDIVIDUAL_MANAGER (self),
 
515
      EMPATHY_INDIVIDUAL_MANAGER_NO_FLAGS);
 
516
 
 
517
  priv = GET_PRIV (self);
 
518
 
 
519
  list_flags = empathy_contact_manager_get_flags_for_connection (
 
520
    priv->contact_manager, connection);
 
521
 
 
522
  flags = EMPATHY_INDIVIDUAL_MANAGER_NO_FLAGS;
 
523
  if (list_flags & EMPATHY_CONTACT_LIST_CAN_ADD)
 
524
    flags |= EMPATHY_INDIVIDUAL_MANAGER_CAN_ADD;
 
525
  if (list_flags & EMPATHY_CONTACT_LIST_CAN_REMOVE)
 
526
    flags |= EMPATHY_INDIVIDUAL_MANAGER_CAN_REMOVE;
 
527
  if (list_flags & EMPATHY_CONTACT_LIST_CAN_ALIAS)
 
528
    flags |= EMPATHY_INDIVIDUAL_MANAGER_CAN_ALIAS;
 
529
  if (list_flags & EMPATHY_CONTACT_LIST_CAN_GROUP)
 
530
    flags |= EMPATHY_INDIVIDUAL_MANAGER_CAN_GROUP;
 
531
 
 
532
  return flags;
 
533
}
 
534
 
 
535
static void
 
536
link_personas_cb (FolksIndividualAggregator *aggregator,
 
537
    GAsyncResult *async_result,
 
538
    gpointer user_data)
 
539
{
 
540
  GError *error = NULL;
 
541
 
 
542
  folks_individual_aggregator_link_personas_finish (aggregator, async_result,
 
543
      &error);
 
544
 
 
545
  if (error != NULL)
 
546
    {
 
547
      g_warning ("Failed to link personas: %s", error->message);
 
548
      g_clear_error (&error);
 
549
    }
 
550
}
 
551
 
 
552
void
 
553
empathy_individual_manager_link_personas (EmpathyIndividualManager *self,
 
554
    GList *personas)
 
555
{
 
556
  EmpathyIndividualManagerPriv *priv;
 
557
 
 
558
  g_return_if_fail (EMPATHY_IS_INDIVIDUAL_MANAGER (self));
 
559
  g_return_if_fail (personas != NULL);
 
560
 
 
561
  priv = GET_PRIV (self);
 
562
 
 
563
  DEBUG ("Linking %u personas", g_list_length (personas));
 
564
 
 
565
  folks_individual_aggregator_link_personas (priv->aggregator, personas,
 
566
      (GAsyncReadyCallback) link_personas_cb, NULL);
 
567
}
 
568
 
 
569
static void
 
570
unlink_individual_cb (FolksIndividualAggregator *aggregator,
 
571
    GAsyncResult *async_result,
 
572
    gpointer user_data)
 
573
{
 
574
  GError *error = NULL;
 
575
 
 
576
  folks_individual_aggregator_unlink_individual_finish (aggregator,
 
577
      async_result, &error);
 
578
 
 
579
  if (error != NULL)
 
580
    {
 
581
      g_warning ("Failed to unlink individual: %s", error->message);
 
582
      g_clear_error (&error);
 
583
    }
 
584
}
 
585
 
 
586
void
 
587
empathy_individual_manager_unlink_individual (EmpathyIndividualManager *self,
 
588
    FolksIndividual *individual)
 
589
{
 
590
  EmpathyIndividualManagerPriv *priv;
 
591
 
 
592
  g_return_if_fail (EMPATHY_IS_INDIVIDUAL_MANAGER (self));
 
593
  g_return_if_fail (FOLKS_IS_INDIVIDUAL (individual));
 
594
 
 
595
  priv = GET_PRIV (self);
 
596
 
 
597
  DEBUG ("Unlinking individual '%s'", folks_individual_get_id (individual));
 
598
 
 
599
  folks_individual_aggregator_unlink_individual (priv->aggregator, individual,
 
600
      (GAsyncReadyCallback) unlink_individual_cb, NULL);
 
601
}