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