2 * Copyright (C) 2008 Collabora Ltd.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 * Authors: Cosimo Cecchi <cosimo.cecchi@collabora.co.uk>
23 #include <glib-object.h>
25 #include "empathy-contact-monitor.h"
26 #include "empathy-contact-list.h"
28 #include "empathy-contact.h"
29 #include "empathy-utils.h"
30 #include "empathy-marshal.h"
32 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyContactMonitor)
35 EmpathyContactList *iface;
39 } EmpathyContactMonitorPriv;
43 CONTACT_AVATAR_CHANGED,
44 CONTACT_CAPABILITIES_CHANGED,
46 CONTACT_PRESENCE_CHANGED,
47 CONTACT_PRESENCE_MESSAGE_CHANGED,
57 static guint signals[LAST_SIGNAL];
59 G_DEFINE_TYPE (EmpathyContactMonitor, empathy_contact_monitor, G_TYPE_OBJECT);
62 contact_monitor_presence_changed_cb (EmpathyContact *contact,
63 TpConnectionPresenceType current_presence,
64 TpConnectionPresenceType previous_presence,
65 EmpathyContactMonitor *self)
67 g_signal_emit (self, signals[CONTACT_PRESENCE_CHANGED], 0, contact,
68 current_presence, previous_presence);
72 contact_monitor_presence_message_changed_cb (EmpathyContact *contact,
74 EmpathyContactMonitor *self)
78 /* use the status so that we always have a presence message */
79 status = empathy_contact_get_status (contact);
81 g_signal_emit (self, signals[CONTACT_PRESENCE_MESSAGE_CHANGED], 0,
86 contact_monitor_name_changed_cb (EmpathyContact *contact,
88 EmpathyContactMonitor *self)
92 name = empathy_contact_get_name (contact);
94 g_signal_emit (self, signals[CONTACT_NAME_CHANGED], 0, contact, name);
98 contact_monitor_avatar_changed_cb (EmpathyContact *contact,
100 EmpathyContactMonitor *self)
102 /* don't emit a pixbuf in the signal, as we don't depend on GTK+ here
105 g_signal_emit (self, signals[CONTACT_AVATAR_CHANGED], 0, contact);
109 contact_monitor_capabilities_changed_cb (EmpathyContact *contact,
111 EmpathyContactMonitor *self)
113 g_signal_emit (self, signals[CONTACT_CAPABILITIES_CHANGED], 0, contact);
117 contact_add (EmpathyContactMonitor *monitor,
118 EmpathyContact *contact)
120 EmpathyContactMonitorPriv *priv = GET_PRIV (monitor);
122 g_signal_connect (contact, "presence-changed",
123 G_CALLBACK (contact_monitor_presence_changed_cb),
125 g_signal_connect (contact, "notify::presence-message",
126 G_CALLBACK (contact_monitor_presence_message_changed_cb),
128 g_signal_connect (contact, "notify::name",
129 G_CALLBACK (contact_monitor_name_changed_cb),
131 g_signal_connect (contact, "notify::avatar",
132 G_CALLBACK (contact_monitor_avatar_changed_cb),
134 g_signal_connect (contact, "notify::capabilities",
135 G_CALLBACK (contact_monitor_capabilities_changed_cb),
138 priv->contacts = g_list_prepend (priv->contacts, g_object_ref (contact));
140 g_signal_emit (monitor, signals[CONTACT_ADDED], 0, contact);
144 contact_remove (EmpathyContactMonitor *monitor,
145 EmpathyContact *contact)
147 EmpathyContactMonitorPriv *priv = GET_PRIV (monitor);
149 g_signal_handlers_disconnect_by_func (contact,
150 G_CALLBACK (contact_monitor_presence_changed_cb),
152 g_signal_handlers_disconnect_by_func (contact,
153 G_CALLBACK (contact_monitor_presence_message_changed_cb),
155 g_signal_handlers_disconnect_by_func (contact,
156 G_CALLBACK (contact_monitor_name_changed_cb),
158 g_signal_handlers_disconnect_by_func (contact,
159 G_CALLBACK (contact_monitor_avatar_changed_cb),
161 g_signal_handlers_disconnect_by_func (contact,
162 G_CALLBACK (contact_monitor_capabilities_changed_cb),
165 priv->contacts = g_list_remove (priv->contacts, contact);
167 g_signal_emit (monitor, signals[CONTACT_REMOVED], 0, contact);
169 g_object_unref (contact);
173 contact_remove_foreach (EmpathyContact *contact,
174 EmpathyContactMonitor *monitor)
176 contact_remove (monitor, contact);
180 cl_members_changed_cb (EmpathyContactList *cl,
181 EmpathyContact *contact,
182 EmpathyContact *actor,
186 EmpathyContactMonitor *monitor)
189 contact_add (monitor, contact);
191 contact_remove (monitor, contact);
195 do_set_property (GObject *object,
203 empathy_contact_monitor_set_iface (EMPATHY_CONTACT_MONITOR (object),
204 g_value_get_object (value));
207 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
213 do_get_property (GObject *object,
218 EmpathyContactMonitorPriv *priv = GET_PRIV (object);
223 g_value_set_object (value, priv->iface);
226 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
232 do_finalize (GObject *obj)
234 EmpathyContactMonitorPriv *priv;
236 priv = GET_PRIV (obj);
240 g_list_free (priv->contacts);
241 priv->contacts = NULL;
245 g_signal_handlers_disconnect_by_func (priv->iface,
246 cl_members_changed_cb, obj);
248 G_OBJECT_CLASS (empathy_contact_monitor_parent_class)->finalize (obj);
252 do_dispose (GObject *obj)
254 EmpathyContactMonitorPriv *priv;
256 priv = GET_PRIV (obj);
258 if (priv->dispose_run)
261 priv->dispose_run = TRUE;
264 g_list_foreach (priv->contacts,
265 (GFunc) contact_remove_foreach, obj);
268 g_signal_handlers_disconnect_by_func (priv->iface,
269 cl_members_changed_cb, obj);
271 G_OBJECT_CLASS (empathy_contact_monitor_parent_class)->dispose (obj);
275 empathy_contact_monitor_class_init (EmpathyContactMonitorClass *klass)
277 GObjectClass *oclass = G_OBJECT_CLASS (klass);
279 oclass->finalize = do_finalize;
280 oclass->dispose = do_dispose;
281 oclass->get_property = do_get_property;
282 oclass->set_property = do_set_property;
284 g_object_class_install_property (oclass,
286 g_param_spec_object ("iface",
288 "The contact list we're monitoring",
289 EMPATHY_TYPE_CONTACT_LIST,
291 G_PARAM_CONSTRUCT_ONLY |
292 G_PARAM_STATIC_STRINGS));
294 signals[CONTACT_ADDED] =
295 g_signal_new ("contact-added",
296 G_TYPE_FROM_CLASS (klass),
300 g_cclosure_marshal_VOID__OBJECT,
302 1, EMPATHY_TYPE_CONTACT);
303 signals[CONTACT_AVATAR_CHANGED] =
304 g_signal_new ("contact-avatar-changed",
305 G_TYPE_FROM_CLASS (klass),
309 g_cclosure_marshal_VOID__OBJECT,
311 1, EMPATHY_TYPE_CONTACT);
312 signals[CONTACT_CAPABILITIES_CHANGED] =
313 g_signal_new ("contact-capabilities-changed",
314 G_TYPE_FROM_CLASS (klass),
318 g_cclosure_marshal_VOID__OBJECT,
320 1, EMPATHY_TYPE_CONTACT);
321 signals[CONTACT_NAME_CHANGED] =
322 g_signal_new ("contact-name-changed",
323 G_TYPE_FROM_CLASS (klass),
327 _empathy_marshal_VOID__OBJECT_STRING,
329 2, EMPATHY_TYPE_CONTACT,
331 signals[CONTACT_PRESENCE_CHANGED] =
332 g_signal_new ("contact-presence-changed",
333 G_TYPE_FROM_CLASS (klass),
337 _empathy_marshal_VOID__OBJECT_UINT_UINT,
339 3, EMPATHY_TYPE_CONTACT,
342 signals[CONTACT_PRESENCE_MESSAGE_CHANGED] =
343 g_signal_new ("contact-presence-message-changed",
344 G_TYPE_FROM_CLASS (klass),
348 _empathy_marshal_VOID__OBJECT_STRING,
350 2, EMPATHY_TYPE_CONTACT,
352 signals[CONTACT_REMOVED] =
353 g_signal_new ("contact-removed",
354 G_TYPE_FROM_CLASS (klass),
358 g_cclosure_marshal_VOID__OBJECT,
360 1, EMPATHY_TYPE_CONTACT);
362 g_type_class_add_private (klass, sizeof (EmpathyContactMonitorPriv));
366 empathy_contact_monitor_init (EmpathyContactMonitor *self)
368 EmpathyContactMonitorPriv *priv =
369 G_TYPE_INSTANCE_GET_PRIVATE (self, EMPATHY_TYPE_CONTACT_MONITOR,
370 EmpathyContactMonitorPriv);
373 priv->contacts = NULL;
375 priv->dispose_run = FALSE;
381 empathy_contact_monitor_set_iface (EmpathyContactMonitor *self,
382 EmpathyContactList *iface)
384 EmpathyContactMonitorPriv *priv;
386 g_return_if_fail (EMPATHY_IS_CONTACT_MONITOR (self));
387 g_return_if_fail (EMPATHY_IS_CONTACT_LIST (iface));
389 priv = GET_PRIV (self);
391 if (priv->contacts != NULL)
393 g_list_foreach (priv->contacts,
394 (GFunc) contact_remove_foreach, self);
395 g_list_free (priv->contacts);
396 priv->contacts = NULL;
401 g_signal_connect (iface, "members-changed",
402 G_CALLBACK (cl_members_changed_cb), self);
405 EmpathyContactMonitor *
406 empathy_contact_monitor_new_for_iface (EmpathyContactList *iface)
408 EmpathyContactMonitor *retval;
410 g_return_val_if_fail (EMPATHY_IS_CONTACT_LIST (iface), NULL);
412 retval = g_object_new (EMPATHY_TYPE_CONTACT_MONITOR,
413 "iface", iface, NULL);