]> git.0d.be Git - empathy.git/blob - libempathy/gossip-contact.c
Fix indentation Fix not returning the contact in tp_contact_list_find()
[empathy.git] / libempathy / gossip-contact.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2004-2007 Imendio AB
4  *
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.
9  *
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.
14  *
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.
19  *
20  * Authors: Mikael Hallendal <micke@imendio.com>
21  *          Martyn Russell <martyn@imendio.com>
22  */
23
24 #include "config.h"
25
26 #include <string.h>
27
28 #include <glib/gi18n.h>
29
30 #include "gossip-contact.h"
31 #include "gossip-utils.h"
32 #include "gossip-debug.h"
33 #include "empathy-contact-manager.h"
34
35 #define DEBUG_DOMAIN "Contact"
36
37 #define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GOSSIP_TYPE_CONTACT, GossipContactPriv))
38
39 typedef struct _GossipContactPriv GossipContactPriv;
40
41 struct _GossipContactPriv {
42         gchar              *id;
43         gchar              *name;
44         GossipAvatar       *avatar;
45         McAccount          *account;
46         GossipPresence     *presence;
47         GList              *groups;
48         GossipSubscription  subscription;
49         guint               handle;
50 };
51
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,
56                                    guint               param_id,
57                                    GValue             *value,
58                                    GParamSpec         *pspec);
59 static void contact_set_property  (GObject            *object,
60                                    guint               param_id,
61                                    const GValue       *value,
62                                    GParamSpec         *pspec);
63
64 enum {
65         PROP_0,
66         PROP_ID,
67         PROP_NAME,
68         PROP_AVATAR,
69         PROP_ACCOUNT,
70         PROP_PRESENCE,
71         PROP_GROUPS,
72         PROP_SUBSCRIPTION,
73         PROP_HANDLE
74 };
75
76 static gpointer parent_class = NULL;
77
78 GType
79 gossip_contact_get_gtype (void)
80 {
81         static GType type = 0;
82
83         if (!type) {
84                 static const GTypeInfo info = {
85                         sizeof (GossipContactClass),
86                         NULL, /* base_init */
87                         NULL, /* base_finalize */
88                         (GClassInitFunc) contact_class_init,
89                         NULL, /* class_finalize */
90                         NULL, /* class_data */
91                         sizeof (GossipContact),
92                         0,    /* n_preallocs */
93                         (GInstanceInitFunc) contact_init
94                 };
95
96                 type = g_type_register_static (G_TYPE_OBJECT,
97                                                "GossipContact",
98                                                &info, 0);
99         }
100
101         return type;
102 }
103
104 static void
105 contact_class_init (GossipContactClass *class)
106 {
107         GObjectClass *object_class;
108
109         object_class = G_OBJECT_CLASS (class);
110         parent_class = g_type_class_peek_parent (class);
111
112         object_class->finalize     = contact_finalize;
113         object_class->get_property = contact_get_property;
114         object_class->set_property = contact_set_property;
115
116         g_object_class_install_property (object_class,
117                                          PROP_ID,
118                                          g_param_spec_string ("id",
119                                                               "Contact id",
120                                                               "String identifying contact",
121                                                               NULL,
122                                                               G_PARAM_READWRITE));
123
124         g_object_class_install_property (object_class,
125                                          PROP_NAME,
126                                          g_param_spec_string ("name",
127                                                               "Contact Name",
128                                                               "The name of the contact",
129                                                               NULL,
130                                                               G_PARAM_READWRITE));
131
132         g_object_class_install_property (object_class,
133                                          PROP_AVATAR,
134                                          g_param_spec_boxed ("avatar",
135                                                              "Avatar image",
136                                                              "The avatar image",
137                                                              GOSSIP_TYPE_AVATAR,
138                                                              G_PARAM_READWRITE));
139
140         g_object_class_install_property (object_class,
141                                          PROP_ACCOUNT,
142                                          g_param_spec_object ("account",
143                                                               "Contact Account",
144                                                               "The account associated with the contact",
145                                                               MC_TYPE_ACCOUNT,
146                                                               G_PARAM_READWRITE));
147
148         g_object_class_install_property (object_class,
149                                          PROP_PRESENCE,
150                                          g_param_spec_object ("presence",
151                                                               "Contact presence",
152                                                               "Presence of contact",
153                                                               GOSSIP_TYPE_PRESENCE,
154                                                               G_PARAM_READWRITE));
155
156         g_object_class_install_property (object_class,
157                                          PROP_GROUPS,
158                                          g_param_spec_pointer ("groups",
159                                                                "Contact groups",
160                                                                "Groups of contact",
161                                                                G_PARAM_READWRITE));
162
163         g_object_class_install_property (object_class,
164                                          PROP_SUBSCRIPTION,
165                                          g_param_spec_int ("subscription",
166                                                            "Contact Subscription",
167                                                            "The subscription status of the contact",
168                                                            GOSSIP_SUBSCRIPTION_NONE,
169                                                            GOSSIP_SUBSCRIPTION_BOTH,
170                                                            GOSSIP_SUBSCRIPTION_NONE,
171                                                            G_PARAM_READWRITE));
172
173
174         g_object_class_install_property (object_class,
175                                          PROP_HANDLE,
176                                          g_param_spec_uint ("handle",
177                                                             "Contact Handle",
178                                                             "The handle of the contact",
179                                                             0,
180                                                             G_MAXUINT,
181                                                             0,
182                                                             G_PARAM_READWRITE));
183
184         g_type_class_add_private (object_class, sizeof (GossipContactPriv));
185 }
186
187 static void
188 contact_init (GossipContact *contact)
189 {
190         GossipContactPriv *priv;
191
192         priv = GET_PRIV (contact);
193
194         priv->id       = NULL;
195         priv->name     = NULL;
196         priv->avatar   = NULL;
197         priv->account  = NULL;
198         priv->presence = NULL;
199         priv->groups   = NULL;
200         priv->handle   = 0;
201 }
202
203 static void
204 contact_finalize (GObject *object)
205 {
206         GossipContactPriv *priv;
207
208         priv = GET_PRIV (object);
209
210         gossip_debug (DEBUG_DOMAIN, "finalize: %p", object);
211
212         g_free (priv->name);
213         g_free (priv->id);
214
215         if (priv->avatar) {
216                 gossip_avatar_unref (priv->avatar);
217         }
218
219         if (priv->presence) {
220                 g_object_unref (priv->presence);
221         }
222
223         if (priv->groups) {
224                 g_list_foreach (priv->groups, (GFunc) g_free, NULL);
225                 g_list_free (priv->groups);
226         }
227
228         if (priv->account) {
229                 g_object_unref (priv->account);
230         }
231
232         (G_OBJECT_CLASS (parent_class)->finalize) (object);
233 }
234
235 static void
236 contact_get_property (GObject    *object,
237                       guint       param_id,
238                       GValue     *value,
239                       GParamSpec *pspec)
240 {
241         GossipContactPriv *priv;
242
243         priv = GET_PRIV (object);
244
245         switch (param_id) {
246         case PROP_ID:
247                 g_value_set_string (value,
248                                     gossip_contact_get_id (GOSSIP_CONTACT (object)));
249                 break;
250         case PROP_NAME:
251                 g_value_set_string (value,
252                                     gossip_contact_get_name (GOSSIP_CONTACT (object)));
253                 break;
254         case PROP_AVATAR:
255                 g_value_set_boxed (value, priv->avatar);
256                 break;
257         case PROP_ACCOUNT:
258                 g_value_set_object (value, priv->account);
259                 break;
260         case PROP_PRESENCE:
261                 g_value_set_object (value, priv->presence);
262                 break;
263         case PROP_GROUPS:
264                 g_value_set_pointer (value, priv->groups);
265                 break;
266         case PROP_SUBSCRIPTION:
267                 g_value_set_int (value, priv->subscription);
268                 break;
269         case PROP_HANDLE:
270                 g_value_set_uint (value, priv->handle);
271                 break;
272         default:
273                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
274                 break;
275         };
276 }
277
278 static void
279 contact_set_property (GObject      *object,
280                       guint         param_id,
281                       const GValue *value,
282                       GParamSpec   *pspec)
283 {
284         GossipContactPriv *priv;
285
286         priv = GET_PRIV (object);
287
288         switch (param_id) {
289         case PROP_ID:
290                 gossip_contact_set_id (GOSSIP_CONTACT (object),
291                                        g_value_get_string (value));
292                 break;
293         case PROP_NAME:
294                 gossip_contact_set_name (GOSSIP_CONTACT (object),
295                                          g_value_get_string (value));
296                 break;
297         case PROP_AVATAR:
298                 gossip_contact_set_avatar (GOSSIP_CONTACT (object),
299                                            g_value_get_boxed (value));
300                 break;
301         case PROP_ACCOUNT:
302                 gossip_contact_set_account (GOSSIP_CONTACT (object),
303                                             MC_ACCOUNT (g_value_get_object (value)));
304                 break;
305         case PROP_PRESENCE:
306                 gossip_contact_set_presence (GOSSIP_CONTACT (object),
307                                              GOSSIP_PRESENCE (g_value_get_object (value)));
308                 break;
309         case PROP_GROUPS:
310                 gossip_contact_set_groups (GOSSIP_CONTACT (object),
311                                            g_value_get_pointer (value));
312                 break;
313         case PROP_SUBSCRIPTION:
314                 gossip_contact_set_subscription (GOSSIP_CONTACT (object),
315                                                  g_value_get_int (value));
316                 break;
317         case PROP_HANDLE:
318                 gossip_contact_set_handle (GOSSIP_CONTACT (object),
319                                            g_value_get_uint (value));
320                 break;
321         default:
322                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
323                 break;
324         };
325 }
326
327 GossipContact *
328 gossip_contact_new (McAccount *account)
329 {
330         return g_object_new (GOSSIP_TYPE_CONTACT,
331                              "account", account,
332                              NULL);
333 }
334
335 GossipContact *
336 gossip_contact_new_full (McAccount *account,
337                          const gchar   *id,
338                          const gchar   *name)
339 {
340         return g_object_new (GOSSIP_TYPE_CONTACT,
341                              "account", account,
342                              "name", name,
343                              "id", id,
344                              NULL);
345 }
346
347 const gchar *
348 gossip_contact_get_id (GossipContact *contact)
349 {
350         GossipContactPriv *priv;
351
352         g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), "");
353
354         priv = GET_PRIV (contact);
355
356         if (priv->id) {
357                 return priv->id;
358         }
359
360         return "";
361 }
362
363 const gchar *
364 gossip_contact_get_name (GossipContact *contact)
365 {
366         GossipContactPriv *priv;
367
368         g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), "");
369
370         priv = GET_PRIV (contact);
371
372         if (priv->name == NULL) {
373                 return gossip_contact_get_id (contact);
374         }
375
376         return priv->name;
377 }
378
379 GossipAvatar *
380 gossip_contact_get_avatar (GossipContact *contact)
381 {
382         GossipContactPriv *priv;
383
384         g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), NULL);
385
386         priv = GET_PRIV (contact);
387
388         return priv->avatar;
389 }
390
391 McAccount *
392 gossip_contact_get_account (GossipContact *contact)
393 {
394         GossipContactPriv *priv;
395
396         g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), NULL);
397
398         priv = GET_PRIV (contact);
399
400         return priv->account;
401 }
402
403 GossipPresence *
404 gossip_contact_get_presence (GossipContact *contact)
405 {
406         GossipContactPriv *priv;
407
408         g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), NULL);
409
410         priv = GET_PRIV (contact);
411
412         return priv->presence;
413 }
414
415 GList *
416 gossip_contact_get_groups (GossipContact *contact)
417 {
418         GossipContactPriv *priv;
419
420         g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), NULL);
421
422         priv = GET_PRIV (contact);
423
424         return priv->groups;
425 }
426
427 GossipSubscription
428 gossip_contact_get_subscription (GossipContact *contact)
429 {
430         GossipContactPriv *priv;
431
432         g_return_val_if_fail (GOSSIP_IS_CONTACT (contact),
433                               GOSSIP_SUBSCRIPTION_NONE);
434
435         priv = GET_PRIV (contact);
436
437         return priv->subscription;
438 }
439
440 guint
441 gossip_contact_get_handle (GossipContact *contact)
442 {
443         GossipContactPriv *priv;
444
445         g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), 0);
446
447         priv = GET_PRIV (contact);
448
449         return priv->handle;
450 }
451
452 void
453 gossip_contact_set_id (GossipContact *contact,
454                        const gchar   *id)
455 {
456         GossipContactPriv *priv;
457
458         g_return_if_fail (GOSSIP_IS_CONTACT (contact));
459         g_return_if_fail (id != NULL);
460
461         priv = GET_PRIV (contact);
462
463         g_free (priv->id);
464         priv->id = g_strdup (id);
465
466         g_object_notify (G_OBJECT (contact), "id");
467 }
468
469 void
470 gossip_contact_set_name (GossipContact *contact,
471                          const gchar   *name)
472 {
473         GossipContactPriv *priv;
474
475         g_return_if_fail (GOSSIP_IS_CONTACT (contact));
476         g_return_if_fail (name != NULL);
477
478         priv = GET_PRIV (contact);
479
480         g_free (priv->name);
481         priv->name = g_strdup (name);
482
483         g_object_notify (G_OBJECT (contact), "name");
484 }
485
486 void
487 gossip_contact_set_avatar (GossipContact *contact,
488                            GossipAvatar  *avatar)
489 {
490         GossipContactPriv *priv;
491
492         g_return_if_fail (GOSSIP_IS_CONTACT (contact));
493
494         priv = GET_PRIV (contact);
495
496         if (priv->avatar) {
497                 gossip_avatar_unref (priv->avatar);
498                 priv->avatar = NULL;
499         }
500
501         if (avatar) {
502                 priv->avatar = gossip_avatar_ref (avatar);
503         }
504
505         g_object_notify (G_OBJECT (contact), "avatar");
506 }
507
508 void
509 gossip_contact_set_account (GossipContact *contact,
510                             McAccount     *account)
511 {
512         GossipContactPriv *priv;
513
514         g_return_if_fail (GOSSIP_IS_CONTACT (contact));
515         g_return_if_fail (MC_IS_ACCOUNT (account));
516
517         priv = GET_PRIV (contact);
518
519         if (priv->account) {
520                 g_object_unref (priv->account);
521         }
522         priv->account = g_object_ref (account);
523
524         g_object_notify (G_OBJECT (contact), "account");
525 }
526
527 void
528 gossip_contact_set_presence (GossipContact  *contact,
529                              GossipPresence *presence)
530 {
531         GossipContactPriv *priv;
532
533         g_return_if_fail (GOSSIP_IS_CONTACT (contact));
534
535         priv = GET_PRIV (contact);
536
537         if (priv->presence) {
538                 g_object_unref (priv->presence);
539                 priv->presence = NULL;
540         }
541
542         if (presence) {
543                 priv->presence = g_object_ref (presence);
544         }
545
546         g_object_notify (G_OBJECT (contact), "presence");
547 }
548
549 void
550 gossip_contact_set_groups (GossipContact *contact,
551                            GList         *groups)
552 {
553         GossipContactPriv *priv;
554         GList             *old_groups, *l;
555
556         g_return_if_fail (GOSSIP_IS_CONTACT (contact));
557
558         priv = GET_PRIV (contact);
559
560         old_groups = priv->groups;
561         priv->groups = NULL;
562
563         for (l = groups; l; l = l->next) {
564                 priv->groups = g_list_append (priv->groups,
565                                               g_strdup (l->data));
566         }
567
568         g_list_foreach (old_groups, (GFunc) g_free, NULL);
569         g_list_free (old_groups);
570
571         g_object_notify (G_OBJECT (contact), "groups");
572 }
573
574 void
575 gossip_contact_set_subscription (GossipContact      *contact,
576                                  GossipSubscription  subscription)
577 {
578         GossipContactPriv *priv;
579
580         g_return_if_fail (GOSSIP_IS_CONTACT (contact));
581
582         priv = GET_PRIV (contact);
583
584         priv->subscription = subscription;
585
586         g_object_notify (G_OBJECT (contact), "subscription");
587 }
588
589 void
590 gossip_contact_set_handle (GossipContact *contact,
591                            guint          handle)
592 {
593         GossipContactPriv *priv;
594
595         priv = GET_PRIV (contact);
596
597         priv->handle = handle;
598
599         g_object_notify (G_OBJECT (contact), "handle");
600 }
601
602 gboolean
603 gossip_contact_is_online (GossipContact *contact)
604 {
605         GossipContactPriv *priv;
606
607         g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), FALSE);
608
609         priv = GET_PRIV (contact);
610
611         return (priv->presence != NULL);
612 }
613
614 gboolean
615 gossip_contact_is_in_group (GossipContact *contact,
616                             const gchar   *group)
617 {
618         GossipContactPriv *priv;
619
620         g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), FALSE);
621         g_return_val_if_fail (!G_STR_EMPTY (group), FALSE);
622
623         priv = GET_PRIV (contact);
624
625         if (g_list_find_custom (priv->groups, group, (GCompareFunc) strcmp)) {
626                 return TRUE;
627         }
628
629         return FALSE;
630 }
631
632 const gchar *
633 gossip_contact_get_status (GossipContact *contact)
634 {
635         GossipContactPriv *priv;
636
637         g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), "");
638
639         priv = GET_PRIV (contact);
640
641         if (priv->presence) {
642                 const gchar *status;
643
644                 status = gossip_presence_get_status (priv->presence);
645                 if (!status) {
646                         McPresence state;
647
648                         state = gossip_presence_get_state (priv->presence);
649                         status = gossip_presence_state_get_default_status (state);
650                 }
651
652                 return status;
653         }
654
655         return _("Offline");
656 }
657
658 GossipContact *
659 gossip_contact_get_user (GossipContact *contact)
660 {
661         GossipContactPriv     *priv;
662         EmpathyContactManager *manager;
663         GossipContact         *user_contact;
664
665         g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), NULL);
666
667         priv = GET_PRIV (contact);
668
669         manager = empathy_contact_manager_new ();
670         user_contact = empathy_contact_manager_get_user (manager, priv->account);
671         g_object_unref (manager);
672
673         return user_contact;
674 }
675
676 gboolean
677 gossip_contact_equal (gconstpointer v1,
678                       gconstpointer v2)
679 {
680         McAccount   *account_a;
681         McAccount   *account_b;
682         const gchar *id_a;
683         const gchar *id_b;
684
685         g_return_val_if_fail (GOSSIP_IS_CONTACT (v1), FALSE);
686         g_return_val_if_fail (GOSSIP_IS_CONTACT (v2), FALSE);
687
688         account_a = gossip_contact_get_account (GOSSIP_CONTACT (v1));
689         account_b = gossip_contact_get_account (GOSSIP_CONTACT (v2));
690
691         id_a = gossip_contact_get_id (GOSSIP_CONTACT (v1));
692         id_b = gossip_contact_get_id (GOSSIP_CONTACT (v2));
693
694         return gossip_account_equal (account_a, account_b) && g_str_equal (id_a, id_b);
695 }
696
697 guint
698 gossip_contact_hash (gconstpointer key)
699 {
700         GossipContactPriv *priv;
701         guint              hash;
702
703         g_return_val_if_fail (GOSSIP_IS_CONTACT (key), +1);
704
705         priv = GET_PRIV (GOSSIP_CONTACT (key));
706
707         hash = gossip_account_hash (gossip_contact_get_account (GOSSIP_CONTACT (key)));
708         hash += g_str_hash (gossip_contact_get_id (GOSSIP_CONTACT (key)));
709
710         return hash;
711 }
712