1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2004-2007 Imendio AB
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
10 * This program 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 * General Public License for more details.
15 * You should have received a copy of the GNU General Public
16 * License along with this program; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Authors: Mikael Hallendal <micke@imendio.com>
21 * Martyn Russell <martyn@imendio.com>
28 #include <glib/gi18n.h>
30 #include "gossip-contact.h"
31 #include "gossip-utils.h"
32 #include "gossip-debug.h"
34 #define DEBUG_DOMAIN "Contact"
36 #define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GOSSIP_TYPE_CONTACT, GossipContactPriv))
38 typedef struct _GossipContactPriv GossipContactPriv;
40 struct _GossipContactPriv {
45 GossipPresence *presence;
47 GossipSubscription subscription;
52 static void contact_class_init (GossipContactClass *class);
53 static void contact_init (GossipContact *contact);
54 static void contact_finalize (GObject *object);
55 static void contact_get_property (GObject *object,
59 static void contact_set_property (GObject *object,
77 static gpointer parent_class = NULL;
80 gossip_contact_get_gtype (void)
82 static GType type = 0;
85 static const GTypeInfo info = {
86 sizeof (GossipContactClass),
88 NULL, /* base_finalize */
89 (GClassInitFunc) contact_class_init,
90 NULL, /* class_finalize */
91 NULL, /* class_data */
92 sizeof (GossipContact),
94 (GInstanceInitFunc) contact_init
97 type = g_type_register_static (G_TYPE_OBJECT,
106 contact_class_init (GossipContactClass *class)
108 GObjectClass *object_class;
110 object_class = G_OBJECT_CLASS (class);
111 parent_class = g_type_class_peek_parent (class);
113 object_class->finalize = contact_finalize;
114 object_class->get_property = contact_get_property;
115 object_class->set_property = contact_set_property;
117 g_object_class_install_property (object_class,
119 g_param_spec_string ("id",
121 "String identifying contact",
125 g_object_class_install_property (object_class,
127 g_param_spec_string ("name",
129 "The name of the contact",
133 g_object_class_install_property (object_class,
135 g_param_spec_boxed ("avatar",
141 g_object_class_install_property (object_class,
143 g_param_spec_object ("account",
145 "The account associated with the contact",
149 g_object_class_install_property (object_class,
151 g_param_spec_object ("presence",
153 "Presence of contact",
154 GOSSIP_TYPE_PRESENCE,
157 g_object_class_install_property (object_class,
159 g_param_spec_pointer ("groups",
164 g_object_class_install_property (object_class,
166 g_param_spec_int ("subscription",
167 "Contact Subscription",
168 "The subscription status of the contact",
169 GOSSIP_SUBSCRIPTION_NONE,
170 GOSSIP_SUBSCRIPTION_BOTH,
171 GOSSIP_SUBSCRIPTION_NONE,
175 g_object_class_install_property (object_class,
177 g_param_spec_uint ("handle",
179 "The handle of the contact",
184 g_object_class_install_property (object_class,
186 g_param_spec_boolean ("is-user",
188 "Is contact the user",
192 g_type_class_add_private (object_class, sizeof (GossipContactPriv));
196 contact_init (GossipContact *contact)
201 contact_finalize (GObject *object)
203 GossipContactPriv *priv;
205 priv = GET_PRIV (object);
207 gossip_debug (DEBUG_DOMAIN, "finalize: %p", object);
213 gossip_avatar_unref (priv->avatar);
216 if (priv->presence) {
217 g_object_unref (priv->presence);
221 g_list_foreach (priv->groups, (GFunc) g_free, NULL);
222 g_list_free (priv->groups);
226 g_object_unref (priv->account);
229 (G_OBJECT_CLASS (parent_class)->finalize) (object);
233 contact_get_property (GObject *object,
238 GossipContactPriv *priv;
240 priv = GET_PRIV (object);
244 g_value_set_string (value,
245 gossip_contact_get_id (GOSSIP_CONTACT (object)));
248 g_value_set_string (value,
249 gossip_contact_get_name (GOSSIP_CONTACT (object)));
252 g_value_set_boxed (value, priv->avatar);
255 g_value_set_object (value, priv->account);
258 g_value_set_object (value, priv->presence);
261 g_value_set_pointer (value, priv->groups);
263 case PROP_SUBSCRIPTION:
264 g_value_set_int (value, priv->subscription);
267 g_value_set_uint (value, priv->handle);
270 g_value_set_boolean (value, priv->is_user);
273 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
279 contact_set_property (GObject *object,
284 GossipContactPriv *priv;
286 priv = GET_PRIV (object);
290 gossip_contact_set_id (GOSSIP_CONTACT (object),
291 g_value_get_string (value));
294 gossip_contact_set_name (GOSSIP_CONTACT (object),
295 g_value_get_string (value));
298 gossip_contact_set_avatar (GOSSIP_CONTACT (object),
299 g_value_get_boxed (value));
302 gossip_contact_set_account (GOSSIP_CONTACT (object),
303 MC_ACCOUNT (g_value_get_object (value)));
306 gossip_contact_set_presence (GOSSIP_CONTACT (object),
307 GOSSIP_PRESENCE (g_value_get_object (value)));
310 gossip_contact_set_groups (GOSSIP_CONTACT (object),
311 g_value_get_pointer (value));
313 case PROP_SUBSCRIPTION:
314 gossip_contact_set_subscription (GOSSIP_CONTACT (object),
315 g_value_get_int (value));
318 gossip_contact_set_handle (GOSSIP_CONTACT (object),
319 g_value_get_uint (value));
322 gossip_contact_set_is_user (GOSSIP_CONTACT (object),
323 g_value_get_boolean (value));
326 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
332 gossip_contact_new (McAccount *account)
334 return g_object_new (GOSSIP_TYPE_CONTACT,
340 gossip_contact_new_full (McAccount *account,
344 return g_object_new (GOSSIP_TYPE_CONTACT,
352 gossip_contact_get_id (GossipContact *contact)
354 GossipContactPriv *priv;
356 g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), "");
358 priv = GET_PRIV (contact);
368 gossip_contact_get_name (GossipContact *contact)
370 GossipContactPriv *priv;
372 g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), "");
374 priv = GET_PRIV (contact);
376 if (priv->name == NULL) {
377 return gossip_contact_get_id (contact);
384 gossip_contact_get_avatar (GossipContact *contact)
386 GossipContactPriv *priv;
388 g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), NULL);
390 priv = GET_PRIV (contact);
396 gossip_contact_get_account (GossipContact *contact)
398 GossipContactPriv *priv;
400 g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), NULL);
402 priv = GET_PRIV (contact);
404 return priv->account;
408 gossip_contact_get_presence (GossipContact *contact)
410 GossipContactPriv *priv;
412 g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), NULL);
414 priv = GET_PRIV (contact);
416 return priv->presence;
420 gossip_contact_get_groups (GossipContact *contact)
422 GossipContactPriv *priv;
424 g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), NULL);
426 priv = GET_PRIV (contact);
432 gossip_contact_get_subscription (GossipContact *contact)
434 GossipContactPriv *priv;
436 g_return_val_if_fail (GOSSIP_IS_CONTACT (contact),
437 GOSSIP_SUBSCRIPTION_NONE);
439 priv = GET_PRIV (contact);
441 return priv->subscription;
445 gossip_contact_get_handle (GossipContact *contact)
447 GossipContactPriv *priv;
449 g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), 0);
451 priv = GET_PRIV (contact);
457 gossip_contact_is_user (GossipContact *contact)
459 GossipContactPriv *priv;
461 g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), FALSE);
463 priv = GET_PRIV (contact);
465 return priv->is_user;
469 gossip_contact_set_id (GossipContact *contact,
472 GossipContactPriv *priv;
474 g_return_if_fail (GOSSIP_IS_CONTACT (contact));
475 g_return_if_fail (id != NULL);
477 priv = GET_PRIV (contact);
479 if (priv->id && strcmp (id, priv->id) == 0) {
484 priv->id = g_strdup (id);
486 g_object_notify (G_OBJECT (contact), "id");
490 gossip_contact_set_name (GossipContact *contact,
493 GossipContactPriv *priv;
495 g_return_if_fail (GOSSIP_IS_CONTACT (contact));
496 g_return_if_fail (name != NULL);
498 priv = GET_PRIV (contact);
500 if (priv->name && strcmp (name, priv->name) == 0) {
505 priv->name = g_strdup (name);
507 g_object_notify (G_OBJECT (contact), "name");
511 gossip_contact_set_avatar (GossipContact *contact,
512 GossipAvatar *avatar)
514 GossipContactPriv *priv;
516 g_return_if_fail (GOSSIP_IS_CONTACT (contact));
518 priv = GET_PRIV (contact);
520 if (priv->avatar == avatar) {
525 gossip_avatar_unref (priv->avatar);
530 priv->avatar = gossip_avatar_ref (avatar);
533 g_object_notify (G_OBJECT (contact), "avatar");
537 gossip_contact_set_account (GossipContact *contact,
540 GossipContactPriv *priv;
542 g_return_if_fail (GOSSIP_IS_CONTACT (contact));
543 g_return_if_fail (MC_IS_ACCOUNT (account));
545 priv = GET_PRIV (contact);
547 if (account == priv->account) {
552 g_object_unref (priv->account);
554 priv->account = g_object_ref (account);
556 g_object_notify (G_OBJECT (contact), "account");
560 gossip_contact_set_presence (GossipContact *contact,
561 GossipPresence *presence)
563 GossipContactPriv *priv;
565 g_return_if_fail (GOSSIP_IS_CONTACT (contact));
567 priv = GET_PRIV (contact);
569 if (presence == priv->presence) {
573 if (priv->presence) {
574 g_object_unref (priv->presence);
575 priv->presence = NULL;
579 priv->presence = g_object_ref (presence);
582 g_object_notify (G_OBJECT (contact), "presence");
586 gossip_contact_set_groups (GossipContact *contact,
589 GossipContactPriv *priv;
590 GList *old_groups, *l;
592 g_return_if_fail (GOSSIP_IS_CONTACT (contact));
594 priv = GET_PRIV (contact);
596 old_groups = priv->groups;
599 for (l = groups; l; l = l->next) {
600 priv->groups = g_list_append (priv->groups,
604 g_list_foreach (old_groups, (GFunc) g_free, NULL);
605 g_list_free (old_groups);
607 g_object_notify (G_OBJECT (contact), "groups");
611 gossip_contact_set_subscription (GossipContact *contact,
612 GossipSubscription subscription)
614 GossipContactPriv *priv;
616 g_return_if_fail (GOSSIP_IS_CONTACT (contact));
618 priv = GET_PRIV (contact);
620 if (priv->subscription == subscription) {
624 priv->subscription = subscription;
626 g_object_notify (G_OBJECT (contact), "subscription");
630 gossip_contact_set_handle (GossipContact *contact,
633 GossipContactPriv *priv;
635 g_return_if_fail (GOSSIP_IS_CONTACT (contact));
637 priv = GET_PRIV (contact);
639 if (priv->handle == handle) {
643 priv->handle = handle;
645 g_object_notify (G_OBJECT (contact), "handle");
649 gossip_contact_set_is_user (GossipContact *contact,
652 GossipContactPriv *priv;
654 g_return_if_fail (GOSSIP_IS_CONTACT (contact));
656 priv = GET_PRIV (contact);
658 if (priv->is_user == is_user) {
662 priv->is_user = is_user;
664 g_object_notify (G_OBJECT (contact), "is-user");
668 gossip_contact_add_group (GossipContact *contact,
671 GossipContactPriv *priv;
673 g_return_if_fail (GOSSIP_IS_CONTACT (contact));
674 g_return_if_fail (group != NULL);
676 priv = GET_PRIV (contact);
678 if (!g_list_find_custom (priv->groups, group, (GCompareFunc) strcmp)) {
679 priv->groups = g_list_prepend (priv->groups, g_strdup (group));
680 g_object_notify (G_OBJECT (contact), "groups");
685 gossip_contact_remove_group (GossipContact *contact,
688 GossipContactPriv *priv;
691 g_return_if_fail (GOSSIP_IS_CONTACT (contact));
692 g_return_if_fail (group != NULL);
694 priv = GET_PRIV (contact);
696 l = g_list_find_custom (priv->groups, group, (GCompareFunc) strcmp);
699 priv->groups = g_list_delete_link (priv->groups, l);
700 g_object_notify (G_OBJECT (contact), "groups");
705 gossip_contact_is_online (GossipContact *contact)
707 GossipContactPriv *priv;
709 g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), FALSE);
711 priv = GET_PRIV (contact);
713 return (priv->presence != NULL);
717 gossip_contact_is_in_group (GossipContact *contact,
720 GossipContactPriv *priv;
722 g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), FALSE);
723 g_return_val_if_fail (!G_STR_EMPTY (group), FALSE);
725 priv = GET_PRIV (contact);
727 if (g_list_find_custom (priv->groups, group, (GCompareFunc) strcmp)) {
735 gossip_contact_get_status (GossipContact *contact)
737 GossipContactPriv *priv;
739 g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), "");
741 priv = GET_PRIV (contact);
743 if (priv->presence) {
746 status = gossip_presence_get_status (priv->presence);
750 state = gossip_presence_get_state (priv->presence);
751 status = gossip_presence_state_get_default_status (state);
757 return gossip_presence_state_get_default_status (MC_PRESENCE_OFFLINE);
761 gossip_contact_equal (gconstpointer v1,
764 McAccount *account_a;
765 McAccount *account_b;
769 g_return_val_if_fail (GOSSIP_IS_CONTACT (v1), FALSE);
770 g_return_val_if_fail (GOSSIP_IS_CONTACT (v2), FALSE);
772 account_a = gossip_contact_get_account (GOSSIP_CONTACT (v1));
773 account_b = gossip_contact_get_account (GOSSIP_CONTACT (v2));
775 id_a = gossip_contact_get_id (GOSSIP_CONTACT (v1));
776 id_b = gossip_contact_get_id (GOSSIP_CONTACT (v2));
778 return gossip_account_equal (account_a, account_b) && g_str_equal (id_a, id_b);
782 gossip_contact_hash (gconstpointer key)
784 GossipContactPriv *priv;
787 g_return_val_if_fail (GOSSIP_IS_CONTACT (key), +1);
789 priv = GET_PRIV (GOSSIP_CONTACT (key));
791 hash = gossip_account_hash (gossip_contact_get_account (GOSSIP_CONTACT (key)));
792 hash += g_str_hash (gossip_contact_get_id (GOSSIP_CONTACT (key)));