2 * empathy-connection-aggregator.c - Source for EmpathyConnectionAggregator
3 * Copyright (C) 2010 Collabora Ltd.
4 * @author Cosimo Cecchi <cosimo.cecchi@collabora.co.uk>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "empathy-connection-aggregator.h"
24 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER
25 #include "empathy-debug.h"
27 G_DEFINE_TYPE (EmpathyConnectionAggregator
, empathy_connection_aggregator
,
31 EVENT_CONTACT_LIST_CHANGED
,
35 static guint signals
[LAST_SIGNAL
];
37 struct _EmpathyConnectionAggregatorPriv
{
38 TpAccountManager
*mgr
;
40 /* List of owned TpConnection */
45 empathy_connection_aggregator_dispose (GObject
*object
)
47 EmpathyConnectionAggregator
*self
= (EmpathyConnectionAggregator
*) object
;
49 g_clear_object (&self
->priv
->mgr
);
51 g_list_free_full (self
->priv
->conns
, g_object_unref
);
52 self
->priv
->conns
= NULL
;
54 G_OBJECT_CLASS (empathy_connection_aggregator_parent_class
)->dispose (object
);
58 empathy_connection_aggregator_class_init (
59 EmpathyConnectionAggregatorClass
*klass
)
61 GObjectClass
*oclass
= G_OBJECT_CLASS (klass
);
63 oclass
->dispose
= empathy_connection_aggregator_dispose
;
65 signals
[EVENT_CONTACT_LIST_CHANGED
] =
66 g_signal_new ("contact-list-changed",
67 G_TYPE_FROM_CLASS (klass
),
71 g_cclosure_marshal_generic
,
73 2, G_TYPE_PTR_ARRAY
, G_TYPE_PTR_ARRAY
);
75 g_type_class_add_private (klass
, sizeof (EmpathyConnectionAggregatorPriv
));
79 contact_list_changed_cb (TpConnection
*conn
,
82 EmpathyConnectionAggregator
*self
)
84 g_signal_emit (self
, signals
[EVENT_CONTACT_LIST_CHANGED
], 0, added
, removed
);
88 conn_invalidated_cb (TpConnection
*conn
,
92 EmpathyConnectionAggregator
*self
)
94 self
->priv
->conns
= g_list_remove (self
->priv
->conns
, conn
);
96 g_object_unref (conn
);
100 check_connection (EmpathyConnectionAggregator
*self
,
105 if (g_list_find (self
->priv
->conns
, conn
) != NULL
)
108 self
->priv
->conns
= g_list_prepend (self
->priv
->conns
,
109 g_object_ref (conn
));
111 tp_g_signal_connect_object (conn
, "contact-list-changed",
112 G_CALLBACK (contact_list_changed_cb
), self
, 0);
114 contacts
= tp_connection_dup_contact_list (conn
);
115 if (contacts
!= NULL
)
119 empty
= g_ptr_array_new ();
121 contact_list_changed_cb (conn
, contacts
, empty
, self
);
122 g_ptr_array_unref (empty
);
124 g_ptr_array_unref (contacts
);
126 tp_g_signal_connect_object (conn
, "invalidated",
127 G_CALLBACK (conn_invalidated_cb
), self
, 0);
131 check_account (EmpathyConnectionAggregator
*self
,
136 conn
= tp_account_get_connection (account
);
138 check_connection (self
, conn
);
142 account_conn_changed_cb (TpAccount
*account
,
144 EmpathyConnectionAggregator
*self
)
146 check_account (self
, account
);
150 add_account (EmpathyConnectionAggregator
*self
,
153 check_account (self
, account
);
155 tp_g_signal_connect_object (account
, "notify::connection",
156 G_CALLBACK (account_conn_changed_cb
), self
, 0);
160 account_validity_changed_cb (TpAccountManager
*manager
,
163 EmpathyConnectionAggregator
*self
)
166 add_account (self
, account
);
170 am_prepare_cb (GObject
*source
,
171 GAsyncResult
*result
,
174 EmpathyConnectionAggregator
*self
= EMPATHY_CONNECTION_AGGREGATOR (user_data
);
175 GError
*error
= NULL
;
178 if (!tp_proxy_prepare_finish (source
, result
, &error
))
180 DEBUG ("Failed to prepare account manager: %s", error
->message
);
181 g_error_free (error
);
185 accounts
= tp_account_manager_dup_valid_accounts (self
->priv
->mgr
);
186 for (l
= accounts
; l
!= NULL
; l
= g_list_next (l
))
188 TpAccount
*account
= l
->data
;
190 add_account (self
, account
);
193 tp_g_signal_connect_object (self
->priv
->mgr
, "account-validity-changed",
194 G_CALLBACK (account_validity_changed_cb
), self
, 0);
196 g_list_free_full (accounts
, g_object_unref
);
199 g_object_unref (self
);
203 empathy_connection_aggregator_init (EmpathyConnectionAggregator
*self
)
205 self
->priv
= G_TYPE_INSTANCE_GET_PRIVATE (self
,
206 EMPATHY_TYPE_CONNECTION_AGGREGATOR
, EmpathyConnectionAggregatorPriv
);
208 self
->priv
->mgr
= tp_account_manager_dup ();
210 tp_proxy_prepare_async (self
->priv
->mgr
, NULL
, am_prepare_cb
,
211 g_object_ref (self
));
214 EmpathyConnectionAggregator
*
215 empathy_connection_aggregator_dup_singleton (void)
217 static EmpathyConnectionAggregator
*aggregator
= NULL
;
219 if (G_LIKELY (aggregator
!= NULL
))
220 return g_object_ref (aggregator
);
222 aggregator
= g_object_new (EMPATHY_TYPE_CONNECTION_AGGREGATOR
, NULL
);
224 g_object_add_weak_pointer (G_OBJECT (aggregator
), (gpointer
*) &aggregator
);
228 /* (transfer container) */
230 empathy_connection_aggregator_get_all_groups (EmpathyConnectionAggregator
*self
)
235 set
= g_hash_table_new (g_str_hash
, g_str_equal
);
237 for (l
= self
->priv
->conns
; l
!= NULL
; l
= g_list_next (l
))
239 TpConnection
*conn
= l
->data
;
240 const gchar
* const *groups
;
243 groups
= tp_connection_get_contact_groups (conn
);
247 for (i
= 0; groups
[i
] != NULL
; i
++)
248 g_hash_table_insert (set
, (gchar
*) groups
[i
], GUINT_TO_POINTER (TRUE
));
251 keys
= g_hash_table_get_keys (set
);
252 g_hash_table_unref (set
);
258 empathy_connection_aggregator_dup_all_contacts (
259 EmpathyConnectionAggregator
*self
)
264 result
= g_ptr_array_new_with_free_func (g_object_unref
);
266 for (l
= self
->priv
->conns
; l
!= NULL
; l
= g_list_next (l
))
268 TpConnection
*conn
= l
->data
;
271 contacts
= tp_connection_dup_contact_list (conn
);
272 if (contacts
== NULL
)
275 tp_g_ptr_array_extend (result
, contacts
);
277 /* tp_g_ptr_array_extend() doesn't give us an extra ref */
278 g_ptr_array_foreach (contacts
, (GFunc
) g_object_ref
, NULL
);
280 g_ptr_array_unref (contacts
);
287 rename_group_cb (GObject
*source
,
288 GAsyncResult
*result
,
291 GError
*error
= NULL
;
293 if (!tp_connection_rename_group_finish (TP_CONNECTION (source
), result
,
296 DEBUG ("Failed to rename group on %s: %s",
297 tp_proxy_get_object_path (source
), error
->message
);
298 g_error_free (error
);
303 empathy_connection_aggregator_rename_group (EmpathyConnectionAggregator
*self
,
304 const gchar
*old_name
,
305 const gchar
*new_name
)
309 for (l
= self
->priv
->conns
; l
!= NULL
; l
= g_list_next (l
))
311 TpConnection
*conn
= l
->data
;
312 const gchar
* const *groups
;
314 groups
= tp_connection_get_contact_groups (conn
);
316 if (!tp_strv_contains (groups
, old_name
))
319 DEBUG ("Rename group '%s' to '%s' on %s", old_name
, new_name
,
320 tp_proxy_get_object_path (conn
));
322 tp_connection_rename_group_async (conn
, old_name
, new_name
,
323 rename_group_cb
, NULL
);