]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-individual-store-manager.c
include telepathy-glib.h
[empathy.git] / libempathy-gtk / empathy-individual-store-manager.c
1 /*
2  * Copyright (C) 2005-2007 Imendio AB
3  * Copyright (C) 2007-2011 Collabora Ltd.
4  *
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.
9  *
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.
14  *
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., 51 Franklin St, Fifth Floor,
18  * Boston, MA  02110-1301  USA
19  *
20  * Authors: Mikael Hallendal <micke@imendio.com>
21  *          Martyn Russell <martyn@imendio.com>
22  *          Xavier Claessens <xclaesse@gmail.com>
23  *          Travis Reitter <travis.reitter@collabora.co.uk>
24  */
25
26 #include "config.h"
27
28 #include <string.h>
29
30 #include <glib.h>
31 #include <glib/gi18n-lib.h>
32 #include <gtk/gtk.h>
33
34 #include <folks/folks.h>
35 #include <folks/folks-telepathy.h>
36 #include <telepathy-glib/telepathy-glib.h>
37
38 #include <libempathy/empathy-utils.h>
39 #include <libempathy/empathy-enum-types.h>
40 #include <libempathy/empathy-individual-manager.h>
41
42 #include "empathy-individual-store-manager.h"
43
44 #include "empathy-ui-utils.h"
45 #include "empathy-gtk-enum-types.h"
46
47 #define DEBUG_FLAG EMPATHY_DEBUG_CONTACT
48 #include <libempathy/empathy-debug.h>
49
50 struct _EmpathyIndividualStoreManagerPriv
51 {
52   EmpathyIndividualManager *manager;
53   gboolean setup_idle_id;
54 };
55
56 enum
57 {
58   PROP_0,
59   PROP_INDIVIDUAL_MANAGER,
60 };
61
62
63 G_DEFINE_TYPE (EmpathyIndividualStoreManager, empathy_individual_store_manager,
64     EMPATHY_TYPE_INDIVIDUAL_STORE);
65
66 static void
67 individual_store_manager_members_changed_cb (EmpathyIndividualManager *manager,
68     const gchar *message,
69     GList *added,
70     GList *removed,
71     guint reason,
72     EmpathyIndividualStoreManager *self)
73 {
74   GList *l;
75   EmpathyIndividualStore *store = EMPATHY_INDIVIDUAL_STORE (self);
76
77   for (l = removed; l; l = l->next)
78     {
79       DEBUG ("Individual %s (%s) %s",
80           folks_individual_get_id (l->data),
81           folks_alias_details_get_alias (FOLKS_ALIAS_DETAILS (l->data)),
82           "removed");
83
84       individual_store_remove_individual_and_disconnect (store, l->data);
85     }
86
87   for (l = added; l; l = l->next)
88     {
89       DEBUG ("Individual %s (%s) %s", folks_individual_get_id (l->data),
90           folks_alias_details_get_alias (FOLKS_ALIAS_DETAILS (l->data)),
91           "added");
92
93       individual_store_add_individual_and_connect (store, l->data);
94     }
95 }
96
97 static void
98 individual_store_manager_groups_changed_cb (EmpathyIndividualManager *manager,
99     FolksIndividual *individual,
100     gchar *group,
101     gboolean is_member,
102     EmpathyIndividualStoreManager *self)
103 {
104   EmpathyIndividualStore *store = EMPATHY_INDIVIDUAL_STORE (self);
105
106   DEBUG ("Updating groups for individual %s (%s)",
107       folks_individual_get_id (individual),
108       folks_alias_details_get_alias (FOLKS_ALIAS_DETAILS (individual)));
109
110   /* We do this to make sure the groups are correct, if not, we
111    * would have to check the groups already set up for each
112    * contact and then see what has been updated.
113    */
114   empathy_individual_store_refresh_individual (store, individual);
115 }
116
117 static gboolean
118 individual_store_manager_manager_setup (gpointer user_data)
119 {
120   EmpathyIndividualStoreManager *self = user_data;
121   GList *individuals;
122
123   /* Signal connection. */
124
125   DEBUG ("handling individual renames unimplemented");
126
127   g_signal_connect (self->priv->manager,
128       "members-changed",
129       G_CALLBACK (individual_store_manager_members_changed_cb), self);
130
131   g_signal_connect (self->priv->manager,
132       "groups-changed",
133       G_CALLBACK (individual_store_manager_groups_changed_cb), self);
134
135   /* Add contacts already created. */
136   individuals = empathy_individual_manager_get_members (self->priv->manager);
137   if (individuals != NULL)
138     {
139       individual_store_manager_members_changed_cb (self->priv->manager, "initial add",
140           individuals, NULL, 0, self);
141       g_list_free (individuals);
142     }
143
144   self->priv->setup_idle_id = 0;
145   return FALSE;
146 }
147
148 static void
149 individual_store_manager_set_individual_manager (
150     EmpathyIndividualStoreManager *self,
151     EmpathyIndividualManager *manager)
152 {
153   g_assert (self->priv->manager == NULL); /* construct only */
154   self->priv->manager = g_object_ref (manager);
155
156   /* Let a chance to have all properties set before populating */
157   self->priv->setup_idle_id = g_idle_add (
158       individual_store_manager_manager_setup, self);
159 }
160
161 static void
162 individual_store_manager_member_renamed_cb (EmpathyIndividualManager *manager,
163     FolksIndividual *old_individual,
164     FolksIndividual *new_individual,
165     guint reason,
166     const gchar *message,
167     EmpathyIndividualStoreManager *self)
168 {
169   EmpathyIndividualStore *store = EMPATHY_INDIVIDUAL_STORE (self);
170
171   DEBUG ("Individual %s (%s) renamed to %s",
172       folks_individual_get_id (old_individual),
173       folks_alias_details_get_alias (FOLKS_ALIAS_DETAILS (old_individual)),
174       folks_individual_get_id (new_individual));
175
176   /* remove old contact */
177   individual_store_remove_individual_and_disconnect (store, old_individual);
178
179   /* add the new contact */
180   individual_store_add_individual_and_connect (store, new_individual);
181 }
182
183 static void
184 individual_store_manager_dispose (GObject *object)
185 {
186   EmpathyIndividualStoreManager *self = EMPATHY_INDIVIDUAL_STORE_MANAGER (
187       object);
188   EmpathyIndividualStore *store = EMPATHY_INDIVIDUAL_STORE (object);
189   GList *individuals, *l;
190
191   individuals = empathy_individual_manager_get_members (self->priv->manager);
192   for (l = individuals; l; l = l->next)
193     {
194       empathy_individual_store_disconnect_individual (store,
195           FOLKS_INDIVIDUAL (l->data));
196     }
197   tp_clear_pointer (&individuals, g_list_free);
198
199   if (self->priv->manager != NULL)
200     {
201       g_signal_handlers_disconnect_by_func (self->priv->manager,
202           G_CALLBACK (individual_store_manager_member_renamed_cb), object);
203       g_signal_handlers_disconnect_by_func (self->priv->manager,
204           G_CALLBACK (individual_store_manager_members_changed_cb), object);
205       g_signal_handlers_disconnect_by_func (self->priv->manager,
206           G_CALLBACK (individual_store_manager_groups_changed_cb), object);
207       g_clear_object (&self->priv->manager);
208     }
209
210   if (self->priv->setup_idle_id != 0)
211     {
212       g_source_remove (self->priv->setup_idle_id);
213       self->priv->setup_idle_id = 0;
214     }
215
216   G_OBJECT_CLASS (empathy_individual_store_manager_parent_class)->dispose (
217       object);
218 }
219
220 static void
221 individual_store_manager_get_property (GObject *object,
222     guint param_id,
223     GValue *value,
224     GParamSpec *pspec)
225 {
226   EmpathyIndividualStoreManager *self = EMPATHY_INDIVIDUAL_STORE_MANAGER (
227       object);
228
229   switch (param_id)
230     {
231     case PROP_INDIVIDUAL_MANAGER:
232       g_value_set_object (value, self->priv->manager);
233       break;
234     default:
235       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
236       break;
237     };
238 }
239
240 static void
241 individual_store_manager_set_property (GObject *object,
242     guint param_id,
243     const GValue *value,
244     GParamSpec *pspec)
245 {
246   switch (param_id)
247     {
248     case PROP_INDIVIDUAL_MANAGER:
249       individual_store_manager_set_individual_manager (
250           EMPATHY_INDIVIDUAL_STORE_MANAGER (object),
251           g_value_get_object (value));
252       break;
253     default:
254       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
255       break;
256     };
257 }
258
259 static void
260 individual_store_manager_reload_individuals (EmpathyIndividualStore *store)
261 {
262   EmpathyIndividualStoreManager *self = EMPATHY_INDIVIDUAL_STORE_MANAGER (
263       store);
264   GList *contacts;
265
266   contacts = empathy_individual_manager_get_members (self->priv->manager);
267
268   individual_store_manager_members_changed_cb (self->priv->manager,
269       "re-adding members: toggled group visibility",
270       contacts, NULL, 0, self);
271
272   g_list_free (contacts);
273 }
274
275 static gboolean
276 individual_store_manager_initial_loading (EmpathyIndividualStore *store)
277 {
278   EmpathyIndividualStoreManager *self = EMPATHY_INDIVIDUAL_STORE_MANAGER (
279       store);
280
281   return self->priv->setup_idle_id != 0;
282 }
283
284 static void
285 empathy_individual_store_manager_class_init (
286     EmpathyIndividualStoreManagerClass *klass)
287 {
288   GObjectClass *object_class = G_OBJECT_CLASS (klass);
289   EmpathyIndividualStoreClass *store_class = EMPATHY_INDIVIDUAL_STORE_CLASS (
290       klass);
291
292   object_class->dispose = individual_store_manager_dispose;
293   object_class->get_property = individual_store_manager_get_property;
294   object_class->set_property = individual_store_manager_set_property;
295
296   store_class->reload_individuals = individual_store_manager_reload_individuals;
297   store_class->initial_loading = individual_store_manager_initial_loading;
298
299   g_object_class_install_property (object_class,
300       PROP_INDIVIDUAL_MANAGER,
301       g_param_spec_object ("individual-manager",
302           "Individual manager",
303           "Individual manager",
304           EMPATHY_TYPE_INDIVIDUAL_MANAGER,
305           G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
306
307   g_type_class_add_private (object_class,
308       sizeof (EmpathyIndividualStoreManagerPriv));
309 }
310
311 static void
312 empathy_individual_store_manager_init (EmpathyIndividualStoreManager *self)
313 {
314   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
315       EMPATHY_TYPE_INDIVIDUAL_STORE_MANAGER, EmpathyIndividualStoreManagerPriv);
316 }
317
318 EmpathyIndividualStoreManager *
319 empathy_individual_store_manager_new (EmpathyIndividualManager *manager)
320 {
321   g_return_val_if_fail (EMPATHY_IS_INDIVIDUAL_MANAGER (manager), NULL);
322
323   return g_object_new (EMPATHY_TYPE_INDIVIDUAL_STORE_MANAGER,
324       "individual-manager", manager, NULL);
325 }
326
327 EmpathyIndividualManager *
328 empathy_individual_store_manager_get_manager (
329     EmpathyIndividualStoreManager *self)
330 {
331   g_return_val_if_fail (EMPATHY_IS_INDIVIDUAL_STORE_MANAGER (self), FALSE);
332
333   return self->priv->manager;
334 }