]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-individual-store-manager.c
03841f17585f584e7f810204eab6babb927a3ed9
[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/util.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",
80           folks_individual_get_id (l->data), "removed");
81
82       individual_store_remove_individual_and_disconnect (store, l->data);
83     }
84
85   for (l = added; l; l = l->next)
86     {
87       DEBUG ("Individual %s %s", folks_individual_get_id (l->data), "added");
88
89       individual_store_add_individual_and_connect (store, l->data);
90     }
91 }
92
93 static void
94 individual_store_manager_groups_changed_cb (EmpathyIndividualManager *manager,
95     FolksIndividual *individual,
96     gchar *group,
97     gboolean is_member,
98     EmpathyIndividualStoreManager *self)
99 {
100   EmpathyIndividualStore *store = EMPATHY_INDIVIDUAL_STORE (self);
101
102   DEBUG ("Updating groups for individual %s",
103       folks_individual_get_id (individual));
104
105   /* We do this to make sure the groups are correct, if not, we
106    * would have to check the groups already set up for each
107    * contact and then see what has been updated.
108    */
109   empathy_individual_store_refresh_individual (store, individual);
110 }
111
112 static gboolean
113 individual_store_manager_manager_setup (gpointer user_data)
114 {
115   EmpathyIndividualStoreManager *self = user_data;
116   EmpathyIndividualStore *store = user_data;
117   GList *individuals;
118
119   /* Signal connection. */
120
121   DEBUG ("handling individual renames unimplemented");
122
123   g_signal_connect (self->priv->manager,
124       "members-changed",
125       G_CALLBACK (individual_store_manager_members_changed_cb), self);
126
127   g_signal_connect (self->priv->manager,
128       "groups-changed",
129       G_CALLBACK (individual_store_manager_groups_changed_cb), self);
130
131   /* Add contacts already created. */
132   individuals = empathy_individual_manager_get_members (self->priv->manager);
133   if (individuals != NULL)
134     {
135       individual_store_manager_members_changed_cb (self->priv->manager, "initial add",
136           individuals, NULL, 0, self);
137       g_list_free (individuals);
138     }
139
140   self->priv->setup_idle_id = 0;
141   return FALSE;
142 }
143
144 static void
145 individual_store_manager_set_individual_manager (
146     EmpathyIndividualStoreManager *self,
147     EmpathyIndividualManager *manager)
148 {
149   EmpathyIndividualStore *store = EMPATHY_INDIVIDUAL_STORE (self);
150
151   g_assert (self->priv->manager == NULL); /* construct only */
152   self->priv->manager = g_object_ref (manager);
153
154   /* Let a chance to have all properties set before populating */
155   self->priv->setup_idle_id = g_idle_add (
156       individual_store_manager_manager_setup, self);
157 }
158
159 static void
160 individual_store_manager_member_renamed_cb (EmpathyIndividualManager *manager,
161     FolksIndividual *old_individual,
162     FolksIndividual *new_individual,
163     guint reason,
164     const gchar *message,
165     EmpathyIndividualStoreManager *self)
166 {
167   EmpathyIndividualStore *store = EMPATHY_INDIVIDUAL_STORE (self);
168
169   DEBUG ("Individual %s renamed to %s",
170       folks_individual_get_id (old_individual),
171       folks_individual_get_id (new_individual));
172
173   /* remove old contact */
174   individual_store_remove_individual_and_disconnect (store, old_individual);
175
176   /* add the new contact */
177   individual_store_add_individual_and_connect (store, new_individual);
178 }
179
180 static void
181 individual_store_manager_dispose (GObject *object)
182 {
183   EmpathyIndividualStoreManager *self = EMPATHY_INDIVIDUAL_STORE_MANAGER (
184       object);
185   EmpathyIndividualStore *store = EMPATHY_INDIVIDUAL_STORE (object);
186   GList *individuals, *l;
187
188   individuals = empathy_individual_manager_get_members (self->priv->manager);
189   for (l = individuals; l; l = l->next)
190     {
191       empathy_individual_store_disconnect_individual (store,
192           FOLKS_INDIVIDUAL (l->data));
193     }
194   tp_clear_pointer (&individuals, g_list_free);
195
196   if (self->priv->manager != NULL)
197     {
198       g_signal_handlers_disconnect_by_func (self->priv->manager,
199           G_CALLBACK (individual_store_manager_member_renamed_cb), object);
200       g_signal_handlers_disconnect_by_func (self->priv->manager,
201           G_CALLBACK (individual_store_manager_members_changed_cb), object);
202       g_signal_handlers_disconnect_by_func (self->priv->manager,
203           G_CALLBACK (individual_store_manager_groups_changed_cb), object);
204       g_clear_object (&self->priv->manager);
205     }
206
207   if (self->priv->setup_idle_id != 0)
208     {
209       g_source_remove (self->priv->setup_idle_id);
210       self->priv->setup_idle_id = 0;
211     }
212
213   G_OBJECT_CLASS (empathy_individual_store_manager_parent_class)->dispose (
214       object);
215 }
216
217 static void
218 individual_store_manager_get_property (GObject *object,
219     guint param_id,
220     GValue *value,
221     GParamSpec *pspec)
222 {
223   EmpathyIndividualStoreManager *self = EMPATHY_INDIVIDUAL_STORE_MANAGER (
224       object);
225
226   switch (param_id)
227     {
228     case PROP_INDIVIDUAL_MANAGER:
229       g_value_set_object (value, self->priv->manager);
230       break;
231     default:
232       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
233       break;
234     };
235 }
236
237 static void
238 individual_store_manager_set_property (GObject *object,
239     guint param_id,
240     const GValue *value,
241     GParamSpec *pspec)
242 {
243   switch (param_id)
244     {
245     case PROP_INDIVIDUAL_MANAGER:
246       individual_store_manager_set_individual_manager (
247           EMPATHY_INDIVIDUAL_STORE_MANAGER (object),
248           g_value_get_object (value));
249       break;
250     default:
251       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
252       break;
253     };
254 }
255
256 static void
257 individual_store_manager_reload_individuals (EmpathyIndividualStore *store)
258 {
259   EmpathyIndividualStoreManager *self = EMPATHY_INDIVIDUAL_STORE_MANAGER (
260       store);
261   GList *contacts;
262
263   contacts = empathy_individual_manager_get_members (self->priv->manager);
264
265   individual_store_manager_members_changed_cb (self->priv->manager,
266       "re-adding members: toggled group visibility",
267       contacts, NULL, 0, self);
268
269   g_list_free (contacts);
270 }
271
272 static gboolean
273 individual_store_manager_initial_loading (EmpathyIndividualStore *store)
274 {
275   EmpathyIndividualStoreManager *self = EMPATHY_INDIVIDUAL_STORE_MANAGER (
276       store);
277
278   return self->priv->setup_idle_id != 0;
279 }
280
281 static void
282 empathy_individual_store_manager_class_init (
283     EmpathyIndividualStoreManagerClass *klass)
284 {
285   GObjectClass *object_class = G_OBJECT_CLASS (klass);
286   EmpathyIndividualStoreClass *store_class = EMPATHY_INDIVIDUAL_STORE_CLASS (
287       klass);
288
289   object_class->dispose = individual_store_manager_dispose;
290   object_class->get_property = individual_store_manager_get_property;
291   object_class->set_property = individual_store_manager_set_property;
292
293   store_class->reload_individuals = individual_store_manager_reload_individuals;
294   store_class->initial_loading = individual_store_manager_initial_loading;
295
296   g_object_class_install_property (object_class,
297       PROP_INDIVIDUAL_MANAGER,
298       g_param_spec_object ("individual-manager",
299           "Individual manager",
300           "Individual manager",
301           EMPATHY_TYPE_INDIVIDUAL_MANAGER,
302           G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
303
304   g_type_class_add_private (object_class,
305       sizeof (EmpathyIndividualStoreManagerPriv));
306 }
307
308 static void
309 empathy_individual_store_manager_init (EmpathyIndividualStoreManager *self)
310 {
311   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
312       EMPATHY_TYPE_INDIVIDUAL_STORE_MANAGER, EmpathyIndividualStoreManagerPriv);
313 }
314
315 EmpathyIndividualStoreManager *
316 empathy_individual_store_manager_new (EmpathyIndividualManager *manager)
317 {
318   g_return_val_if_fail (EMPATHY_IS_INDIVIDUAL_MANAGER (manager), NULL);
319
320   return g_object_new (EMPATHY_TYPE_INDIVIDUAL_STORE_MANAGER,
321       "individual-manager", manager, NULL);
322 }
323
324 EmpathyIndividualManager *
325 empathy_individual_store_manager_get_manager (
326     EmpathyIndividualStoreManager *self)
327 {
328   g_return_val_if_fail (EMPATHY_IS_INDIVIDUAL_STORE_MANAGER (self), FALSE);
329
330   return self->priv->manager;
331 }