1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2008 Collabora Ltd.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library 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 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 * Authors: Cosimo Cecchi <cosimo.cecchi@collabora.co.uk>
22 #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 *proxy;
38 } EmpathyContactMonitorPriv;
42 CONTACT_AVATAR_CHANGED,
43 CONTACT_CAPABILITIES_CHANGED,
45 CONTACT_PRESENCE_CHANGED,
46 CONTACT_PRESENCE_MESSAGE_CHANGED,
56 static void contact_remove_foreach (EmpathyContact *contact,
57 EmpathyContactMonitor *monitor);
58 static void cl_members_changed_cb (EmpathyContactList *cl,
59 EmpathyContact *contact,
60 EmpathyContact *actor,
64 EmpathyContactMonitor *monitor);
66 static guint signals[LAST_SIGNAL];
68 G_DEFINE_TYPE (EmpathyContactMonitor, empathy_contact_monitor, G_TYPE_OBJECT);
71 do_set_property (GObject *object,
78 empathy_contact_monitor_set_proxy
79 (EMPATHY_CONTACT_MONITOR (object),
80 g_value_get_object (value));
83 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
89 do_get_property (GObject *object,
94 EmpathyContactMonitorPriv *priv = GET_PRIV (object);
98 g_value_set_object (value, priv->proxy);
101 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
107 do_finalize (GObject *obj)
109 EmpathyContactMonitorPriv *priv;
111 priv = GET_PRIV (obj);
113 if (priv->contacts) {
114 g_ptr_array_foreach (priv->contacts,
115 (GFunc) contact_remove_foreach, obj);
116 g_ptr_array_free (priv->contacts, TRUE);
117 priv->contacts = NULL;
121 g_signal_handlers_disconnect_by_func (priv->proxy,
122 cl_members_changed_cb, obj);
125 G_OBJECT_CLASS (empathy_contact_monitor_parent_class)->finalize (obj);
129 empathy_contact_monitor_class_init (EmpathyContactMonitorClass *klass)
131 GObjectClass *oclass = G_OBJECT_CLASS (klass);
133 oclass->finalize = do_finalize;
134 oclass->get_property = do_get_property;
135 oclass->set_property = do_set_property;
137 g_object_class_install_property (oclass,
139 g_param_spec_object ("proxy",
141 "The contact list associated we're monitoring",
142 EMPATHY_TYPE_CONTACT_LIST,
144 G_PARAM_CONSTRUCT_ONLY |
145 G_PARAM_STATIC_STRINGS));
147 signals[CONTACT_ADDED] =
148 g_signal_new ("contact-added",
149 G_TYPE_FROM_CLASS (klass),
153 g_cclosure_marshal_VOID__OBJECT,
155 1, EMPATHY_TYPE_CONTACT);
156 signals[CONTACT_AVATAR_CHANGED] =
157 g_signal_new ("contact-avatar-changed",
158 G_TYPE_FROM_CLASS (klass),
162 g_cclosure_marshal_VOID__OBJECT,
164 1, EMPATHY_TYPE_CONTACT);
165 signals[CONTACT_CAPABILITIES_CHANGED] =
166 g_signal_new ("contact-capabilities-changed",
167 G_TYPE_FROM_CLASS (klass),
171 g_cclosure_marshal_VOID__OBJECT,
173 1, EMPATHY_TYPE_CONTACT);
174 signals[CONTACT_NAME_CHANGED] =
175 g_signal_new ("contact-name-changed",
176 G_TYPE_FROM_CLASS (klass),
180 _empathy_marshal_VOID__OBJECT_STRING,
182 2, EMPATHY_TYPE_CONTACT,
184 signals[CONTACT_PRESENCE_CHANGED] =
185 g_signal_new ("contact-presence-changed",
186 G_TYPE_FROM_CLASS (klass),
190 _empathy_marshal_VOID__OBJECT_ENUM_ENUM,
192 3, EMPATHY_TYPE_CONTACT,
195 signals[CONTACT_PRESENCE_MESSAGE_CHANGED] =
196 g_signal_new ("contact-presence-message-changed",
197 G_TYPE_FROM_CLASS (klass),
201 _empathy_marshal_VOID__OBJECT_STRING,
203 2, EMPATHY_TYPE_CONTACT,
205 signals[CONTACT_REMOVED] =
206 g_signal_new ("contact-removed",
207 G_TYPE_FROM_CLASS (klass),
211 g_cclosure_marshal_VOID__OBJECT,
213 1, EMPATHY_TYPE_CONTACT);
215 g_type_class_add_private (klass, sizeof (EmpathyContactMonitorPriv));
219 empathy_contact_monitor_init (EmpathyContactMonitor *self)
221 EmpathyContactMonitorPriv *priv =
222 G_TYPE_INSTANCE_GET_PRIVATE (self,
223 EMPATHY_TYPE_CONTACT_MONITOR, EmpathyContactMonitorPriv);
226 priv->contacts = NULL;
231 contact_monitor_presence_changed_cb (EmpathyContact *contact,
232 McPresence current_presence,
233 McPresence previous_presence,
234 EmpathyContactMonitor *self)
236 g_signal_emit (self, signals[CONTACT_PRESENCE_CHANGED], 0, contact,
237 current_presence, previous_presence);
241 contact_monitor_presence_message_changed_cb (EmpathyContact *contact,
243 EmpathyContactMonitor *self)
247 /* use the status so that we always have a presence message */
248 status = empathy_contact_get_status (contact);
250 g_signal_emit (self, signals[CONTACT_PRESENCE_MESSAGE_CHANGED], 0,
255 contact_monitor_name_changed_cb (EmpathyContact *contact,
257 EmpathyContactMonitor *self)
261 name = empathy_contact_get_name (contact);
263 g_signal_emit (self, signals[CONTACT_NAME_CHANGED], 0, contact, name);
267 contact_monitor_avatar_changed_cb (EmpathyContact *contact,
269 EmpathyContactMonitor *self)
271 /* don't emit a pixbuf in the signal, as we don't know how large
272 * a client would like it to be.
275 g_signal_emit (self, signals[CONTACT_AVATAR_CHANGED], 0, contact);
279 contact_monitor_capabilities_changed_cb (EmpathyContact *contact,
281 EmpathyContactMonitor *self)
283 g_signal_emit (self, signals[CONTACT_CAPABILITIES_CHANGED], 0, contact);
287 contact_add (EmpathyContactMonitor *monitor,
288 EmpathyContact *contact)
290 EmpathyContactMonitorPriv *priv = GET_PRIV (monitor);
292 g_signal_connect (contact, "presence-changed",
293 G_CALLBACK (contact_monitor_presence_changed_cb),
295 g_signal_connect (contact, "notify::presence-message",
296 G_CALLBACK (contact_monitor_presence_message_changed_cb),
298 g_signal_connect (contact, "notify::name",
299 G_CALLBACK (contact_monitor_name_changed_cb),
301 g_signal_connect (contact, "notify::avatar",
302 G_CALLBACK (contact_monitor_avatar_changed_cb),
304 g_signal_connect (contact, "notify::capabilities",
305 G_CALLBACK (contact_monitor_capabilities_changed_cb),
308 g_ptr_array_add (priv->contacts, g_object_ref (contact));
310 g_signal_emit (monitor, signals[CONTACT_ADDED], 0, contact);
314 contact_remove (EmpathyContactMonitor *monitor,
315 EmpathyContact *contact)
317 EmpathyContactMonitorPriv *priv = GET_PRIV (monitor);
319 g_signal_handlers_disconnect_by_func (contact,
320 G_CALLBACK (contact_monitor_presence_changed_cb),
322 g_signal_handlers_disconnect_by_func (contact,
323 G_CALLBACK (contact_monitor_presence_message_changed_cb),
325 g_signal_handlers_disconnect_by_func (contact,
326 G_CALLBACK (contact_monitor_name_changed_cb),
328 g_signal_handlers_disconnect_by_func (contact,
329 G_CALLBACK (contact_monitor_avatar_changed_cb),
331 g_signal_handlers_disconnect_by_func (contact,
332 G_CALLBACK (contact_monitor_capabilities_changed_cb),
335 g_ptr_array_remove (priv->contacts, contact);
337 g_signal_emit (monitor, signals[CONTACT_REMOVED], 0, contact);
339 g_object_unref (contact);
343 contact_remove_foreach (EmpathyContact *contact,
344 EmpathyContactMonitor *monitor)
346 contact_remove (monitor, contact);
350 cl_members_changed_cb (EmpathyContactList *cl,
351 EmpathyContact *contact,
352 EmpathyContact *actor,
356 EmpathyContactMonitor *monitor)
359 contact_add (monitor, contact);
361 contact_remove (monitor, contact);
368 empathy_contact_monitor_set_proxy (EmpathyContactMonitor *self,
369 EmpathyContactList *proxy)
371 EmpathyContactMonitorPriv *priv;
373 g_assert (EMPATHY_IS_CONTACT_MONITOR (self));
374 g_assert (EMPATHY_IS_CONTACT_LIST (proxy));
376 priv = GET_PRIV (self);
378 if (priv->contacts != NULL) {
379 g_ptr_array_foreach (priv->contacts,
380 (GFunc) contact_remove_foreach, self);
381 g_ptr_array_free (priv->contacts, TRUE);
382 priv->contacts = NULL;
386 priv->contacts = g_ptr_array_new ();
388 g_signal_connect (proxy, "members-changed",
389 G_CALLBACK (cl_members_changed_cb), self);
392 EmpathyContactMonitor *
393 empathy_contact_monitor_new_for_proxy (EmpathyContactList *proxy)
395 EmpathyContactMonitor *retval;
397 g_assert (EMPATHY_IS_CONTACT_LIST (proxy));
399 retval = g_object_new (EMPATHY_TYPE_CONTACT_MONITOR,
400 "proxy", proxy, NULL);