]> git.0d.be Git - empathy.git/blob - libempathy/empathy-individual-manager.c
Cut outdated comment.
[empathy.git] / libempathy / empathy-individual-manager.c
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 typedef struct
47 {
48   FolksIndividualAggregator *aggregator;
49   EmpathyContactManager *contact_manager;
50   TpProxy *logger;
51 } EmpathyIndividualManagerPriv;
52
53 G_DEFINE_TYPE (EmpathyIndividualManager, empathy_individual_manager,
54     G_TYPE_OBJECT);
55
56 static EmpathyIndividualManager *manager_singleton = NULL;
57
58 static void
59 individual_group_changed_cb (FolksIndividual *individual,
60     gchar *group,
61     gboolean is_member,
62     EmpathyIndividualManager *self)
63 {
64   g_signal_emit_by_name (self, "groups-changed", individual, group,
65       is_member);
66 }
67
68 static void
69 individual_notify_is_favourite_cb (FolksIndividual *individual,
70     GParamSpec *pspec,
71     EmpathyIndividualManager *self)
72 {
73   gboolean is_favourite = folks_favourite_get_is_favourite (
74       FOLKS_FAVOURITE (individual));
75   g_signal_emit_by_name (self, "favourites-changed", individual, is_favourite);
76 }
77
78 static void
79 aggregator_individuals_added_cb (FolksIndividualAggregator *aggregator,
80     GList *individuals,
81     EmpathyIndividualManager *self)
82 {
83   GList *l;
84
85   for (l = individuals; l; l = l->next)
86     {
87       g_signal_connect (l->data, "group-changed",
88           G_CALLBACK (individual_group_changed_cb), self);
89       g_signal_connect (l->data, "notify::is-favourite",
90           G_CALLBACK (individual_notify_is_favourite_cb), self);
91     }
92
93   /* TODO: don't hard-code the reason or message */
94   g_signal_emit_by_name (self, "members-changed",
95       "individual(s) added", individuals, NULL,
96       TP_CHANNEL_GROUP_CHANGE_REASON_NONE, TRUE);
97 }
98
99 static void
100 aggregator_individuals_removed_cb (FolksIndividualAggregator *aggregator,
101     GList *individuals,
102     EmpathyIndividualManager *self)
103 {
104   GList *l;
105
106   for (l = individuals; l; l = l->next)
107     {
108       g_signal_handlers_disconnect_by_func (l->data,
109           individual_group_changed_cb, self);
110       g_signal_handlers_disconnect_by_func (l->data,
111           individual_notify_is_favourite_cb, self);
112     }
113
114   /* TODO: don't hard-code the reason or message */
115   g_signal_emit_by_name (self, "members-changed",
116       "individual(s) removed", NULL, individuals,
117       TP_CHANNEL_GROUP_CHANGE_REASON_NONE, TRUE);
118 }
119
120 static void
121 individual_manager_finalize (GObject *object)
122 {
123   EmpathyIndividualManagerPriv *priv = GET_PRIV (object);
124
125   if (priv->logger != NULL)
126     g_object_unref (priv->logger);
127
128   if (priv->contact_manager != NULL)
129     g_object_unref (priv->contact_manager);
130
131   if (priv->aggregator != NULL)
132     g_object_unref (priv->aggregator);
133 }
134
135 static GObject *
136 individual_manager_constructor (GType type,
137     guint n_props,
138     GObjectConstructParam *props)
139 {
140   GObject *retval;
141
142   if (manager_singleton)
143     {
144       retval = g_object_ref (manager_singleton);
145     }
146   else
147     {
148       retval =
149           G_OBJECT_CLASS (empathy_individual_manager_parent_class)->
150           constructor (type, n_props, props);
151
152       manager_singleton = EMPATHY_INDIVIDUAL_MANAGER (retval);
153       g_object_add_weak_pointer (retval, (gpointer) & manager_singleton);
154     }
155
156   return retval;
157 }
158
159 /**
160  * empathy_individual_manager_initialized:
161  *
162  * Reports whether or not the singleton has already been created.
163  *
164  * There can be instances where you want to access the #EmpathyIndividualManager
165  * only if it has been set up for this process.
166  *
167  * Returns: %TRUE if the #EmpathyIndividualManager singleton has previously
168  * been initialized.
169  */
170 gboolean
171 empathy_individual_manager_initialized (void)
172 {
173   return (manager_singleton != NULL);
174 }
175
176 static void
177 empathy_individual_manager_class_init (EmpathyIndividualManagerClass *klass)
178 {
179   GObjectClass *object_class = G_OBJECT_CLASS (klass);
180
181   object_class->finalize = individual_manager_finalize;
182   object_class->constructor = individual_manager_constructor;
183
184   g_signal_new ("groups-changed",
185       G_TYPE_FROM_CLASS (klass),
186       G_SIGNAL_RUN_LAST,
187       0,
188       NULL, NULL,
189       _empathy_marshal_VOID__OBJECT_STRING_BOOLEAN,
190       G_TYPE_NONE, 3, FOLKS_TYPE_INDIVIDUAL, G_TYPE_STRING, G_TYPE_BOOLEAN);
191
192   g_signal_new ("favourites-changed",
193       G_TYPE_FROM_CLASS (klass),
194       G_SIGNAL_RUN_LAST,
195       0,
196       NULL, NULL,
197       _empathy_marshal_VOID__OBJECT_BOOLEAN,
198       G_TYPE_NONE, 2, FOLKS_TYPE_INDIVIDUAL, G_TYPE_BOOLEAN);
199
200   g_signal_new ("members-changed",
201       G_TYPE_FROM_CLASS (klass),
202       G_SIGNAL_RUN_LAST,
203       0,
204       NULL, NULL,
205       _empathy_marshal_VOID__STRING_OBJECT_OBJECT_UINT,
206       G_TYPE_NONE,
207       4, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_UINT);
208
209   g_type_class_add_private (object_class,
210       sizeof (EmpathyIndividualManagerPriv));
211 }
212
213 static void
214 empathy_individual_manager_init (EmpathyIndividualManager *self)
215 {
216   EmpathyIndividualManagerPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
217       EMPATHY_TYPE_INDIVIDUAL_MANAGER, EmpathyIndividualManagerPriv);
218   TpDBusDaemon *bus;
219   GError *error = NULL;
220
221   self->priv = priv;
222   priv->contact_manager = empathy_contact_manager_dup_singleton ();
223
224   priv->aggregator = folks_individual_aggregator_new ();
225   g_signal_connect (priv->aggregator, "individuals-added",
226       G_CALLBACK (aggregator_individuals_added_cb), self);
227   g_signal_connect (priv->aggregator, "individuals-removed",
228       G_CALLBACK (aggregator_individuals_removed_cb), self);
229
230   bus = tp_dbus_daemon_dup (&error);
231
232   if (error == NULL)
233     {
234       priv->logger = g_object_new (TP_TYPE_PROXY,
235           "bus-name", "org.freedesktop.Telepathy.Logger",
236           "object-path",
237           "/org/freedesktop/Telepathy/Logger", "dbus-daemon", bus, NULL);
238       g_object_unref (bus);
239
240       tp_proxy_add_interface_by_id (priv->logger, EMP_IFACE_QUARK_LOGGER);
241     }
242   else
243     {
244       DEBUG ("Failed to get telepathy-logger proxy: %s", error->message);
245       g_clear_error (&error);
246     }
247 }
248
249 EmpathyIndividualManager *
250 empathy_individual_manager_dup_singleton (void)
251 {
252   return g_object_new (EMPATHY_TYPE_INDIVIDUAL_MANAGER, NULL);
253 }
254
255 GList *
256 empathy_individual_manager_get_members (EmpathyIndividualManager *self)
257 {
258   EmpathyIndividualManagerPriv *priv = GET_PRIV (self);
259   GHashTable *individuals;
260
261   g_return_val_if_fail (EMPATHY_IS_INDIVIDUAL_MANAGER (self), NULL);
262
263   individuals = folks_individual_aggregator_get_individuals (priv->aggregator);
264   return individuals ? g_hash_table_get_values (individuals) : NULL;
265 }
266
267 FolksIndividual *
268 empathy_individual_manager_lookup_member (EmpathyIndividualManager *self,
269     const gchar *id)
270 {
271   EmpathyIndividualManagerPriv *priv = GET_PRIV (self);
272   GHashTable *individuals;
273
274   g_return_val_if_fail (EMPATHY_IS_INDIVIDUAL_MANAGER (self), NULL);
275
276   individuals = folks_individual_aggregator_get_individuals (priv->aggregator);
277   if (individuals != NULL)
278     return g_hash_table_lookup (individuals, id);
279
280   return NULL;
281 }
282
283 static void
284 aggregator_add_persona_from_details_cb (GObject *source,
285     GAsyncResult *result,
286     gpointer user_data)
287 {
288   EmpathyIndividualManager *self = EMPATHY_INDIVIDUAL_MANAGER (user_data);
289   EmpathyIndividualManagerPriv *priv = GET_PRIV (self);
290   FolksPersona *persona;
291   GError *error = NULL;
292
293   persona = folks_individual_aggregator_add_persona_from_details_finish (
294       priv->aggregator, result, &error);
295   if (error != NULL)
296     {
297       g_warning ("failed to add individual from contact: %s", error->message);
298       g_clear_error (&error);
299     }
300 }
301
302 void
303 empathy_individual_manager_add_from_contact (EmpathyIndividualManager *self,
304     EmpathyContact *contact)
305 {
306   EmpathyIndividualManagerPriv *priv;
307   GHashTable* details;
308   TpAccount *account;
309   const gchar *store_id;
310
311   g_return_if_fail (EMPATHY_IS_INDIVIDUAL_MANAGER (self));
312   g_return_if_fail (EMPATHY_IS_CONTACT (contact));
313
314   priv = GET_PRIV (self);
315
316   DEBUG (G_STRLOC ": adding individual from contact %s (%s)",
317       empathy_contact_get_id (contact), empathy_contact_get_name (contact));
318
319   account = empathy_contact_get_account (contact);
320   store_id = tp_proxy_get_object_path (TP_PROXY (account));
321
322   details = g_hash_table_new (g_str_hash, g_str_equal);
323   g_hash_table_insert (details, "contact",
324       (gchar*) empathy_contact_get_id (contact));
325
326   folks_individual_aggregator_add_persona_from_details (
327       priv->aggregator, NULL, "telepathy", store_id, details,
328       aggregator_add_persona_from_details_cb, self);
329
330   g_hash_table_destroy (details);
331 }
332
333 /**
334  * Removes the inner contact from the server (and thus the Individual). Not
335  * meant for de-shelling inner personas from an Individual.
336  */
337 void
338 empathy_individual_manager_remove (EmpathyIndividualManager *self,
339     FolksIndividual *individual,
340     const gchar *message)
341 {
342   EmpathyIndividualManagerPriv *priv;
343
344   g_return_if_fail (EMPATHY_IS_INDIVIDUAL_MANAGER (self));
345   g_return_if_fail (FOLKS_IS_INDIVIDUAL (individual));
346
347   priv = GET_PRIV (self);
348
349   DEBUG (G_STRLOC ": removing individual %s (%s)",
350       folks_individual_get_id (individual),
351       folks_individual_get_alias (individual));
352
353   folks_individual_aggregator_remove_individual (priv->aggregator, individual);
354 }
355
356 EmpathyIndividualManagerFlags
357 empathy_individual_manager_get_flags_for_connection (
358     EmpathyIndividualManager *self,
359     TpConnection *connection)
360 {
361   EmpathyIndividualManagerPriv *priv;
362   EmpathyContactListFlags list_flags;
363   EmpathyIndividualManagerFlags flags;
364
365   g_return_val_if_fail (EMPATHY_IS_INDIVIDUAL_MANAGER (self),
366       EMPATHY_INDIVIDUAL_MANAGER_NO_FLAGS);
367
368   priv = GET_PRIV (self);
369
370   list_flags = empathy_contact_manager_get_flags_for_connection (
371     priv->contact_manager, connection);
372
373   flags = EMPATHY_INDIVIDUAL_MANAGER_NO_FLAGS;
374   if (list_flags & EMPATHY_CONTACT_LIST_CAN_ADD)
375     flags |= EMPATHY_INDIVIDUAL_MANAGER_CAN_ADD;
376   if (list_flags & EMPATHY_CONTACT_LIST_CAN_REMOVE)
377     flags |= EMPATHY_INDIVIDUAL_MANAGER_CAN_REMOVE;
378   if (list_flags & EMPATHY_CONTACT_LIST_CAN_ALIAS)
379     flags |= EMPATHY_INDIVIDUAL_MANAGER_CAN_ALIAS;
380   if (list_flags & EMPATHY_CONTACT_LIST_CAN_GROUP)
381     flags |= EMPATHY_INDIVIDUAL_MANAGER_CAN_GROUP;
382
383   return flags;
384 }