4 #include "empathy-roster-view.h"
6 #include <libempathy-gtk/empathy-roster-contact.h>
8 G_DEFINE_TYPE (EmpathyRosterView, empathy_roster_view, EGG_TYPE_LIST_BOX)
24 static guint signals[LAST_SIGNAL];
27 struct _EmpathyRosterViewPriv
29 EmpathyIndividualManager *manager;
31 /* FolksIndividual (borrowed) -> EmpathyRosterContact (borrowed) */
32 GHashTable *roster_contacts;
34 gboolean show_offline;
39 empathy_roster_view_get_property (GObject *object,
44 EmpathyRosterView *self = EMPATHY_ROSTER_VIEW (object);
49 g_value_set_object (value, self->priv->manager);
51 case PROP_SHOW_OFFLINE:
52 g_value_set_boolean (value, self->priv->show_offline);
54 case PROP_SHOW_GROUPS:
55 g_value_set_boolean (value, self->priv->show_groups);
58 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
64 empathy_roster_view_set_property (GObject *object,
69 EmpathyRosterView *self = EMPATHY_ROSTER_VIEW (object);
74 g_assert (self->priv->manager == NULL); /* construct only */
75 self->priv->manager = g_value_dup_object (value);
77 case PROP_SHOW_OFFLINE:
78 empathy_roster_view_show_offline (self, g_value_get_boolean (value));
80 case PROP_SHOW_GROUPS:
81 empathy_roster_view_show_groups (self, g_value_get_boolean (value));
84 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
90 roster_contact_changed_cb (GtkWidget *child,
92 EmpathyRosterView *self)
94 egg_list_box_child_changed (EGG_LIST_BOX (self), child);
98 add_roster_contact (EmpathyRosterView *self,
99 FolksIndividual *individual)
103 contact = empathy_roster_contact_new (individual);
105 /* Need to refilter if online is changed */
106 g_signal_connect (contact, "notify::online",
107 G_CALLBACK (roster_contact_changed_cb), self);
109 /* Need to resort if alias is changed */
110 g_signal_connect (contact, "notify::alias",
111 G_CALLBACK (roster_contact_changed_cb), self);
113 gtk_widget_show (contact);
114 gtk_container_add (GTK_CONTAINER (self), contact);
120 individual_added (EmpathyRosterView *self,
121 FolksIndividual *individual)
125 contact = g_hash_table_lookup (self->priv->roster_contacts, individual);
129 contact = add_roster_contact (self, individual);
131 g_hash_table_insert (self->priv->roster_contacts, individual, contact);
135 individual_removed (EmpathyRosterView *self,
136 FolksIndividual *individual)
140 contact = g_hash_table_lookup (self->priv->roster_contacts, individual);
144 gtk_container_remove (GTK_CONTAINER (self), contact);
146 g_hash_table_remove (self->priv->roster_contacts, individual);
150 members_changed_cb (EmpathyIndividualManager *manager,
151 const gchar *message,
154 TpChannelGroupChangeReason reason,
155 EmpathyRosterView *self)
159 for (l = added; l != NULL; l = g_list_next (l))
161 FolksIndividual *individual = l->data;
163 individual_added (self, individual);
166 for (l = removed; l != NULL; l = g_list_next (l))
168 FolksIndividual *individual = l->data;
170 individual_removed (self, individual);
175 roster_view_sort (EmpathyRosterContact *a,
176 EmpathyRosterContact *b,
177 EmpathyRosterView *self)
179 FolksIndividual *ind_a, *ind_b;
180 const gchar *alias_a, *alias_b;
182 ind_a = empathy_roster_contact_get_individual (a);
183 ind_b = empathy_roster_contact_get_individual (b);
185 alias_a = folks_alias_details_get_alias (FOLKS_ALIAS_DETAILS (ind_a));
186 alias_b = folks_alias_details_get_alias (FOLKS_ALIAS_DETAILS (ind_b));
188 return g_ascii_strcasecmp (alias_a, alias_b);
192 update_separator (GtkWidget **separator,
199 /* No separator before the first row */
200 g_clear_object (separator);
204 if (*separator != NULL)
207 *separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
208 g_object_ref_sink (*separator);
212 filter_list (GtkWidget *child,
215 EmpathyRosterView *self = user_data;
216 EmpathyRosterContact *contact = EMPATHY_ROSTER_CONTACT (child);
218 if (self->priv->show_offline)
221 return empathy_roster_contact_is_online (contact);
225 populate_view (EmpathyRosterView *self)
227 GList *individuals, *l;
229 individuals = empathy_individual_manager_get_members (self->priv->manager);
230 for (l = individuals; l != NULL; l = g_list_next (l))
232 FolksIndividual *individual = l->data;
234 individual_added (self, individual);
237 g_list_free (individuals);
241 empathy_roster_view_constructed (GObject *object)
243 EmpathyRosterView *self = EMPATHY_ROSTER_VIEW (object);
244 void (*chain_up) (GObject *) =
245 ((GObjectClass *) empathy_roster_view_parent_class)->constructed;
247 if (chain_up != NULL)
250 g_assert (EMPATHY_IS_INDIVIDUAL_MANAGER (self->priv->manager));
252 populate_view (self);
254 tp_g_signal_connect_object (self->priv->manager, "members-changed",
255 G_CALLBACK (members_changed_cb), self, 0);
257 egg_list_box_set_sort_func (EGG_LIST_BOX (self),
258 (GCompareDataFunc) roster_view_sort, self, NULL);
260 egg_list_box_set_separator_funcs (EGG_LIST_BOX (self), update_separator,
263 egg_list_box_set_filter_func (EGG_LIST_BOX (self), filter_list, self, NULL);
267 empathy_roster_view_dispose (GObject *object)
269 EmpathyRosterView *self = EMPATHY_ROSTER_VIEW (object);
270 void (*chain_up) (GObject *) =
271 ((GObjectClass *) empathy_roster_view_parent_class)->dispose;
273 g_clear_object (&self->priv->manager);
275 if (chain_up != NULL)
280 empathy_roster_view_finalize (GObject *object)
282 EmpathyRosterView *self = EMPATHY_ROSTER_VIEW (object);
283 void (*chain_up) (GObject *) =
284 ((GObjectClass *) empathy_roster_view_parent_class)->finalize;
286 g_hash_table_unref (self->priv->roster_contacts);
288 if (chain_up != NULL)
293 empathy_roster_view_class_init (
294 EmpathyRosterViewClass *klass)
296 GObjectClass *oclass = G_OBJECT_CLASS (klass);
299 oclass->get_property = empathy_roster_view_get_property;
300 oclass->set_property = empathy_roster_view_set_property;
301 oclass->constructed = empathy_roster_view_constructed;
302 oclass->dispose = empathy_roster_view_dispose;
303 oclass->finalize = empathy_roster_view_finalize;
305 spec = g_param_spec_object ("manager", "Manager",
306 "EmpathyIndividualManager",
307 EMPATHY_TYPE_INDIVIDUAL_MANAGER,
308 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
309 g_object_class_install_property (oclass, PROP_MANAGER, spec);
311 spec = g_param_spec_boolean ("show-offline", "Show Offline",
312 "Show offline contacts",
314 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
315 g_object_class_install_property (oclass, PROP_SHOW_OFFLINE, spec);
317 spec = g_param_spec_boolean ("show-groups", "Show Groups",
320 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
321 g_object_class_install_property (oclass, PROP_SHOW_GROUPS, spec);
323 g_type_class_add_private (klass, sizeof (EmpathyRosterViewPriv));
327 empathy_roster_view_init (EmpathyRosterView *self)
329 self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
330 EMPATHY_TYPE_ROSTER_VIEW, EmpathyRosterViewPriv);
332 self->priv->roster_contacts = g_hash_table_new (NULL, NULL);
336 empathy_roster_view_new (EmpathyIndividualManager *manager)
338 g_return_val_if_fail (EMPATHY_IS_INDIVIDUAL_MANAGER (manager), NULL);
340 return g_object_new (EMPATHY_TYPE_ROSTER_VIEW,
345 EmpathyIndividualManager *
346 empathy_roster_view_get_manager (EmpathyRosterView *self)
348 return self->priv->manager;
352 empathy_roster_view_show_offline (EmpathyRosterView *self,
355 if (self->priv->show_offline == show)
358 self->priv->show_offline = show;
359 egg_list_box_refilter (EGG_LIST_BOX (self));
361 g_object_notify (G_OBJECT (self), "show-offline");
365 clear_view (EmpathyRosterView *self)
367 gtk_container_foreach (GTK_CONTAINER (self),
368 (GtkCallback) gtk_widget_destroy, NULL);
370 g_hash_table_remove_all (self->priv->roster_contacts);
374 empathy_roster_view_show_groups (EmpathyRosterView *self,
377 if (self->priv->show_groups == show)
380 self->priv->show_groups = show;
383 populate_view (self);
385 g_object_notify (G_OBJECT (self), "show-groups");