1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2007-2008 Collabora Ltd.
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.
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.
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
19 * Authors: Xavier Claessens <xclaesse@gmail.com>
26 #include <telepathy-glib/enums.h>
28 #include "empathy-contact-manager.h"
29 #include "empathy-account-manager.h"
30 #include "empathy-contact-monitor.h"
31 #include "empathy-contact-list.h"
32 #include "empathy-utils.h"
34 #define DEBUG_FLAG EMPATHY_DEBUG_CONTACT
35 #include "empathy-debug.h"
37 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyContactManager)
40 EmpathyAccountManager *account_manager;
41 EmpathyContactMonitor *contact_monitor;
42 } EmpathyContactManagerPriv;
44 static void contact_manager_iface_init (EmpathyContactListIface *iface);
46 G_DEFINE_TYPE_WITH_CODE (EmpathyContactManager, empathy_contact_manager, G_TYPE_OBJECT,
47 G_IMPLEMENT_INTERFACE (EMPATHY_TYPE_CONTACT_LIST,
48 contact_manager_iface_init));
50 static EmpathyContactManager *manager_singleton = NULL;
53 contact_manager_members_changed_cb (EmpathyTpContactList *list,
54 EmpathyContact *contact,
55 EmpathyContact *actor,
59 EmpathyContactManager *manager)
61 g_signal_emit_by_name (manager, "members-changed",
62 contact, actor, reason, message, is_member);
66 contact_manager_pendings_changed_cb (EmpathyTpContactList *list,
67 EmpathyContact *contact,
68 EmpathyContact *actor,
72 EmpathyContactManager *manager)
74 g_signal_emit_by_name (manager, "pendings-changed",
75 contact, actor, reason, message, is_pending);
79 contact_manager_groups_changed_cb (EmpathyTpContactList *list,
80 EmpathyContact *contact,
83 EmpathyContactManager *manager)
85 g_signal_emit_by_name (manager, "groups-changed",
86 contact, group, is_member);
90 contact_manager_disconnect_foreach (gpointer key,
94 EmpathyTpContactList *list = value;
95 EmpathyContactManager *manager = user_data;
97 /* Disconnect signals from the list */
98 g_signal_handlers_disconnect_by_func (list,
99 contact_manager_members_changed_cb,
101 g_signal_handlers_disconnect_by_func (list,
102 contact_manager_pendings_changed_cb,
104 g_signal_handlers_disconnect_by_func (list,
105 contact_manager_groups_changed_cb,
110 contact_manager_invalidated_cb (TpProxy *connection,
114 EmpathyContactManager *manager)
116 EmpathyContactManagerPriv *priv = GET_PRIV (manager);
117 EmpathyTpContactList *list;
119 DEBUG ("Removing connection: %s (%s)",
120 tp_proxy_get_object_path (TP_PROXY (connection)),
123 list = g_hash_table_lookup (priv->lists, connection);
125 empathy_tp_contact_list_remove_all (list);
126 g_hash_table_remove (priv->lists, connection);
131 contact_manager_new_connection_cb (EmpathyAccountManager *account_manager,
132 TpConnection *connection,
133 EmpathyContactManager *self)
135 EmpathyContactManagerPriv *priv = GET_PRIV (self);
136 EmpathyTpContactList *list;
138 if (g_hash_table_lookup (priv->lists, connection)) {
142 DEBUG ("Adding new connection: %s",
143 tp_proxy_get_object_path (TP_PROXY (connection)));
145 list = empathy_tp_contact_list_new (connection);
146 g_hash_table_insert (priv->lists, g_object_ref (connection), list);
147 g_signal_connect (connection, "invalidated",
148 G_CALLBACK (contact_manager_invalidated_cb),
151 /* Connect signals */
152 g_signal_connect (list, "members-changed",
153 G_CALLBACK (contact_manager_members_changed_cb),
155 g_signal_connect (list, "pendings-changed",
156 G_CALLBACK (contact_manager_pendings_changed_cb),
158 g_signal_connect (list, "groups-changed",
159 G_CALLBACK (contact_manager_groups_changed_cb),
164 contact_manager_finalize (GObject *object)
166 EmpathyContactManagerPriv *priv = GET_PRIV (object);
168 g_hash_table_foreach (priv->lists,
169 contact_manager_disconnect_foreach,
171 g_hash_table_destroy (priv->lists);
173 g_signal_handlers_disconnect_by_func (priv->account_manager,
174 contact_manager_new_connection_cb,
176 g_object_unref (priv->account_manager);
178 if (priv->contact_monitor) {
179 g_object_unref (priv->contact_monitor);
184 contact_manager_constructor (GType type,
186 GObjectConstructParam *props)
190 if (manager_singleton) {
191 retval = g_object_ref (manager_singleton);
193 retval = G_OBJECT_CLASS (empathy_contact_manager_parent_class)->constructor
194 (type, n_props, props);
196 manager_singleton = EMPATHY_CONTACT_MANAGER (retval);
197 g_object_add_weak_pointer (retval, (gpointer) &manager_singleton);
204 empathy_contact_manager_class_init (EmpathyContactManagerClass *klass)
206 GObjectClass *object_class = G_OBJECT_CLASS (klass);
208 object_class->finalize = contact_manager_finalize;
209 object_class->constructor = contact_manager_constructor;
211 g_type_class_add_private (object_class, sizeof (EmpathyContactManagerPriv));
215 empathy_contact_manager_init (EmpathyContactManager *manager)
217 GList *connections, *l;
218 EmpathyContactManagerPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (manager,
219 EMPATHY_TYPE_CONTACT_MANAGER, EmpathyContactManagerPriv);
221 manager->priv = priv;
222 priv->lists = g_hash_table_new_full (empathy_proxy_hash,
224 (GDestroyNotify) g_object_unref,
225 (GDestroyNotify) g_object_unref);
226 priv->account_manager = empathy_account_manager_dup_singleton ();
227 priv->contact_monitor = NULL;
229 g_signal_connect (priv->account_manager, "new-connection",
230 G_CALLBACK (contact_manager_new_connection_cb),
233 /* Get ContactList for existing connections */
234 connections = empathy_account_manager_dup_connections (priv->account_manager);
235 for (l = connections; l; l = l->next) {
236 contact_manager_new_connection_cb (priv->account_manager,
238 g_object_unref (l->data);
240 g_list_free (connections);
243 EmpathyContactManager *
244 empathy_contact_manager_dup_singleton (void)
246 return g_object_new (EMPATHY_TYPE_CONTACT_MANAGER, NULL);
249 EmpathyTpContactList *
250 empathy_contact_manager_get_list (EmpathyContactManager *manager,
251 TpConnection *connection)
253 EmpathyContactManagerPriv *priv = GET_PRIV (manager);
255 g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
256 g_return_val_if_fail (TP_IS_CONNECTION (connection), NULL);
258 return g_hash_table_lookup (priv->lists, connection);
262 contact_manager_add (EmpathyContactList *manager,
263 EmpathyContact *contact,
264 const gchar *message)
266 EmpathyContactManagerPriv *priv = GET_PRIV (manager);
267 EmpathyContactList *list;
268 TpConnection *connection;
270 g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
272 connection = empathy_contact_get_connection (contact);
273 list = g_hash_table_lookup (priv->lists, connection);
276 empathy_contact_list_add (list, contact, message);
281 contact_manager_remove (EmpathyContactList *manager,
282 EmpathyContact *contact,
283 const gchar *message)
285 EmpathyContactManagerPriv *priv = GET_PRIV (manager);
286 EmpathyContactList *list;
287 TpConnection *connection;
289 g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
291 connection = empathy_contact_get_connection (contact);
292 list = g_hash_table_lookup (priv->lists, connection);
295 empathy_contact_list_remove (list, contact, message);
300 contact_manager_get_members_foreach (TpConnection *connection,
301 EmpathyTpContactList *list,
306 l = empathy_contact_list_get_members (EMPATHY_CONTACT_LIST (list));
307 *contacts = g_list_concat (*contacts, l);
311 contact_manager_get_members (EmpathyContactList *manager)
313 EmpathyContactManagerPriv *priv = GET_PRIV (manager);
314 GList *contacts = NULL;
316 g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
318 g_hash_table_foreach (priv->lists,
319 (GHFunc) contact_manager_get_members_foreach,
325 static EmpathyContactMonitor *
326 contact_manager_get_monitor (EmpathyContactList *manager)
328 EmpathyContactManagerPriv *priv = GET_PRIV (manager);
330 if (priv->contact_monitor == NULL) {
331 priv->contact_monitor = empathy_contact_monitor_new_for_iface (manager);
334 return priv->contact_monitor;
338 contact_manager_get_pendings_foreach (TpConnection *connection,
339 EmpathyTpContactList *list,
344 l = empathy_contact_list_get_pendings (EMPATHY_CONTACT_LIST (list));
345 *contacts = g_list_concat (*contacts, l);
349 contact_manager_get_pendings (EmpathyContactList *manager)
351 EmpathyContactManagerPriv *priv = GET_PRIV (manager);
352 GList *contacts = NULL;
354 g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
356 g_hash_table_foreach (priv->lists,
357 (GHFunc) contact_manager_get_pendings_foreach,
364 contact_manager_get_all_groups_foreach (TpConnection *connection,
365 EmpathyTpContactList *list,
370 groups = empathy_contact_list_get_all_groups (EMPATHY_CONTACT_LIST (list));
371 for (l = groups; l; l = l->next) {
372 if (!g_list_find_custom (*all_groups,
374 (GCompareFunc) strcmp)) {
375 *all_groups = g_list_prepend (*all_groups, l->data);
381 g_list_free (groups);
385 contact_manager_get_all_groups (EmpathyContactList *manager)
387 EmpathyContactManagerPriv *priv = GET_PRIV (manager);
388 GList *groups = NULL;
390 g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
392 g_hash_table_foreach (priv->lists,
393 (GHFunc) contact_manager_get_all_groups_foreach,
400 contact_manager_get_groups (EmpathyContactList *manager,
401 EmpathyContact *contact)
403 EmpathyContactManagerPriv *priv = GET_PRIV (manager);
404 EmpathyContactList *list;
405 TpConnection *connection;
407 g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), NULL);
409 connection = empathy_contact_get_connection (contact);
410 list = g_hash_table_lookup (priv->lists, connection);
413 return empathy_contact_list_get_groups (list, contact);
420 contact_manager_add_to_group (EmpathyContactList *manager,
421 EmpathyContact *contact,
424 EmpathyContactManagerPriv *priv = GET_PRIV (manager);
425 EmpathyContactList *list;
426 TpConnection *connection;
428 g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
430 connection = empathy_contact_get_connection (contact);
431 list = g_hash_table_lookup (priv->lists, connection);
434 empathy_contact_list_add_to_group (list, contact, group);
439 contact_manager_remove_from_group (EmpathyContactList *manager,
440 EmpathyContact *contact,
443 EmpathyContactManagerPriv *priv = GET_PRIV (manager);
444 EmpathyContactList *list;
445 TpConnection *connection;
447 g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
449 connection = empathy_contact_get_connection (contact);
450 list = g_hash_table_lookup (priv->lists, connection);
453 empathy_contact_list_remove_from_group (list, contact, group);
458 const gchar *old_group;
459 const gchar *new_group;
463 contact_manager_rename_group_foreach (TpConnection *connection,
464 EmpathyTpContactList *list,
465 RenameGroupData *data)
467 empathy_contact_list_rename_group (EMPATHY_CONTACT_LIST (list),
473 contact_manager_rename_group (EmpathyContactList *manager,
474 const gchar *old_group,
475 const gchar *new_group)
477 EmpathyContactManagerPriv *priv = GET_PRIV (manager);
478 RenameGroupData data;
480 g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
482 data.old_group = old_group;
483 data.new_group = new_group;
484 g_hash_table_foreach (priv->lists,
485 (GHFunc) contact_manager_rename_group_foreach,
489 static void contact_manager_remove_group_foreach (TpConnection *connection,
490 EmpathyTpContactList *list,
493 empathy_contact_list_remove_group (EMPATHY_CONTACT_LIST (list),
498 contact_manager_remove_group (EmpathyContactList *manager,
501 EmpathyContactManagerPriv *priv = GET_PRIV (manager);
503 g_return_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager));
505 g_hash_table_foreach (priv->lists,
506 (GHFunc) contact_manager_remove_group_foreach,
511 contact_manager_iface_init (EmpathyContactListIface *iface)
513 iface->add = contact_manager_add;
514 iface->remove = contact_manager_remove;
515 iface->get_members = contact_manager_get_members;
516 iface->get_monitor = contact_manager_get_monitor;
517 iface->get_pendings = contact_manager_get_pendings;
518 iface->get_all_groups = contact_manager_get_all_groups;
519 iface->get_groups = contact_manager_get_groups;
520 iface->add_to_group = contact_manager_add_to_group;
521 iface->remove_from_group = contact_manager_remove_from_group;
522 iface->rename_group = contact_manager_rename_group;
523 iface->remove_group = contact_manager_remove_group;
527 empathy_contact_manager_can_add (EmpathyContactManager *manager,
528 TpConnection *connection)
530 EmpathyContactManagerPriv *priv = GET_PRIV (manager);
531 EmpathyTpContactList *list;
533 g_return_val_if_fail (EMPATHY_IS_CONTACT_MANAGER (manager), FALSE);
535 list = g_hash_table_lookup (priv->lists, connection);
539 return empathy_tp_contact_list_can_add (list);