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>
24 #include <libmissioncontrol/mc-enum-types.h>
26 #include "empathy-contact-monitor.h"
27 #include "empathy-contact-list.h"
29 #include "empathy-contact.h"
30 #include "empathy-utils.h"
31 #include "empathy-marshal.h"
33 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyContactMonitor)
36 EmpathyContactList *iface;
40 } EmpathyContactMonitorPriv;
44 CONTACT_AVATAR_CHANGED,
45 CONTACT_CAPABILITIES_CHANGED,
47 CONTACT_PRESENCE_CHANGED,
48 CONTACT_PRESENCE_MESSAGE_CHANGED,
58 static guint signals[LAST_SIGNAL];
60 G_DEFINE_TYPE (EmpathyContactMonitor, empathy_contact_monitor, G_TYPE_OBJECT);
63 contact_monitor_presence_changed_cb (EmpathyContact *contact,
64 McPresence current_presence,
65 McPresence previous_presence,
66 EmpathyContactMonitor *self)
68 g_signal_emit (self, signals[CONTACT_PRESENCE_CHANGED], 0, contact,
69 current_presence, previous_presence);
73 contact_monitor_presence_message_changed_cb (EmpathyContact *contact,
75 EmpathyContactMonitor *self)
79 /* use the status so that we always have a presence message */
80 status = empathy_contact_get_status (contact);
82 g_signal_emit (self, signals[CONTACT_PRESENCE_MESSAGE_CHANGED], 0,
87 contact_monitor_name_changed_cb (EmpathyContact *contact,
89 EmpathyContactMonitor *self)
93 name = empathy_contact_get_name (contact);
95 g_signal_emit (self, signals[CONTACT_NAME_CHANGED], 0, contact, name);
99 contact_monitor_avatar_changed_cb (EmpathyContact *contact,
101 EmpathyContactMonitor *self)
103 /* don't emit a pixbuf in the signal, as we don't depend on GTK+ here
106 g_signal_emit (self, signals[CONTACT_AVATAR_CHANGED], 0, contact);
110 contact_monitor_capabilities_changed_cb (EmpathyContact *contact,
112 EmpathyContactMonitor *self)
114 g_signal_emit (self, signals[CONTACT_CAPABILITIES_CHANGED], 0, contact);
118 contact_add (EmpathyContactMonitor *monitor,
119 EmpathyContact *contact)
121 EmpathyContactMonitorPriv *priv = GET_PRIV (monitor);
123 g_signal_connect (contact, "presence-changed",
124 G_CALLBACK (contact_monitor_presence_changed_cb),
126 g_signal_connect (contact, "notify::presence-message",
127 G_CALLBACK (contact_monitor_presence_message_changed_cb),
129 g_signal_connect (contact, "notify::name",
130 G_CALLBACK (contact_monitor_name_changed_cb),
132 g_signal_connect (contact, "notify::avatar",
133 G_CALLBACK (contact_monitor_avatar_changed_cb),
135 g_signal_connect (contact, "notify::capabilities",
136 G_CALLBACK (contact_monitor_capabilities_changed_cb),
139 priv->contacts = g_list_prepend (priv->contacts, g_object_ref (contact));
141 g_signal_emit (monitor, signals[CONTACT_ADDED], 0, contact);
145 contact_remove (EmpathyContactMonitor *monitor,
146 EmpathyContact *contact)
148 EmpathyContactMonitorPriv *priv = GET_PRIV (monitor);
150 g_signal_handlers_disconnect_by_func (contact,
151 G_CALLBACK (contact_monitor_presence_changed_cb),
153 g_signal_handlers_disconnect_by_func (contact,
154 G_CALLBACK (contact_monitor_presence_message_changed_cb),
156 g_signal_handlers_disconnect_by_func (contact,
157 G_CALLBACK (contact_monitor_name_changed_cb),
159 g_signal_handlers_disconnect_by_func (contact,
160 G_CALLBACK (contact_monitor_avatar_changed_cb),
162 g_signal_handlers_disconnect_by_func (contact,
163 G_CALLBACK (contact_monitor_capabilities_changed_cb),
166 priv->contacts = g_list_remove (priv->contacts, contact);
168 g_signal_emit (monitor, signals[CONTACT_REMOVED], 0, contact);
170 g_object_unref (contact);
174 contact_remove_foreach (EmpathyContact *contact,
175 EmpathyContactMonitor *monitor)
177 contact_remove (monitor, contact);
181 cl_members_changed_cb (EmpathyContactList *cl,
182 EmpathyContact *contact,
183 EmpathyContact *actor,
187 EmpathyContactMonitor *monitor)
190 contact_add (monitor, contact);
192 contact_remove (monitor, contact);
196 do_set_property (GObject *object,
204 empathy_contact_monitor_set_iface (EMPATHY_CONTACT_MONITOR (object),
205 g_value_get_object (value));
208 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
214 do_get_property (GObject *object,
219 EmpathyContactMonitorPriv *priv = GET_PRIV (object);
224 g_value_set_object (value, priv->iface);
227 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
233 do_finalize (GObject *obj)
235 EmpathyContactMonitorPriv *priv;
237 priv = GET_PRIV (obj);
241 g_list_free (priv->contacts);
242 priv->contacts = NULL;
246 g_signal_handlers_disconnect_by_func (priv->iface,
247 cl_members_changed_cb, obj);
249 G_OBJECT_CLASS (empathy_contact_monitor_parent_class)->finalize (obj);
253 do_dispose (GObject *obj)
255 EmpathyContactMonitorPriv *priv;
257 priv = GET_PRIV (obj);
259 if (priv->dispose_run)
262 priv->dispose_run = TRUE;
265 g_list_foreach (priv->contacts,
266 (GFunc) contact_remove_foreach, obj);
269 g_signal_handlers_disconnect_by_func (priv->iface,
270 cl_members_changed_cb, obj);
272 G_OBJECT_CLASS (empathy_contact_monitor_parent_class)->dispose (obj);
276 empathy_contact_monitor_class_init (EmpathyContactMonitorClass *klass)
278 GObjectClass *oclass = G_OBJECT_CLASS (klass);
280 oclass->finalize = do_finalize;
281 oclass->dispose = do_dispose;
282 oclass->get_property = do_get_property;
283 oclass->set_property = do_set_property;
285 g_object_class_install_property (oclass,
287 g_param_spec_object ("iface",
289 "The contact list we're monitoring",
290 EMPATHY_TYPE_CONTACT_LIST,
292 G_PARAM_CONSTRUCT_ONLY |
293 G_PARAM_STATIC_STRINGS));
295 signals[CONTACT_ADDED] =
296 g_signal_new ("contact-added",
297 G_TYPE_FROM_CLASS (klass),
301 g_cclosure_marshal_VOID__OBJECT,
303 1, EMPATHY_TYPE_CONTACT);
304 signals[CONTACT_AVATAR_CHANGED] =
305 g_signal_new ("contact-avatar-changed",
306 G_TYPE_FROM_CLASS (klass),
310 g_cclosure_marshal_VOID__OBJECT,
312 1, EMPATHY_TYPE_CONTACT);
313 signals[CONTACT_CAPABILITIES_CHANGED] =
314 g_signal_new ("contact-capabilities-changed",
315 G_TYPE_FROM_CLASS (klass),
319 g_cclosure_marshal_VOID__OBJECT,
321 1, EMPATHY_TYPE_CONTACT);
322 signals[CONTACT_NAME_CHANGED] =
323 g_signal_new ("contact-name-changed",
324 G_TYPE_FROM_CLASS (klass),
328 _empathy_marshal_VOID__OBJECT_STRING,
330 2, EMPATHY_TYPE_CONTACT,
332 signals[CONTACT_PRESENCE_CHANGED] =
333 g_signal_new ("contact-presence-changed",
334 G_TYPE_FROM_CLASS (klass),
338 _empathy_marshal_VOID__OBJECT_ENUM_ENUM,
340 3, EMPATHY_TYPE_CONTACT,
343 signals[CONTACT_PRESENCE_MESSAGE_CHANGED] =
344 g_signal_new ("contact-presence-message-changed",
345 G_TYPE_FROM_CLASS (klass),
349 _empathy_marshal_VOID__OBJECT_STRING,
351 2, EMPATHY_TYPE_CONTACT,
353 signals[CONTACT_REMOVED] =
354 g_signal_new ("contact-removed",
355 G_TYPE_FROM_CLASS (klass),
359 g_cclosure_marshal_VOID__OBJECT,
361 1, EMPATHY_TYPE_CONTACT);
363 g_type_class_add_private (klass, sizeof (EmpathyContactMonitorPriv));
367 empathy_contact_monitor_init (EmpathyContactMonitor *self)
369 EmpathyContactMonitorPriv *priv =
370 G_TYPE_INSTANCE_GET_PRIVATE (self, EMPATHY_TYPE_CONTACT_MONITOR,
371 EmpathyContactMonitorPriv);
374 priv->contacts = NULL;
376 priv->dispose_run = FALSE;
382 empathy_contact_monitor_set_iface (EmpathyContactMonitor *self,
383 EmpathyContactList *iface)
385 EmpathyContactMonitorPriv *priv;
387 g_return_if_fail (EMPATHY_IS_CONTACT_MONITOR (self));
388 g_return_if_fail (EMPATHY_IS_CONTACT_LIST (iface));
390 priv = GET_PRIV (self);
392 if (priv->contacts != NULL)
394 g_list_foreach (priv->contacts,
395 (GFunc) contact_remove_foreach, self);
396 g_list_free (priv->contacts);
397 priv->contacts = NULL;
402 g_signal_connect (iface, "members-changed",
403 G_CALLBACK (cl_members_changed_cb), self);
406 EmpathyContactMonitor *
407 empathy_contact_monitor_new_for_iface (EmpathyContactList *iface)
409 EmpathyContactMonitor *retval;
411 g_return_val_if_fail (EMPATHY_IS_CONTACT_LIST (iface), NULL);
413 retval = g_object_new (EMPATHY_TYPE_CONTACT_MONITOR,
414 "iface", iface, NULL);