]> git.0d.be Git - empathy.git/blob - libempathy/empathy-contact.c
Remove empathy-marshal-main.c and include empathy-marshal.h from
[empathy.git] / libempathy / empathy-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 "empathy-contact.h"
31 #include "empathy-utils.h"
32 #include "empathy-debug.h"
33 #include "empathy-enum-types.h"
34
35 #define DEBUG_DOMAIN "Contact"
36
37 #define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EMPATHY_TYPE_CONTACT, EmpathyContactPriv))
38
39 typedef struct _EmpathyContactPriv EmpathyContactPriv;
40
41 struct _EmpathyContactPriv {
42         gchar              *id;
43         gchar              *name;
44         EmpathyAvatar       *avatar;
45         McAccount          *account;
46         EmpathyPresence     *presence;
47         GList              *groups;
48         EmpathySubscription  subscription;
49         guint               handle;
50         gboolean            is_user;
51 };
52
53 static void contact_class_init    (EmpathyContactClass *class);
54 static void contact_init          (EmpathyContact      *contact);
55 static void contact_finalize      (GObject            *object);
56 static void contact_get_property  (GObject            *object,
57                                    guint               param_id,
58                                    GValue             *value,
59                                    GParamSpec         *pspec);
60 static void contact_set_property  (GObject            *object,
61                                    guint               param_id,
62                                    const GValue       *value,
63                                    GParamSpec         *pspec);
64
65 enum {
66         PROP_0,
67         PROP_ID,
68         PROP_NAME,
69         PROP_AVATAR,
70         PROP_ACCOUNT,
71         PROP_PRESENCE,
72         PROP_GROUPS,
73         PROP_SUBSCRIPTION,
74         PROP_HANDLE,
75         PROP_IS_USER
76 };
77
78 static gpointer parent_class = NULL;
79
80 GType
81 empathy_contact_get_gtype (void)
82 {
83         static GType type = 0;
84
85         if (!type) {
86                 static const GTypeInfo info = {
87                         sizeof (EmpathyContactClass),
88                         NULL, /* base_init */
89                         NULL, /* base_finalize */
90                         (GClassInitFunc) contact_class_init,
91                         NULL, /* class_finalize */
92                         NULL, /* class_data */
93                         sizeof (EmpathyContact),
94                         0,    /* n_preallocs */
95                         (GInstanceInitFunc) contact_init
96                 };
97
98                 type = g_type_register_static (G_TYPE_OBJECT,
99                                                "EmpathyContact",
100                                                &info, 0);
101         }
102
103         return type;
104 }
105
106 static void
107 contact_class_init (EmpathyContactClass *class)
108 {
109         GObjectClass *object_class;
110
111         object_class = G_OBJECT_CLASS (class);
112         parent_class = g_type_class_peek_parent (class);
113
114         object_class->finalize     = contact_finalize;
115         object_class->get_property = contact_get_property;
116         object_class->set_property = contact_set_property;
117
118         g_object_class_install_property (object_class,
119                                          PROP_ID,
120                                          g_param_spec_string ("id",
121                                                               "Contact id",
122                                                               "String identifying contact",
123                                                               NULL,
124                                                               G_PARAM_READWRITE));
125
126         g_object_class_install_property (object_class,
127                                          PROP_NAME,
128                                          g_param_spec_string ("name",
129                                                               "Contact Name",
130                                                               "The name of the contact",
131                                                               NULL,
132                                                               G_PARAM_READWRITE));
133
134         g_object_class_install_property (object_class,
135                                          PROP_AVATAR,
136                                          g_param_spec_boxed ("avatar",
137                                                              "Avatar image",
138                                                              "The avatar image",
139                                                              EMPATHY_TYPE_AVATAR,
140                                                              G_PARAM_READWRITE));
141
142         g_object_class_install_property (object_class,
143                                          PROP_ACCOUNT,
144                                          g_param_spec_object ("account",
145                                                               "Contact Account",
146                                                               "The account associated with the contact",
147                                                               MC_TYPE_ACCOUNT,
148                                                               G_PARAM_READWRITE));
149
150         g_object_class_install_property (object_class,
151                                          PROP_PRESENCE,
152                                          g_param_spec_object ("presence",
153                                                               "Contact presence",
154                                                               "Presence of contact",
155                                                               EMPATHY_TYPE_PRESENCE,
156                                                               G_PARAM_READWRITE));
157
158         g_object_class_install_property (object_class,
159                                          PROP_GROUPS,
160                                          g_param_spec_pointer ("groups",
161                                                                "Contact groups",
162                                                                "Groups of contact",
163                                                                G_PARAM_READWRITE));
164
165         g_object_class_install_property (object_class,
166                                          PROP_SUBSCRIPTION,
167                                          g_param_spec_flags ("subscription",
168                                                              "Contact Subscription",
169                                                              "The subscription status of the contact",
170                                                              EMPATHY_TYPE_SUBSCRIPTION,
171                                                              EMPATHY_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 (EmpathyContactPriv));
193 }
194
195 static void
196 contact_init (EmpathyContact *contact)
197 {
198 }
199
200 static void
201 contact_finalize (GObject *object)
202 {
203         EmpathyContactPriv *priv;
204
205         priv = GET_PRIV (object);
206
207         empathy_debug (DEBUG_DOMAIN, "finalize: %p", object);
208
209         g_free (priv->name);
210         g_free (priv->id);
211
212         if (priv->avatar) {
213                 empathy_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         EmpathyContactPriv *priv;
239
240         priv = GET_PRIV (object);
241
242         switch (param_id) {
243         case PROP_ID:
244                 g_value_set_string (value,
245                                     empathy_contact_get_id (EMPATHY_CONTACT (object)));
246                 break;
247         case PROP_NAME:
248                 g_value_set_string (value,
249                                     empathy_contact_get_name (EMPATHY_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_flags (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         EmpathyContactPriv *priv;
285
286         priv = GET_PRIV (object);
287
288         switch (param_id) {
289         case PROP_ID:
290                 empathy_contact_set_id (EMPATHY_CONTACT (object),
291                                        g_value_get_string (value));
292                 break;
293         case PROP_NAME:
294                 empathy_contact_set_name (EMPATHY_CONTACT (object),
295                                          g_value_get_string (value));
296                 break;
297         case PROP_AVATAR:
298                 empathy_contact_set_avatar (EMPATHY_CONTACT (object),
299                                            g_value_get_boxed (value));
300                 break;
301         case PROP_ACCOUNT:
302                 empathy_contact_set_account (EMPATHY_CONTACT (object),
303                                             MC_ACCOUNT (g_value_get_object (value)));
304                 break;
305         case PROP_PRESENCE:
306                 empathy_contact_set_presence (EMPATHY_CONTACT (object),
307                                              EMPATHY_PRESENCE (g_value_get_object (value)));
308                 break;
309         case PROP_GROUPS:
310                 empathy_contact_set_groups (EMPATHY_CONTACT (object),
311                                            g_value_get_pointer (value));
312                 break;
313         case PROP_SUBSCRIPTION:
314                 empathy_contact_set_subscription (EMPATHY_CONTACT (object),
315                                                   g_value_get_flags (value));
316                 break;
317         case PROP_HANDLE:
318                 empathy_contact_set_handle (EMPATHY_CONTACT (object),
319                                            g_value_get_uint (value));
320                 break;
321         case PROP_IS_USER:
322                 empathy_contact_set_is_user (EMPATHY_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 EmpathyContact *
332 empathy_contact_new (McAccount *account)
333 {
334         return g_object_new (EMPATHY_TYPE_CONTACT,
335                              "account", account,
336                              NULL);
337 }
338
339 EmpathyContact *
340 empathy_contact_new_full (McAccount   *account,
341                          const gchar *id,
342                          const gchar *name)
343 {
344         return g_object_new (EMPATHY_TYPE_CONTACT,
345                              "account", account,
346                              "name", name,
347                              "id", id,
348                              NULL);
349 }
350
351 const gchar *
352 empathy_contact_get_id (EmpathyContact *contact)
353 {
354         EmpathyContactPriv *priv;
355
356         g_return_val_if_fail (EMPATHY_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 empathy_contact_get_name (EmpathyContact *contact)
369 {
370         EmpathyContactPriv *priv;
371
372         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), "");
373
374         priv = GET_PRIV (contact);
375
376         if (G_STR_EMPTY (priv->name)) {
377                 return empathy_contact_get_id (contact);
378         }
379
380         return priv->name;
381 }
382
383 EmpathyAvatar *
384 empathy_contact_get_avatar (EmpathyContact *contact)
385 {
386         EmpathyContactPriv *priv;
387
388         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
389
390         priv = GET_PRIV (contact);
391
392         return priv->avatar;
393 }
394
395 McAccount *
396 empathy_contact_get_account (EmpathyContact *contact)
397 {
398         EmpathyContactPriv *priv;
399
400         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
401
402         priv = GET_PRIV (contact);
403
404         return priv->account;
405 }
406
407 EmpathyPresence *
408 empathy_contact_get_presence (EmpathyContact *contact)
409 {
410         EmpathyContactPriv *priv;
411
412         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
413
414         priv = GET_PRIV (contact);
415
416         return priv->presence;
417 }
418
419 GList *
420 empathy_contact_get_groups (EmpathyContact *contact)
421 {
422         EmpathyContactPriv *priv;
423
424         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
425
426         priv = GET_PRIV (contact);
427
428         return priv->groups;
429 }
430
431 EmpathySubscription
432 empathy_contact_get_subscription (EmpathyContact *contact)
433 {
434         EmpathyContactPriv *priv;
435
436         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact),
437                               EMPATHY_SUBSCRIPTION_NONE);
438
439         priv = GET_PRIV (contact);
440
441         return priv->subscription;
442 }
443
444 guint
445 empathy_contact_get_handle (EmpathyContact *contact)
446 {
447         EmpathyContactPriv *priv;
448
449         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), 0);
450
451         priv = GET_PRIV (contact);
452
453         return priv->handle;
454 }
455
456 gboolean
457 empathy_contact_is_user (EmpathyContact *contact)
458 {
459         EmpathyContactPriv *priv;
460
461         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), FALSE);
462
463         priv = GET_PRIV (contact);
464
465         return priv->is_user;
466 }
467
468 void
469 empathy_contact_set_id (EmpathyContact *contact,
470                        const gchar   *id)
471 {
472         EmpathyContactPriv *priv;
473
474         g_return_if_fail (EMPATHY_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 empathy_contact_set_name (EmpathyContact *contact,
491                          const gchar   *name)
492 {
493         EmpathyContactPriv *priv;
494
495         g_return_if_fail (EMPATHY_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 empathy_contact_set_avatar (EmpathyContact *contact,
512                            EmpathyAvatar  *avatar)
513 {
514         EmpathyContactPriv *priv;
515
516         g_return_if_fail (EMPATHY_IS_CONTACT (contact));
517
518         priv = GET_PRIV (contact);
519
520         if (priv->avatar == avatar) {
521                 return;
522         }
523
524         if (priv->avatar) {
525                 empathy_avatar_unref (priv->avatar);
526                 priv->avatar = NULL;
527         }
528
529         if (avatar) {
530                 priv->avatar = empathy_avatar_ref (avatar);
531         }
532
533         g_object_notify (G_OBJECT (contact), "avatar");
534 }
535
536 void
537 empathy_contact_set_account (EmpathyContact *contact,
538                             McAccount     *account)
539 {
540         EmpathyContactPriv *priv;
541
542         g_return_if_fail (EMPATHY_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 empathy_contact_set_presence (EmpathyContact  *contact,
561                              EmpathyPresence *presence)
562 {
563         EmpathyContactPriv *priv;
564
565         g_return_if_fail (EMPATHY_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 empathy_contact_set_groups (EmpathyContact *contact,
587                            GList         *groups)
588 {
589         EmpathyContactPriv *priv;
590         GList             *old_groups, *l;
591
592         g_return_if_fail (EMPATHY_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 empathy_contact_set_subscription (EmpathyContact      *contact,
612                                  EmpathySubscription  subscription)
613 {
614         EmpathyContactPriv *priv;
615
616         g_return_if_fail (EMPATHY_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 empathy_contact_set_handle (EmpathyContact *contact,
631                            guint          handle)
632 {
633         EmpathyContactPriv *priv;
634
635         g_return_if_fail (EMPATHY_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 empathy_contact_set_is_user (EmpathyContact *contact,
650                             gboolean       is_user)
651 {
652         EmpathyContactPriv *priv;
653
654         g_return_if_fail (EMPATHY_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 empathy_contact_add_group (EmpathyContact *contact,
669                           const gchar   *group)
670 {
671         EmpathyContactPriv *priv;
672
673         g_return_if_fail (EMPATHY_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 empathy_contact_remove_group (EmpathyContact *contact,
686                              const gchar   *group)
687 {
688         EmpathyContactPriv *priv;
689         GList             *l;
690
691         g_return_if_fail (EMPATHY_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 empathy_contact_is_online (EmpathyContact *contact)
706 {
707         EmpathyContactPriv *priv;
708
709         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), FALSE);
710
711         priv = GET_PRIV (contact);
712
713         if (!priv->presence) {
714                 return FALSE;
715         }
716
717         return (empathy_presence_get_state (priv->presence) > MC_PRESENCE_OFFLINE);
718 }
719
720 gboolean
721 empathy_contact_is_in_group (EmpathyContact *contact,
722                             const gchar   *group)
723 {
724         EmpathyContactPriv *priv;
725
726         g_return_val_if_fail (EMPATHY_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 empathy_contact_get_status (EmpathyContact *contact)
740 {
741         EmpathyContactPriv *priv;
742
743         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), "");
744
745         priv = GET_PRIV (contact);
746
747         if (priv->presence) {
748                 const gchar *status;
749
750                 status = empathy_presence_get_status (priv->presence);
751                 if (!status) {
752                         McPresence state;
753
754                         state = empathy_presence_get_state (priv->presence);
755                         status = empathy_presence_state_get_default_status (state);
756                 }
757
758                 return status;
759         }
760
761         return empathy_presence_state_get_default_status (MC_PRESENCE_OFFLINE);
762 }
763
764 gboolean
765 empathy_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 (EMPATHY_IS_CONTACT (v1), FALSE);
774         g_return_val_if_fail (EMPATHY_IS_CONTACT (v2), FALSE);
775
776         account_a = empathy_contact_get_account (EMPATHY_CONTACT (v1));
777         account_b = empathy_contact_get_account (EMPATHY_CONTACT (v2));
778
779         id_a = empathy_contact_get_id (EMPATHY_CONTACT (v1));
780         id_b = empathy_contact_get_id (EMPATHY_CONTACT (v2));
781
782         return empathy_account_equal (account_a, account_b) && g_str_equal (id_a, id_b);
783 }
784
785 guint
786 empathy_contact_hash (gconstpointer key)
787 {
788         EmpathyContactPriv *priv;
789         guint              hash;
790
791         g_return_val_if_fail (EMPATHY_IS_CONTACT (key), +1);
792
793         priv = GET_PRIV (EMPATHY_CONTACT (key));
794
795         hash = empathy_account_hash (empathy_contact_get_account (EMPATHY_CONTACT (key)));
796         hash += g_str_hash (empathy_contact_get_id (EMPATHY_CONTACT (key)));
797
798         return hash;
799 }
800