1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2007 Collabora Ltd.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
10 * This program 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 * General Public License for more details.
15 * You should have received a copy of the GNU General Public
16 * License along with this program; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Authors: Xavier Claessens <xclaesse@gmail.com>
27 #include <libtelepathy/tp-constants.h>
29 #include "empathy-contact-manager.h"
30 #include "empathy-contact-list.h"
31 #include "gossip-utils.h"
32 #include "gossip-debug.h"
34 #define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
35 EMPATHY_TYPE_CONTACT_MANAGER, EmpathyContactManagerPriv))
37 #define DEBUG_DOMAIN "ContactManager"
39 struct _EmpathyContactManagerPriv {
46 const gchar *old_group;
47 const gchar *new_group;
48 } ContactManagerRenameGroupData;
51 GossipContact *contact;
53 } ContactManagerFindData;
55 static void empathy_contact_manager_class_init (EmpathyContactManagerClass *klass);
56 static void contact_manager_iface_init (EmpathyContactListIface *iface);
57 static void empathy_contact_manager_init (EmpathyContactManager *manager);
58 static void contact_manager_finalize (GObject *object);
59 static void contact_manager_setup (EmpathyContactList *manager);
60 static GossipContact *contact_manager_find (EmpathyContactList *manager,
62 static void contact_manager_add (EmpathyContactList *manager,
63 GossipContact *contact,
64 const gchar *message);
65 static void contact_manager_remove (EmpathyContactList *manager,
66 GossipContact *contact,
67 const gchar *message);
68 static GList * contact_manager_get_members (EmpathyContactList *manager);
69 static GList * contact_manager_get_local_pending (EmpathyContactList *manager);
70 static void contact_manager_setup_foreach (McAccount *account,
71 EmpathyTpContactList *list,
72 EmpathyContactManager *manager);
73 static gboolean contact_manager_find_foreach (McAccount *account,
74 EmpathyTpContactList *list,
75 ContactManagerFindData *data);
76 static void contact_manager_add_account (EmpathyContactManager *manager,
78 static void contact_manager_added_cb (EmpathyTpContactList *list,
79 GossipContact *contact,
80 EmpathyContactManager *manager);
81 static void contact_manager_removed_cb (EmpathyTpContactList *list,
82 GossipContact *contact,
83 EmpathyContactManager *manager);
84 static void contact_manager_local_pending_cb (EmpathyTpContactList *list,
85 GossipContact *contact,
87 EmpathyContactManager *manager);
88 static void contact_manager_destroy_cb (EmpathyTpContactList *list,
89 EmpathyContactManager *manager);
90 static void contact_manager_rename_group_foreach (McAccount *account,
91 EmpathyTpContactList *list,
92 ContactManagerRenameGroupData *data);
93 static void contact_manager_get_groups_foreach (McAccount *account,
94 EmpathyTpContactList *list,
96 static void contact_manager_get_members_foreach (McAccount *account,
97 EmpathyTpContactList *list,
99 static void contact_manager_get_local_pending_foreach (McAccount *account,
100 EmpathyTpContactList *list,
102 static void contact_manager_status_changed_cb (MissionControl *mc,
103 TelepathyConnectionStatus status,
105 TelepathyConnectionStatusReason reason,
106 const gchar *unique_name,
107 EmpathyContactManager *manager);
109 G_DEFINE_TYPE_WITH_CODE (EmpathyContactManager, empathy_contact_manager, G_TYPE_OBJECT,
110 G_IMPLEMENT_INTERFACE (EMPATHY_TYPE_CONTACT_LIST,
111 contact_manager_iface_init));
114 empathy_contact_manager_class_init (EmpathyContactManagerClass *klass)
116 GObjectClass *object_class = G_OBJECT_CLASS (klass);
118 object_class->finalize = contact_manager_finalize;
120 g_type_class_add_private (object_class, sizeof (EmpathyContactManagerPriv));
124 contact_manager_iface_init (EmpathyContactListIface *iface)
126 iface->setup = contact_manager_setup;
127 iface->find = contact_manager_find;
128 iface->add = contact_manager_add;
129 iface->remove = contact_manager_remove;
130 iface->get_members = contact_manager_get_members;
131 iface->get_local_pending = contact_manager_get_local_pending;
135 empathy_contact_manager_init (EmpathyContactManager *manager)
137 EmpathyContactManagerPriv *priv;
138 GSList *accounts, *l;
140 priv = GET_PRIV (manager);
142 priv->lists = g_hash_table_new_full (gossip_account_hash,
143 gossip_account_equal,
144 (GDestroyNotify) g_object_unref,
145 (GDestroyNotify) g_object_unref);
147 priv->mc = gossip_mission_control_new ();
149 dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->mc),
150 "AccountStatusChanged",
151 G_CALLBACK (contact_manager_status_changed_cb),
154 /* Get ContactList for existing connections */
155 accounts = mission_control_get_online_connections (priv->mc, NULL);
156 for (l = accounts; l; l = l->next) {
160 contact_manager_add_account (manager, account);
162 g_object_unref (account);
164 g_slist_free (accounts);
168 contact_manager_finalize (GObject *object)
170 EmpathyContactManagerPriv *priv;
172 priv = GET_PRIV (object);
174 g_hash_table_destroy (priv->lists);
175 g_object_unref (priv->mc);
178 EmpathyContactManager *
179 empathy_contact_manager_new (void)
181 static EmpathyContactManager *manager = NULL;
184 manager = g_object_new (EMPATHY_TYPE_CONTACT_MANAGER, NULL);
185 g_object_add_weak_pointer (G_OBJECT (manager), (gpointer) &manager);
187 g_object_ref (manager);
194 contact_manager_setup (EmpathyContactList *manager)
196 EmpathyContactManagerPriv *priv;
198 g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
200 priv = GET_PRIV (manager);
207 g_hash_table_foreach (priv->lists,
208 (GHFunc) contact_manager_setup_foreach,
214 static GossipContact *
215 contact_manager_find (EmpathyContactList *manager,
218 EmpathyContactManagerPriv *priv;
219 ContactManagerFindData data;
221 g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
222 g_return_val_if_fail (id != NULL, NULL);
224 priv = GET_PRIV (manager);
229 g_hash_table_find (priv->lists,
230 (GHRFunc) contact_manager_find_foreach,
237 contact_manager_add (EmpathyContactList *manager,
238 GossipContact *contact,
239 const gchar *message)
241 EmpathyContactManagerPriv *priv;
242 EmpathyContactList *list;
245 g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
246 g_return_if_fail (GOSSIP_IS_CONTACT (contact));
248 priv = GET_PRIV (manager);
250 account = gossip_contact_get_account (contact);
251 list = g_hash_table_lookup (priv->lists, account);
254 empathy_contact_list_add (list, contact, message);
259 contact_manager_remove (EmpathyContactList *manager,
260 GossipContact *contact,
261 const gchar *message)
263 EmpathyContactManagerPriv *priv;
264 EmpathyContactList *list;
267 g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
268 g_return_if_fail (GOSSIP_IS_CONTACT (contact));
270 priv = GET_PRIV (manager);
272 account = gossip_contact_get_account (contact);
273 list = g_hash_table_lookup (priv->lists, account);
276 empathy_contact_list_remove (list, contact, message);
281 contact_manager_get_members (EmpathyContactList *manager)
283 EmpathyContactManagerPriv *priv;
284 GList *contacts = NULL;
286 g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
288 priv = GET_PRIV (manager);
290 g_hash_table_foreach (priv->lists,
291 (GHFunc) contact_manager_get_members_foreach,
298 contact_manager_get_local_pending (EmpathyContactList *manager)
300 EmpathyContactManagerPriv *priv;
301 GList *pending = NULL;
303 g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
305 priv = GET_PRIV (manager);
307 g_hash_table_foreach (priv->lists,
308 (GHFunc) contact_manager_get_local_pending_foreach,
314 EmpathyTpContactList *
315 empathy_contact_manager_get_list (EmpathyContactManager *manager,
318 EmpathyContactManagerPriv *priv;
320 g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
321 g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
323 priv = GET_PRIV (manager);
325 return g_hash_table_lookup (priv->lists, account);
329 empathy_contact_manager_get_user (EmpathyContactManager *manager,
332 EmpathyContactManagerPriv *priv;
333 EmpathyTpContactList *list;
335 g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
336 g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
338 priv = GET_PRIV (manager);
340 list = g_hash_table_lookup (priv->lists, account);
346 return empathy_tp_contact_list_get_user (list);
350 empathy_contact_manager_create (EmpathyContactManager *manager,
354 EmpathyContactManagerPriv *priv;
355 EmpathyTpContactList *list;
357 g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
358 g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
359 g_return_val_if_fail (id != NULL, NULL);
361 priv = GET_PRIV (manager);
363 list = g_hash_table_lookup (priv->lists, account);
369 return empathy_tp_contact_list_get_from_id (list, id);
373 empathy_contact_manager_rename_group (EmpathyContactManager *manager,
374 const gchar *old_group,
375 const gchar *new_group)
377 EmpathyContactManagerPriv *priv;
378 ContactManagerRenameGroupData data;
380 g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
381 g_return_if_fail (old_group != NULL);
382 g_return_if_fail (new_group != NULL);
384 priv = GET_PRIV (manager);
386 data.old_group = old_group;
387 data.new_group = new_group;
389 g_hash_table_foreach (priv->lists,
390 (GHFunc) contact_manager_rename_group_foreach,
395 empathy_contact_manager_get_groups (EmpathyContactManager *manager)
397 EmpathyContactManagerPriv *priv;
398 GList *groups = NULL;
400 g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
402 priv = GET_PRIV (manager);
404 g_hash_table_foreach (priv->lists,
405 (GHFunc) contact_manager_get_groups_foreach,
412 contact_manager_setup_foreach (McAccount *account,
413 EmpathyTpContactList *list,
414 EmpathyContactManager *manager)
416 empathy_contact_list_setup (EMPATHY_CONTACT_LIST (list));
420 contact_manager_find_foreach (McAccount *account,
421 EmpathyTpContactList *list,
422 ContactManagerFindData *data)
424 data->contact = empathy_contact_list_find (EMPATHY_CONTACT_LIST (list),
435 contact_manager_add_account (EmpathyContactManager *manager,
438 EmpathyContactManagerPriv *priv;
439 EmpathyTpContactList *list;
441 priv = GET_PRIV (manager);
443 if (g_hash_table_lookup (priv->lists, account)) {
447 gossip_debug (DEBUG_DOMAIN, "Adding new account: %s",
448 mc_account_get_display_name (account));
450 list = empathy_tp_contact_list_new (account);
455 g_hash_table_insert (priv->lists, g_object_ref (account), list);
457 /* Connect signals */
458 g_signal_connect (list, "contact-added",
459 G_CALLBACK (contact_manager_added_cb),
461 g_signal_connect (list, "contact-removed",
462 G_CALLBACK (contact_manager_removed_cb),
464 g_signal_connect (list, "local-pending",
465 G_CALLBACK (contact_manager_local_pending_cb),
467 g_signal_connect (list, "destroy",
468 G_CALLBACK (contact_manager_destroy_cb),
472 empathy_contact_list_setup (EMPATHY_CONTACT_LIST (list));
477 contact_manager_added_cb (EmpathyTpContactList *list,
478 GossipContact *contact,
479 EmpathyContactManager *manager)
481 g_signal_emit_by_name (manager, "contact-added", contact);
485 contact_manager_removed_cb (EmpathyTpContactList *list,
486 GossipContact *contact,
487 EmpathyContactManager *manager)
489 g_signal_emit_by_name (manager, "contact-removed", contact);
493 contact_manager_local_pending_cb (EmpathyTpContactList *list,
494 GossipContact *contact,
495 const gchar *message,
496 EmpathyContactManager *manager)
498 g_signal_emit_by_name (manager, "local-pending", contact, message);
502 contact_manager_destroy_cb (EmpathyTpContactList *list,
503 EmpathyContactManager *manager)
505 EmpathyContactManagerPriv *priv;
508 priv = GET_PRIV (manager);
510 account = empathy_tp_contact_list_get_account (list);
512 gossip_debug (DEBUG_DOMAIN, "Removing account: %s",
513 mc_account_get_display_name (account));
515 /* Disconnect signals from the list */
516 g_signal_handlers_disconnect_by_func (list,
517 contact_manager_added_cb,
519 g_signal_handlers_disconnect_by_func (list,
520 contact_manager_removed_cb,
522 g_signal_handlers_disconnect_by_func (list,
523 contact_manager_local_pending_cb,
525 g_signal_handlers_disconnect_by_func (list,
526 contact_manager_destroy_cb,
529 g_hash_table_remove (priv->lists, account);
533 contact_manager_rename_group_foreach (McAccount *account,
534 EmpathyTpContactList *list,
535 ContactManagerRenameGroupData *data)
537 empathy_tp_contact_list_rename_group (list,
543 contact_manager_get_groups_foreach (McAccount *account,
544 EmpathyTpContactList *list,
549 groups = empathy_tp_contact_list_get_groups (list);
550 for (l = groups; l; l = l->next) {
551 if (!g_list_find_custom (*all_groups,
553 (GCompareFunc) strcmp)) {
554 *all_groups = g_list_append (*all_groups,
560 g_list_free (groups);
564 contact_manager_get_members_foreach (McAccount *account,
565 EmpathyTpContactList *list,
570 l = empathy_contact_list_get_members (EMPATHY_CONTACT_LIST (list));
571 *contacts = g_list_concat (*contacts, l);
575 contact_manager_get_local_pending_foreach (McAccount *account,
576 EmpathyTpContactList *list,
581 l = empathy_contact_list_get_local_pending (EMPATHY_CONTACT_LIST (list));
582 *contacts = g_list_concat (*contacts, l);
586 contact_manager_status_changed_cb (MissionControl *mc,
587 TelepathyConnectionStatus status,
589 TelepathyConnectionStatusReason reason,
590 const gchar *unique_name,
591 EmpathyContactManager *manager)
593 EmpathyContactManagerPriv *priv;
596 priv = GET_PRIV (manager);
598 if (status != TP_CONN_STATUS_CONNECTED) {
599 /* We only care about newly connected accounts */
603 account = mc_account_lookup (unique_name);
604 contact_manager_add_account (manager, account);
606 g_object_unref (account);