]> git.0d.be Git - empathy.git/blob - libempathy/gossip-contact.c
sv.po: Updated Swedish translation
[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
34 #define DEBUG_DOMAIN "Contact"
35
36 #define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GOSSIP_TYPE_CONTACT, GossipContactPriv))
37
38 typedef struct _GossipContactPriv GossipContactPriv;
39
40 struct _GossipContactPriv {
41         gchar              *id;
42         gchar              *name;
43         GossipAvatar       *avatar;
44         McAccount          *account;
45         GossipPresence     *presence;
46         GList              *groups;
47         GossipSubscription  subscription;
48         guint               handle;
49         gboolean            is_user;
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         PROP_IS_USER
75 };
76
77 static gpointer parent_class = NULL;
78
79 GType
80 gossip_contact_get_gtype (void)
81 {
82         static GType type = 0;
83
84         if (!type) {
85                 static const GTypeInfo info = {
86                         sizeof (GossipContactClass),
87                         NULL, /* base_init */
88                         NULL, /* base_finalize */
89                         (GClassInitFunc) contact_class_init,
90                         NULL, /* class_finalize */
91                         NULL, /* class_data */
92                         sizeof (GossipContact),
93                         0,    /* n_preallocs */
94                         (GInstanceInitFunc) contact_init
95                 };
96
97                 type = g_type_register_static (G_TYPE_OBJECT,
98                                                "GossipContact",
99                                                &info, 0);
100         }
101
102         return type;
103 }
104
105 static void
106 contact_class_init (GossipContactClass *class)
107 {
108         GObjectClass *object_class;
109
110         object_class = G_OBJECT_CLASS (class);
111         parent_class = g_type_class_peek_parent (class);
112
113         object_class->finalize     = contact_finalize;
114         object_class->get_property = contact_get_property;
115         object_class->set_property = contact_set_property;
116
117         g_object_class_install_property (object_class,
118                                          PROP_ID,
119                                          g_param_spec_string ("id",
120                                                               "Contact id",
121                                                               "String identifying contact",
122                                                               NULL,
123                                                               G_PARAM_READWRITE));
124
125         g_object_class_install_property (object_class,
126                                          PROP_NAME,
127                                          g_param_spec_string ("name",
128                                                               "Contact Name",
129                                                               "The name of the contact",
130                                                               NULL,
131                                                               G_PARAM_READWRITE));
132
133         g_object_class_install_property (object_class,
134                                          PROP_AVATAR,
135                                          g_param_spec_boxed ("avatar",
136                                                              "Avatar image",
137                                                              "The avatar image",
138                                                              GOSSIP_TYPE_AVATAR,
139                                                              G_PARAM_READWRITE));
140
141         g_object_class_install_property (object_class,
142                                          PROP_ACCOUNT,
143                                          g_param_spec_object ("account",
144                                                               "Contact Account",
145                                                               "The account associated with the contact",
146                                                               MC_TYPE_ACCOUNT,
147                                                               G_PARAM_READWRITE));
148
149         g_object_class_install_property (object_class,
150                                          PROP_PRESENCE,
151                                          g_param_spec_object ("presence",
152                                                               "Contact presence",
153                                                               "Presence of contact",
154                                                               GOSSIP_TYPE_PRESENCE,
155                                                               G_PARAM_READWRITE));
156
157         g_object_class_install_property (object_class,
158                                          PROP_GROUPS,
159                                          g_param_spec_pointer ("groups",
160                                                                "Contact groups",
161                                                                "Groups of contact",
162                                                                G_PARAM_READWRITE));
163
164         g_object_class_install_property (object_class,
165                                          PROP_SUBSCRIPTION,
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,
172                                                            G_PARAM_READWRITE));
173
174
175         g_object_class_install_property (object_class,
176                                          PROP_HANDLE,
177                                          g_param_spec_uint ("handle",
178                                                             "Contact Handle",
179                                                             "The handle of the contact",
180                                                             0,
181                                                             G_MAXUINT,
182                                                             0,
183                                                             G_PARAM_READWRITE));
184         g_object_class_install_property (object_class,
185                                          PROP_IS_USER,
186                                          g_param_spec_boolean ("is-user",
187                                                                "Contact is-user",
188                                                                "Is contact the user",
189                                                                FALSE,
190                                                                G_PARAM_READWRITE));
191
192         g_type_class_add_private (object_class, sizeof (GossipContactPriv));
193 }
194
195 static void
196 contact_init (GossipContact *contact)
197 {
198 }
199
200 static void
201 contact_finalize (GObject *object)
202 {
203         GossipContactPriv *priv;
204
205         priv = GET_PRIV (object);
206
207         gossip_debug (DEBUG_DOMAIN, "finalize: %p", object);
208
209         g_free (priv->name);
210         g_free (priv->id);
211
212         if (priv->avatar) {
213                 gossip_avatar_unref (priv->avatar);
214         }
215
216         if (priv->presence) {
217                 g_object_unref (priv->presence);
218         }
219
220         if (priv->groups) {
221                 g_list_foreach (priv->groups, (GFunc) g_free, NULL);
222                 g_list_free (priv->groups);
223         }
224
225         if (priv->account) {
226                 g_object_unref (priv->account);
227         }
228
229         (G_OBJECT_CLASS (parent_class)->finalize) (object);
230 }
231
232 static void
233 contact_get_property (GObject    *object,
234                       guint       param_id,
235                       GValue     *value,
236                       GParamSpec *pspec)
237 {
238         GossipContactPriv *priv;
239
240         priv = GET_PRIV (object);
241
242         switch (param_id) {
243         case PROP_ID:
244                 g_value_set_string (value,
245                                     gossip_contact_get_id (GOSSIP_CONTACT (object)));
246                 break;
247         case PROP_NAME:
248                 g_value_set_string (value,
249                                     gossip_contact_get_name (GOSSIP_CONTACT (object)));
250                 break;
251         case PROP_AVATAR:
252                 g_value_set_boxed (value, priv->avatar);
253                 break;
254         case PROP_ACCOUNT:
255                 g_value_set_object (value, priv->account);
256                 break;
257         case PROP_PRESENCE:
258                 g_value_set_object (value, priv->presence);
259                 break;
260         case PROP_GROUPS:
261                 g_value_set_pointer (value, priv->groups);
262                 break;
263         case PROP_SUBSCRIPTION:
264                 g_value_set_int (value, priv->subscription);
265                 break;
266         case PROP_HANDLE:
267                 g_value_set_uint (value, priv->handle);
268                 break;
269         case PROP_IS_USER:
270                 g_value_set_boolean (value, priv->is_user);
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         case PROP_IS_USER:
322                 gossip_contact_set_is_user (GOSSIP_CONTACT (object),
323                                             g_value_get_boolean (value));
324                 break;
325         default:
326                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
327                 break;
328         };
329 }
330
331 GossipContact *
332 gossip_contact_new (McAccount *account)
333 {
334         return g_object_new (GOSSIP_TYPE_CONTACT,
335                              "account", account,
336                              NULL);
337 }
338
339 GossipContact *
340 gossip_contact_new_full (McAccount   *account,
341                          const gchar *id,
342                          const gchar *name)
343 {
344         return g_object_new (GOSSIP_TYPE_CONTACT,
345                              "account", account,
346                              "name", name,
347                              "id", id,
348                              NULL);
349 }
350
351 const gchar *
352 gossip_contact_get_id (GossipContact *contact)
353 {
354         GossipContactPriv *priv;
355
356         g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), "");
357
358         priv = GET_PRIV (contact);
359
360         if (priv->id) {
361                 return priv->id;
362         }
363
364         return "";
365 }
366
367 const gchar *
368 gossip_contact_get_name (GossipContact *contact)
369 {
370         GossipContactPriv *priv;
371
372         g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), "");
373
374         priv = GET_PRIV (contact);
375
376         if (G_STR_EMPTY (priv->name)) {
377                 return gossip_contact_get_id (contact);
378         }
379
380         return priv->name;
381 }
382
383 GossipAvatar *
384 gossip_contact_get_avatar (GossipContact *contact)
385 {
386         GossipContactPriv *priv;
387
388         g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), NULL);
389
390         priv = GET_PRIV (contact);
391
392         return priv->avatar;
393 }
394
395 McAccount *
396 gossip_contact_get_account (GossipContact *contact)
397 {
398         GossipContactPriv *priv;
399
400         g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), NULL);
401
402         priv = GET_PRIV (contact);
403
404         return priv->account;
405 }
406
407 GossipPresence *
408 gossip_contact_get_presence (GossipContact *contact)
409 {
410         GossipContactPriv *priv;
411
412         g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), NULL);
413
414         priv = GET_PRIV (contact);
415
416         return priv->presence;
417 }
418
419 GList *
420 gossip_contact_get_groups (GossipContact *contact)
421 {
422         GossipContactPriv *priv;
423
424         g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), NULL);
425
426         priv = GET_PRIV (contact);
427
428         return priv->groups;
429 }
430
431 GossipSubscription
432 gossip_contact_get_subscription (GossipContact *contact)
433 {
434         GossipContactPriv *priv;
435
436         g_return_val_if_fail (GOSSIP_IS_CONTACT (contact),
437                               GOSSIP_SUBSCRIPTION_NONE);
438
439         priv = GET_PRIV (contact);
440
441         return priv->subscription;
442 }
443
444 guint
445 gossip_contact_get_handle (GossipContact *contact)
446 {
447         GossipContactPriv *priv;
448
449         g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), 0);
450
451         priv = GET_PRIV (contact);
452
453         return priv->handle;
454 }
455
456 gboolean
457 gossip_contact_is_user (GossipContact *contact)
458 {
459         GossipContactPriv *priv;
460
461         g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), FALSE);
462
463         priv = GET_PRIV (contact);
464
465         return priv->is_user;
466 }
467
468 void
469 gossip_contact_set_id (GossipContact *contact,
470                        const gchar   *id)
471 {
472         GossipContactPriv *priv;
473
474         g_return_if_fail (GOSSIP_IS_CONTACT (contact));
475         g_return_if_fail (id != NULL);
476
477         priv = GET_PRIV (contact);
478
479         if (priv->id && strcmp (id, priv->id) == 0) {
480                 return;
481         }
482
483         g_free (priv->id);
484         priv->id = g_strdup (id);
485
486         g_object_notify (G_OBJECT (contact), "id");
487 }
488
489 void
490 gossip_contact_set_name (GossipContact *contact,
491                          const gchar   *name)
492 {
493         GossipContactPriv *priv;
494
495         g_return_if_fail (GOSSIP_IS_CONTACT (contact));
496         g_return_if_fail (name != NULL);
497
498         priv = GET_PRIV (contact);
499
500         if (priv->name && strcmp (name, priv->name) == 0) {
501                 return;
502         }
503
504         g_free (priv->name);
505         priv->name = g_strdup (name);
506
507         g_object_notify (G_OBJECT (contact), "name");
508 }
509
510 void
511 gossip_contact_set_avatar (GossipContact *contact,
512                            GossipAvatar  *avatar)
513 {
514         GossipContactPriv *priv;
515
516         g_return_if_fail (GOSSIP_IS_CONTACT (contact));
517
518         priv = GET_PRIV (contact);
519
520         if (priv->avatar == avatar) {
521                 return;
522         }
523
524         if (priv->avatar) {
525                 gossip_avatar_unref (priv->avatar);
526                 priv->avatar = NULL;
527         }
528
529         if (avatar) {
530                 priv->avatar = gossip_avatar_ref (avatar);
531         }
532
533         g_object_notify (G_OBJECT (contact), "avatar");
534 }
535
536 void
537 gossip_contact_set_account (GossipContact *contact,
538                             McAccount     *account)
539 {
540         GossipContactPriv *priv;
541
542         g_return_if_fail (GOSSIP_IS_CONTACT (contact));
543         g_return_if_fail (MC_IS_ACCOUNT (account));
544
545         priv = GET_PRIV (contact);
546
547         if (account == priv->account) {
548                 return;
549         }
550
551         if (priv->account) {
552                 g_object_unref (priv->account);
553         }
554         priv->account = g_object_ref (account);
555
556         g_object_notify (G_OBJECT (contact), "account");
557 }
558
559 void
560 gossip_contact_set_presence (GossipContact  *contact,
561                              GossipPresence *presence)
562 {
563         GossipContactPriv *priv;
564
565         g_return_if_fail (GOSSIP_IS_CONTACT (contact));
566
567         priv = GET_PRIV (contact);
568
569         if (presence == priv->presence) {
570                 return;
571         }
572
573         if (priv->presence) {
574                 g_object_unref (priv->presence);
575                 priv->presence = NULL;
576         }
577
578         if (presence) {
579                 priv->presence = g_object_ref (presence);
580         }
581
582         g_object_notify (G_OBJECT (contact), "presence");
583 }
584
585 void
586 gossip_contact_set_groups (GossipContact *contact,
587                            GList         *groups)
588 {
589         GossipContactPriv *priv;
590         GList             *old_groups, *l;
591
592         g_return_if_fail (GOSSIP_IS_CONTACT (contact));
593
594         priv = GET_PRIV (contact);
595
596         old_groups = priv->groups;
597         priv->groups = NULL;
598
599         for (l = groups; l; l = l->next) {
600                 priv->groups = g_list_append (priv->groups,
601                                               g_strdup (l->data));
602         }
603
604         g_list_foreach (old_groups, (GFunc) g_free, NULL);
605         g_list_free (old_groups);
606
607         g_object_notify (G_OBJECT (contact), "groups");
608 }
609
610 void
611 gossip_contact_set_subscription (GossipContact      *contact,
612                                  GossipSubscription  subscription)
613 {
614         GossipContactPriv *priv;
615
616         g_return_if_fail (GOSSIP_IS_CONTACT (contact));
617
618         priv = GET_PRIV (contact);
619
620         if (priv->subscription == subscription) {
621                 return;
622         }
623
624         priv->subscription = subscription;
625
626         g_object_notify (G_OBJECT (contact), "subscription");
627 }
628
629 void
630 gossip_contact_set_handle (GossipContact *contact,
631                            guint          handle)
632 {
633         GossipContactPriv *priv;
634
635         g_return_if_fail (GOSSIP_IS_CONTACT (contact));
636
637         priv = GET_PRIV (contact);
638
639         if (priv->handle == handle) {
640                 return;
641         }
642
643         priv->handle = handle;
644
645         g_object_notify (G_OBJECT (contact), "handle");
646 }
647
648 void
649 gossip_contact_set_is_user (GossipContact *contact,
650                             gboolean       is_user)
651 {
652         GossipContactPriv *priv;
653
654         g_return_if_fail (GOSSIP_IS_CONTACT (contact));
655
656         priv = GET_PRIV (contact);
657
658         if (priv->is_user == is_user) {
659                 return;
660         }
661
662         priv->is_user = is_user;
663
664         g_object_notify (G_OBJECT (contact), "is-user");
665 }
666
667 void
668 gossip_contact_add_group (GossipContact *contact,
669                           const gchar   *group)
670 {
671         GossipContactPriv *priv;
672
673         g_return_if_fail (GOSSIP_IS_CONTACT (contact));
674         g_return_if_fail (group != NULL);
675
676         priv = GET_PRIV (contact);
677
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");
681         }
682 }
683
684 void
685 gossip_contact_remove_group (GossipContact *contact,
686                              const gchar   *group)
687 {
688         GossipContactPriv *priv;
689         GList             *l;
690
691         g_return_if_fail (GOSSIP_IS_CONTACT (contact));
692         g_return_if_fail (group != NULL);
693
694         priv = GET_PRIV (contact);
695
696         l = g_list_find_custom (priv->groups, group, (GCompareFunc) strcmp);
697         if (l) {
698                 g_free (l->data);
699                 priv->groups = g_list_delete_link (priv->groups, l);
700                 g_object_notify (G_OBJECT (contact), "groups");
701         }
702 }
703
704 gboolean
705 gossip_contact_is_online (GossipContact *contact)
706 {
707         GossipContactPriv *priv;
708
709         g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), FALSE);
710
711         priv = GET_PRIV (contact);
712
713         if (!priv->presence) {
714                 return FALSE;
715         }
716
717         return (gossip_presence_get_state (priv->presence) > MC_PRESENCE_OFFLINE);
718 }
719
720 gboolean
721 gossip_contact_is_in_group (GossipContact *contact,
722                             const gchar   *group)
723 {
724         GossipContactPriv *priv;
725
726         g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), FALSE);
727         g_return_val_if_fail (!G_STR_EMPTY (group), FALSE);
728
729         priv = GET_PRIV (contact);
730
731         if (g_list_find_custom (priv->groups, group, (GCompareFunc) strcmp)) {
732                 return TRUE;
733         }
734
735         return FALSE;
736 }
737
738 const gchar *
739 gossip_contact_get_status (GossipContact *contact)
740 {
741         GossipContactPriv *priv;
742
743         g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), "");
744
745         priv = GET_PRIV (contact);
746
747         if (priv->presence) {
748                 const gchar *status;
749
750                 status = gossip_presence_get_status (priv->presence);
751                 if (!status) {
752                         McPresence state;
753
754                         state = gossip_presence_get_state (priv->presence);
755                         status = gossip_presence_state_get_default_status (state);
756                 }
757
758                 return status;
759         }
760
761         return gossip_presence_state_get_default_status (MC_PRESENCE_OFFLINE);
762 }
763
764 gboolean
765 gossip_contact_equal (gconstpointer v1,
766                       gconstpointer v2)
767 {
768         McAccount   *account_a;
769         McAccount   *account_b;
770         const gchar *id_a;
771         const gchar *id_b;
772
773         g_return_val_if_fail (GOSSIP_IS_CONTACT (v1), FALSE);
774         g_return_val_if_fail (GOSSIP_IS_CONTACT (v2), FALSE);
775
776         account_a = gossip_contact_get_account (GOSSIP_CONTACT (v1));
777         account_b = gossip_contact_get_account (GOSSIP_CONTACT (v2));
778
779         id_a = gossip_contact_get_id (GOSSIP_CONTACT (v1));
780         id_b = gossip_contact_get_id (GOSSIP_CONTACT (v2));
781
782         return gossip_account_equal (account_a, account_b) && g_str_equal (id_a, id_b);
783 }
784
785 guint
786 gossip_contact_hash (gconstpointer key)
787 {
788         GossipContactPriv *priv;
789         guint              hash;
790
791         g_return_val_if_fail (GOSSIP_IS_CONTACT (key), +1);
792
793         priv = GET_PRIV (GOSSIP_CONTACT (key));
794
795         hash = gossip_account_hash (gossip_contact_get_account (GOSSIP_CONTACT (key)));
796         hash += g_str_hash (gossip_contact_get_id (GOSSIP_CONTACT (key)));
797
798         return hash;
799 }
800