]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-roster-model-manager.c
Updated Polish translation
[empathy.git] / libempathy-gtk / empathy-roster-model-manager.c
1 /*
2  * empathy-roster-model-manager.c
3  *
4  * Implementation of EmpathyRosterModel using EmpathyIndividualManager as
5  * source.
6  *
7  * Copyright (C) 2012 Collabora Ltd. <http://www.collabora.co.uk/>
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22  */
23
24 #include "config.h"
25
26 #include "empathy-roster-model-manager.h"
27
28 #include "empathy-roster-model.h"
29
30 #include <glib/gi18n-lib.h>
31
32 #include <libempathy/empathy-utils.h>
33
34 static void roster_model_iface_init (EmpathyRosterModelInterface *iface);
35
36 G_DEFINE_TYPE_WITH_CODE (EmpathyRosterModelManager,
37     empathy_roster_model_manager,
38     G_TYPE_OBJECT,
39     G_IMPLEMENT_INTERFACE (EMPATHY_TYPE_ROSTER_MODEL, roster_model_iface_init))
40
41 enum
42 {
43   PROP_MANAGER = 1,
44   N_PROPS
45 };
46
47 /*
48 enum
49 {
50   LAST_SIGNAL
51 };
52
53 static guint signals[LAST_SIGNAL];
54 */
55
56 struct _EmpathyRosterModelManagerPriv
57 {
58   EmpathyIndividualManager *manager;
59   /* FolksIndividual (borrowed) */
60   GList *top_group_members;
61 };
62
63 static gboolean
64 is_xmpp_local_contact (FolksIndividual *individual)
65 {
66   EmpathyContact *contact;
67   TpConnection *connection;
68   const gchar *protocol_name = NULL;
69   gboolean result;
70
71   contact = empathy_contact_dup_from_folks_individual (individual);
72
73   if (contact == NULL)
74     return FALSE;
75
76   connection = empathy_contact_get_connection (contact);
77   protocol_name = tp_connection_get_protocol_name (connection);
78   result = !tp_strdiff (protocol_name, "local-xmpp");
79   g_object_unref (contact);
80
81   return result;
82 }
83
84 static gboolean
85 individual_in_top_group_members (EmpathyRosterModelManager *self,
86     FolksIndividual *individual)
87 {
88   return (g_list_find (self->priv->top_group_members, individual) != NULL);
89 }
90
91 static gboolean
92 individual_should_be_in_top_group_members (EmpathyRosterModelManager *self,
93     FolksIndividual *individual)
94 {
95   GList *tops;
96
97   tops = empathy_individual_manager_get_top_individuals (self->priv->manager);
98
99   return (folks_favourite_details_get_is_favourite (
100           FOLKS_FAVOURITE_DETAILS (individual)) ||
101       g_list_find (tops, individual) != NULL);
102 }
103
104 static void
105 populate_model (EmpathyRosterModelManager *self)
106 {
107   GList *individuals, *l;
108
109   individuals = empathy_individual_manager_get_members (self->priv->manager);
110
111   for (l = individuals; l != NULL; l = g_list_next (l))
112     {
113       if (individual_should_be_in_top_group_members (self, l->data))
114         self->priv->top_group_members = g_list_prepend (
115             self->priv->top_group_members, l->data);
116
117       empathy_roster_model_fire_individual_added (EMPATHY_ROSTER_MODEL (self),
118           l->data);
119     }
120 }
121
122 static void
123 members_changed_cb (EmpathyIndividualManager *manager,
124     const gchar *message,
125     GList *added,
126     GList *removed,
127     TpChannelGroupChangeReason reason,
128     EmpathyRosterModelManager *self)
129 {
130   GList *l;
131
132   for (l = added; l != NULL; l = g_list_next (l))
133     {
134       if (individual_should_be_in_top_group_members (self, l->data) &&
135           !individual_in_top_group_members (self, l->data))
136         self->priv->top_group_members = g_list_prepend (
137             self->priv->top_group_members, l->data);
138
139       empathy_roster_model_fire_individual_added (EMPATHY_ROSTER_MODEL (self),
140           l->data);
141     }
142
143   for (l = removed; l != NULL; l = g_list_next (l))
144     {
145       if (individual_in_top_group_members (self, l->data))
146         self->priv->top_group_members = g_list_remove (
147             self->priv->top_group_members, l->data);
148
149       empathy_roster_model_fire_individual_removed (EMPATHY_ROSTER_MODEL (self),
150           l->data);
151     }
152 }
153
154 static void
155 groups_changed_cb (EmpathyIndividualManager *manager,
156     FolksIndividual *individual,
157     const gchar *group,
158     gboolean is_member,
159     EmpathyRosterModelManager *self)
160 {
161   empathy_roster_model_fire_groups_changed (EMPATHY_ROSTER_MODEL (self),
162       individual, group, is_member);
163 }
164
165 static void
166 top_individuals_changed_cb (EmpathyIndividualManager *manager,
167     GParamSpec *spec,
168     EmpathyRosterModelManager *self)
169 {
170   GList *tops, *l;
171
172   tops = empathy_individual_manager_get_top_individuals (self->priv->manager);
173
174   for (l = tops; l != NULL; l = g_list_next (l))
175     {
176       if (!individual_in_top_group_members (self, l->data))
177         {
178           self->priv->top_group_members = g_list_prepend (
179               self->priv->top_group_members, l->data);
180
181           empathy_roster_model_fire_groups_changed (
182               EMPATHY_ROSTER_MODEL (self), l->data,
183               EMPATHY_ROSTER_MODEL_GROUP_TOP_GROUP, TRUE);
184         }
185     }
186   for (l = self->priv->top_group_members; l != NULL; l = g_list_next (l))
187     {
188       if (!individual_should_be_in_top_group_members (self, l->data))
189         {
190           self->priv->top_group_members = g_list_remove (
191               self->priv->top_group_members, l->data);
192
193           empathy_roster_model_fire_groups_changed (
194               EMPATHY_ROSTER_MODEL (self), l->data,
195               EMPATHY_ROSTER_MODEL_GROUP_TOP_GROUP, FALSE);
196         }
197     }
198 }
199
200 static void
201 favourites_changed_cb (EmpathyIndividualManager *manager,
202     FolksIndividual *individual,
203     gboolean favourite,
204     EmpathyRosterModelManager *self)
205 {
206   if (favourite && !individual_in_top_group_members (self, individual))
207     {
208       self->priv->top_group_members = g_list_prepend (
209           self->priv->top_group_members, individual);
210
211       empathy_roster_model_fire_groups_changed (
212           EMPATHY_ROSTER_MODEL (self), individual,
213           EMPATHY_ROSTER_MODEL_GROUP_TOP_GROUP, favourite);
214     }
215   else if (!favourite &&
216       !individual_should_be_in_top_group_members (self, individual))
217     {
218       self->priv->top_group_members = g_list_remove (
219           self->priv->top_group_members, individual);
220
221       empathy_roster_model_fire_groups_changed (
222           EMPATHY_ROSTER_MODEL (self), individual,
223           EMPATHY_ROSTER_MODEL_GROUP_TOP_GROUP, favourite);
224     }
225 }
226
227 static void
228 empathy_roster_model_manager_get_property (GObject *object,
229     guint property_id,
230     GValue *value,
231     GParamSpec *pspec)
232 {
233   EmpathyRosterModelManager *self = EMPATHY_ROSTER_MODEL_MANAGER (object);
234
235   switch (property_id)
236     {
237       case PROP_MANAGER:
238         g_value_set_object (value, self->priv->manager);
239         break;
240       default:
241         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
242         break;
243     }
244 }
245
246 static void
247 empathy_roster_model_manager_set_property (GObject *object,
248     guint property_id,
249     const GValue *value,
250     GParamSpec *pspec)
251 {
252   EmpathyRosterModelManager *self = EMPATHY_ROSTER_MODEL_MANAGER (object);
253
254   switch (property_id)
255     {
256       case PROP_MANAGER:
257         g_assert (self->priv->manager == NULL); /* construct only */
258         self->priv->manager = g_value_dup_object (value);
259         break;
260       default:
261         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
262         break;
263     }
264 }
265
266 static void
267 empathy_roster_model_manager_constructed (GObject *object)
268 {
269   EmpathyRosterModelManager *self = EMPATHY_ROSTER_MODEL_MANAGER (object);
270   void (*chain_up) (GObject *) =
271       ((GObjectClass *) empathy_roster_model_manager_parent_class)->constructed;
272
273   if (chain_up != NULL)
274     chain_up (object);
275
276   g_assert (EMPATHY_IS_INDIVIDUAL_MANAGER (self->priv->manager));
277
278   populate_model (self);
279
280   tp_g_signal_connect_object (self->priv->manager, "members-changed",
281       G_CALLBACK (members_changed_cb), self, 0);
282   tp_g_signal_connect_object (self->priv->manager, "groups-changed",
283       G_CALLBACK (groups_changed_cb), self, 0);
284   tp_g_signal_connect_object (self->priv->manager, "notify::top-individuals",
285       G_CALLBACK (top_individuals_changed_cb), self, 0);
286   tp_g_signal_connect_object (self->priv->manager, "favourites-changed",
287       G_CALLBACK (favourites_changed_cb), self, 0);
288 }
289
290 static void
291 empathy_roster_model_manager_dispose (GObject *object)
292 {
293   EmpathyRosterModelManager *self = EMPATHY_ROSTER_MODEL_MANAGER (object);
294   void (*chain_up) (GObject *) =
295       ((GObjectClass *) empathy_roster_model_manager_parent_class)->dispose;
296
297   g_clear_object (&self->priv->manager);
298
299   if (chain_up != NULL)
300     chain_up (object);
301 }
302
303 static void
304 empathy_roster_model_manager_finalize (GObject *object)
305 {
306   EmpathyRosterModelManager *self = EMPATHY_ROSTER_MODEL_MANAGER (object);
307   void (*chain_up) (GObject *) =
308       ((GObjectClass *) empathy_roster_model_manager_parent_class)->finalize;
309
310   g_list_free (self->priv->top_group_members);
311
312   if (chain_up != NULL)
313     chain_up (object);
314 }
315
316 static void
317 empathy_roster_model_manager_class_init (
318     EmpathyRosterModelManagerClass *klass)
319 {
320   GObjectClass *oclass = G_OBJECT_CLASS (klass);
321   GParamSpec *spec;
322
323   oclass->get_property = empathy_roster_model_manager_get_property;
324   oclass->set_property = empathy_roster_model_manager_set_property;
325   oclass->constructed = empathy_roster_model_manager_constructed;
326   oclass->dispose = empathy_roster_model_manager_dispose;
327   oclass->finalize = empathy_roster_model_manager_finalize;
328
329   spec = g_param_spec_object ("manager", "Manager",
330       "EmpathyIndividualManager",
331       EMPATHY_TYPE_INDIVIDUAL_MANAGER,
332       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
333   g_object_class_install_property (oclass, PROP_MANAGER, spec);
334
335   g_type_class_add_private (klass, sizeof (EmpathyRosterModelManagerPriv));
336 }
337
338 static void
339 empathy_roster_model_manager_init (EmpathyRosterModelManager *self)
340 {
341   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
342       EMPATHY_TYPE_ROSTER_MODEL_MANAGER, EmpathyRosterModelManagerPriv);
343
344   self->priv->top_group_members = NULL;
345 }
346
347 EmpathyRosterModelManager *
348 empathy_roster_model_manager_new (EmpathyIndividualManager *manager)
349 {
350   g_return_val_if_fail (EMPATHY_IS_INDIVIDUAL_MANAGER (manager), NULL);
351
352   return g_object_new (EMPATHY_TYPE_ROSTER_MODEL_MANAGER,
353       "manager", manager,
354       NULL);
355 }
356
357 static GList *
358 empathy_roster_model_manager_get_individuals (EmpathyRosterModel *model)
359 {
360   EmpathyRosterModelManager *self = EMPATHY_ROSTER_MODEL_MANAGER (model);
361
362   return empathy_individual_manager_get_members (self->priv->manager);
363 }
364
365 static GList *
366 empathy_roster_model_manager_dup_groups_for_individual (
367     EmpathyRosterModel *model,
368     FolksIndividual *individual)
369 {
370   GList *groups_list = NULL;
371   GeeSet *groups_set;
372
373   if (is_xmpp_local_contact (individual))
374     {
375       groups_list = g_list_prepend (groups_list,
376           g_strdup (EMPATHY_ROSTER_MODEL_GROUP_PEOPLE_NEARBY));
377       return groups_list;
378     }
379
380   if (individual_in_top_group_members (EMPATHY_ROSTER_MODEL_MANAGER (model),
381           individual))
382     groups_list = g_list_prepend (groups_list,
383         g_strdup (EMPATHY_ROSTER_MODEL_GROUP_TOP_GROUP));
384
385   groups_set = folks_group_details_get_groups (
386       FOLKS_GROUP_DETAILS (individual));
387   if (gee_collection_get_size (GEE_COLLECTION (groups_set)) > 0)
388     {
389       GeeIterator *iter = gee_iterable_iterator (GEE_ITERABLE (groups_set));
390
391       while (iter != NULL && gee_iterator_next (iter))
392         {
393           groups_list = g_list_prepend (groups_list, gee_iterator_get (iter));
394         }
395       g_clear_object (&iter);
396     }
397
398   return groups_list;
399 }
400
401 static void
402 roster_model_iface_init (EmpathyRosterModelInterface *iface)
403 {
404   iface->get_individuals = empathy_roster_model_manager_get_individuals;
405   iface->dup_groups_for_individual =
406     empathy_roster_model_manager_dup_groups_for_individual;
407 }