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_contacts (EmpathyContactList *manager);
69 static void contact_manager_setup_foreach (McAccount *account,
70 EmpathyTpContactList *list,
71 EmpathyContactManager *manager);
72 static gboolean contact_manager_find_foreach (McAccount *account,
73 EmpathyTpContactList *list,
74 ContactManagerFindData *data);
75 static void contact_manager_add_account (EmpathyContactManager *manager,
77 static void contact_manager_added_cb (EmpathyTpContactList *list,
78 GossipContact *contact,
79 EmpathyContactManager *manager);
80 static void contact_manager_removed_cb (EmpathyTpContactList *list,
81 GossipContact *contact,
82 EmpathyContactManager *manager);
83 static void contact_manager_destroy_cb (EmpathyTpContactList *list,
84 EmpathyContactManager *manager);
85 static void contact_manager_rename_group_foreach (McAccount *account,
86 EmpathyTpContactList *list,
87 ContactManagerRenameGroupData *data);
88 static void contact_manager_get_groups_foreach (McAccount *account,
89 EmpathyTpContactList *list,
91 static void contact_manager_get_contacts_foreach (McAccount *account,
92 EmpathyTpContactList *list,
94 static void contact_manager_status_changed_cb (MissionControl *mc,
95 TelepathyConnectionStatus status,
97 TelepathyConnectionStatusReason reason,
98 const gchar *unique_name,
99 EmpathyContactManager *manager);
101 G_DEFINE_TYPE_WITH_CODE (EmpathyContactManager, empathy_contact_manager, G_TYPE_OBJECT,
102 G_IMPLEMENT_INTERFACE (EMPATHY_TYPE_CONTACT_LIST,
103 contact_manager_iface_init));
106 empathy_contact_manager_class_init (EmpathyContactManagerClass *klass)
108 GObjectClass *object_class = G_OBJECT_CLASS (klass);
110 object_class->finalize = contact_manager_finalize;
112 g_type_class_add_private (object_class, sizeof (EmpathyContactManagerPriv));
116 contact_manager_iface_init (EmpathyContactListIface *iface)
118 iface->setup = contact_manager_setup;
119 iface->find = contact_manager_find;
120 iface->add = contact_manager_add;
121 iface->remove = contact_manager_remove;
122 iface->get_contacts = contact_manager_get_contacts;
126 empathy_contact_manager_init (EmpathyContactManager *manager)
128 EmpathyContactManagerPriv *priv;
129 GSList *accounts, *l;
131 priv = GET_PRIV (manager);
133 priv->lists = g_hash_table_new_full (gossip_account_hash,
134 gossip_account_equal,
135 (GDestroyNotify) g_object_unref,
136 (GDestroyNotify) g_object_unref);
138 priv->mc = gossip_mission_control_new ();
140 dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->mc),
141 "AccountStatusChanged",
142 G_CALLBACK (contact_manager_status_changed_cb),
145 /* Get ContactList for existing connections */
146 accounts = mission_control_get_online_connections (priv->mc, NULL);
147 for (l = accounts; l; l = l->next) {
151 contact_manager_add_account (manager, account);
153 g_object_unref (account);
155 g_slist_free (accounts);
159 contact_manager_finalize (GObject *object)
161 EmpathyContactManagerPriv *priv;
163 priv = GET_PRIV (object);
165 g_hash_table_destroy (priv->lists);
166 g_object_unref (priv->mc);
169 EmpathyContactManager *
170 empathy_contact_manager_new (void)
172 static EmpathyContactManager *manager = NULL;
175 manager = g_object_new (EMPATHY_TYPE_CONTACT_MANAGER, NULL);
176 g_object_add_weak_pointer (G_OBJECT (manager), (gpointer) &manager);
178 g_object_ref (manager);
185 contact_manager_setup (EmpathyContactList *manager)
187 EmpathyContactManagerPriv *priv;
189 g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
191 priv = GET_PRIV (manager);
198 g_hash_table_foreach (priv->lists,
199 (GHFunc) contact_manager_setup_foreach,
205 static GossipContact *
206 contact_manager_find (EmpathyContactList *manager,
209 EmpathyContactManagerPriv *priv;
210 ContactManagerFindData data;
212 g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
213 g_return_val_if_fail (id != NULL, NULL);
215 priv = GET_PRIV (manager);
220 g_hash_table_find (priv->lists,
221 (GHRFunc) contact_manager_find_foreach,
228 contact_manager_add (EmpathyContactList *manager,
229 GossipContact *contact,
230 const gchar *message)
232 EmpathyContactManagerPriv *priv;
233 EmpathyContactList *list;
236 g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
237 g_return_if_fail (GOSSIP_IS_CONTACT (contact));
239 priv = GET_PRIV (manager);
241 account = gossip_contact_get_account (contact);
242 list = g_hash_table_lookup (priv->lists, account);
245 empathy_contact_list_add (list, contact, message);
250 contact_manager_remove (EmpathyContactList *manager,
251 GossipContact *contact,
252 const gchar *message)
254 EmpathyContactManagerPriv *priv;
255 EmpathyContactList *list;
258 g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
259 g_return_if_fail (GOSSIP_IS_CONTACT (contact));
261 priv = GET_PRIV (manager);
263 account = gossip_contact_get_account (contact);
264 list = g_hash_table_lookup (priv->lists, account);
267 empathy_contact_list_remove (list, contact, message);
272 contact_manager_get_contacts (EmpathyContactList *manager)
274 EmpathyContactManagerPriv *priv;
275 GList *contacts = NULL;
277 g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
279 priv = GET_PRIV (manager);
281 g_hash_table_foreach (priv->lists,
282 (GHFunc) contact_manager_get_contacts_foreach,
288 EmpathyTpContactList *
289 empathy_contact_manager_get_list (EmpathyContactManager *manager,
292 EmpathyContactManagerPriv *priv;
294 g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
295 g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
297 priv = GET_PRIV (manager);
299 return g_hash_table_lookup (priv->lists, account);
303 empathy_contact_manager_get_user (EmpathyContactManager *manager,
306 EmpathyContactManagerPriv *priv;
307 EmpathyTpContactList *list;
309 g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
310 g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
312 priv = GET_PRIV (manager);
314 list = g_hash_table_lookup (priv->lists, account);
320 return empathy_tp_contact_list_get_user (list);
324 empathy_contact_manager_create (EmpathyContactManager *manager,
328 EmpathyContactManagerPriv *priv;
329 EmpathyTpContactList *list;
331 g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
332 g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
333 g_return_val_if_fail (id != NULL, NULL);
335 priv = GET_PRIV (manager);
337 list = g_hash_table_lookup (priv->lists, account);
343 return empathy_tp_contact_list_get_from_id (list, id);
347 empathy_contact_manager_rename_group (EmpathyContactManager *manager,
348 const gchar *old_group,
349 const gchar *new_group)
351 EmpathyContactManagerPriv *priv;
352 ContactManagerRenameGroupData data;
354 g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
355 g_return_if_fail (old_group != NULL);
356 g_return_if_fail (new_group != NULL);
358 priv = GET_PRIV (manager);
360 data.old_group = old_group;
361 data.new_group = new_group;
363 g_hash_table_foreach (priv->lists,
364 (GHFunc) contact_manager_rename_group_foreach,
369 empathy_contact_manager_get_groups (EmpathyContactManager *manager)
371 EmpathyContactManagerPriv *priv;
372 GList *groups = NULL;
374 g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
376 priv = GET_PRIV (manager);
378 g_hash_table_foreach (priv->lists,
379 (GHFunc) contact_manager_get_groups_foreach,
386 contact_manager_setup_foreach (McAccount *account,
387 EmpathyTpContactList *list,
388 EmpathyContactManager *manager)
390 empathy_contact_list_setup (EMPATHY_CONTACT_LIST (list));
394 contact_manager_find_foreach (McAccount *account,
395 EmpathyTpContactList *list,
396 ContactManagerFindData *data)
398 data->contact = empathy_contact_list_find (EMPATHY_CONTACT_LIST (list),
409 contact_manager_add_account (EmpathyContactManager *manager,
412 EmpathyContactManagerPriv *priv;
413 EmpathyTpContactList *list;
415 priv = GET_PRIV (manager);
417 if (g_hash_table_lookup (priv->lists, account)) {
421 gossip_debug (DEBUG_DOMAIN, "Adding new account: %s",
422 mc_account_get_display_name (account));
424 list = empathy_tp_contact_list_new (account);
429 g_hash_table_insert (priv->lists, g_object_ref (account), list);
431 /* Connect signals */
432 g_signal_connect (list, "contact-added",
433 G_CALLBACK (contact_manager_added_cb),
435 g_signal_connect (list, "contact-removed",
436 G_CALLBACK (contact_manager_removed_cb),
438 g_signal_connect (list, "destroy",
439 G_CALLBACK (contact_manager_destroy_cb),
443 empathy_contact_list_setup (EMPATHY_CONTACT_LIST (list));
448 contact_manager_added_cb (EmpathyTpContactList *list,
449 GossipContact *contact,
450 EmpathyContactManager *manager)
452 g_signal_emit_by_name (manager, "contact-added", contact);
456 contact_manager_removed_cb (EmpathyTpContactList *list,
457 GossipContact *contact,
458 EmpathyContactManager *manager)
460 g_signal_emit_by_name (manager, "contact-removed", contact);
464 contact_manager_destroy_cb (EmpathyTpContactList *list,
465 EmpathyContactManager *manager)
467 EmpathyContactManagerPriv *priv;
470 priv = GET_PRIV (manager);
472 account = empathy_tp_contact_list_get_account (list);
474 gossip_debug (DEBUG_DOMAIN, "Removing account: %s",
475 mc_account_get_display_name (account));
477 /* Disconnect signals from the list */
478 g_signal_handlers_disconnect_by_func (list,
479 contact_manager_added_cb,
481 g_signal_handlers_disconnect_by_func (list,
482 contact_manager_removed_cb,
484 g_signal_handlers_disconnect_by_func (list,
485 contact_manager_destroy_cb,
488 g_hash_table_remove (priv->lists, account);
492 contact_manager_rename_group_foreach (McAccount *account,
493 EmpathyTpContactList *list,
494 ContactManagerRenameGroupData *data)
496 empathy_tp_contact_list_rename_group (list,
502 contact_manager_get_groups_foreach (McAccount *account,
503 EmpathyTpContactList *list,
508 groups = empathy_tp_contact_list_get_groups (list);
509 for (l = groups; l; l = l->next) {
510 if (!g_list_find_custom (*all_groups,
512 (GCompareFunc) strcmp)) {
513 *all_groups = g_list_append (*all_groups,
519 g_list_free (groups);
523 contact_manager_get_contacts_foreach (McAccount *account,
524 EmpathyTpContactList *list,
529 l = empathy_contact_list_get_contacts (EMPATHY_CONTACT_LIST (list));
530 *contacts = g_list_concat (*contacts, l);
534 contact_manager_status_changed_cb (MissionControl *mc,
535 TelepathyConnectionStatus status,
537 TelepathyConnectionStatusReason reason,
538 const gchar *unique_name,
539 EmpathyContactManager *manager)
541 EmpathyContactManagerPriv *priv;
544 priv = GET_PRIV (manager);
546 if (status != TP_CONN_STATUS_CONNECTED) {
547 /* We only care about newly connected accounts */
551 account = mc_account_lookup (unique_name);
552 contact_manager_add_account (manager, account);
554 g_object_unref (account);