]> git.0d.be Git - empathy.git/blob - libempathy/empathy-contact.c
Merge commit 'sjoerd/master'
[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 Imendio AB
4  * Copyright (C) 2007 Collabora Ltd.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public
17  * License along with this program; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  *
21  * Authors: Mikael Hallendal <micke@imendio.com>
22  *          Martyn Russell <martyn@imendio.com>
23  *          Xavier Claessens <xclaesse@gmail.com>
24  */
25
26 #include "config.h"
27
28 #include <string.h>
29
30 #include <glib/gi18n.h>
31
32 #include <telepathy-glib/util.h>
33
34 #include "empathy-contact.h"
35 #include "empathy-utils.h"
36 #include "empathy-debug.h"
37 #include "empathy-enum-types.h"
38
39 #define DEBUG_DOMAIN "Contact"
40
41 #define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EMPATHY_TYPE_CONTACT, EmpathyContactPriv))
42
43 typedef struct _EmpathyContactPriv EmpathyContactPriv;
44
45 struct _EmpathyContactPriv {
46         gchar              *id;
47         gchar              *name;
48         EmpathyAvatar      *avatar;
49         McAccount          *account;
50         McPresence          presence;
51         gchar              *presence_message;
52         guint               handle;
53         EmpathyCapabilities capabilities;
54         gboolean            is_user;
55 };
56
57 static void empathy_contact_class_init (EmpathyContactClass *class);
58 static void empathy_contact_init       (EmpathyContact      *contact);
59 static void contact_finalize           (GObject             *object);
60 static void contact_get_property       (GObject             *object,
61                                         guint                param_id,
62                                         GValue              *value,
63                                         GParamSpec          *pspec);
64 static void contact_set_property       (GObject             *object,
65                                         guint                param_id,
66                                         const GValue        *value,
67                                         GParamSpec          *pspec);
68
69 G_DEFINE_TYPE (EmpathyContact, empathy_contact, G_TYPE_OBJECT);
70
71 enum {
72         PROP_0,
73         PROP_ID,
74         PROP_NAME,
75         PROP_AVATAR,
76         PROP_ACCOUNT,
77         PROP_PRESENCE,
78         PROP_PRESENCE_MESSAGE,
79         PROP_GROUPS,
80         PROP_SUBSCRIPTION,
81         PROP_HANDLE,
82         PROP_CAPABILITIES,
83         PROP_IS_USER
84 };
85
86 static void
87 empathy_contact_class_init (EmpathyContactClass *class)
88 {
89         GObjectClass *object_class;
90
91         object_class = G_OBJECT_CLASS (class);
92
93         object_class->finalize     = contact_finalize;
94         object_class->get_property = contact_get_property;
95         object_class->set_property = contact_set_property;
96
97         g_object_class_install_property (object_class,
98                                          PROP_ID,
99                                          g_param_spec_string ("id",
100                                                               "Contact id",
101                                                               "String identifying contact",
102                                                               NULL,
103                                                               G_PARAM_READWRITE));
104
105         g_object_class_install_property (object_class,
106                                          PROP_NAME,
107                                          g_param_spec_string ("name",
108                                                               "Contact Name",
109                                                               "The name of the contact",
110                                                               NULL,
111                                                               G_PARAM_READWRITE));
112
113         g_object_class_install_property (object_class,
114                                          PROP_AVATAR,
115                                          g_param_spec_boxed ("avatar",
116                                                              "Avatar image",
117                                                              "The avatar image",
118                                                              EMPATHY_TYPE_AVATAR,
119                                                              G_PARAM_READWRITE));
120
121         g_object_class_install_property (object_class,
122                                          PROP_ACCOUNT,
123                                          g_param_spec_object ("account",
124                                                               "Contact Account",
125                                                               "The account associated with the contact",
126                                                               MC_TYPE_ACCOUNT,
127                                                               G_PARAM_READWRITE));
128
129         g_object_class_install_property (object_class,
130                                          PROP_PRESENCE,
131                                          g_param_spec_uint ("presence",
132                                                             "Contact presence",
133                                                             "Presence of contact",
134                                                             MC_PRESENCE_UNSET,
135                                                             LAST_MC_PRESENCE,
136                                                             MC_PRESENCE_UNSET,
137                                                             G_PARAM_READWRITE));
138
139         g_object_class_install_property (object_class,
140                                          PROP_PRESENCE_MESSAGE,
141                                          g_param_spec_string ("presence-message",
142                                                               "Contact presence message",
143                                                               "Presence message of contact",
144                                                               NULL,
145                                                               G_PARAM_READWRITE));
146         g_object_class_install_property (object_class,
147                                          PROP_HANDLE,
148                                          g_param_spec_uint ("handle",
149                                                             "Contact Handle",
150                                                             "The handle of the contact",
151                                                             0,
152                                                             G_MAXUINT,
153                                                             0,
154                                                             G_PARAM_READWRITE));
155
156         g_object_class_install_property (object_class,
157                                          PROP_CAPABILITIES,
158                                          g_param_spec_flags ("capabilities",
159                                                              "Contact Capabilities",
160                                                              "Capabilities of the contact",
161                                                              EMPATHY_TYPE_CAPABILITIES,
162                                                              0,
163                                                              G_PARAM_READWRITE));
164
165         g_object_class_install_property (object_class,
166                                          PROP_IS_USER,
167                                          g_param_spec_boolean ("is-user",
168                                                                "Contact is-user",
169                                                                "Is contact the user",
170                                                                FALSE,
171                                                                G_PARAM_READWRITE));
172
173         g_type_class_add_private (object_class, sizeof (EmpathyContactPriv));
174 }
175
176 static void
177 empathy_contact_init (EmpathyContact *contact)
178 {
179         EmpathyContactPriv *priv;
180
181         priv = GET_PRIV (contact);
182         priv->capabilities = EMPATHY_CAPABILITIES_UNKNOWN;
183 }
184
185 static void
186 contact_finalize (GObject *object)
187 {
188         EmpathyContactPriv *priv;
189
190         priv = GET_PRIV (object);
191
192         empathy_debug (DEBUG_DOMAIN, "finalize: %p", object);
193
194         g_free (priv->name);
195         g_free (priv->id);
196         g_free (priv->presence_message);
197
198         if (priv->avatar) {
199                 empathy_avatar_unref (priv->avatar);
200         }
201
202         if (priv->account) {
203                 g_object_unref (priv->account);
204         }
205
206         G_OBJECT_CLASS (empathy_contact_parent_class)->finalize (object);
207 }
208
209 static void
210 contact_get_property (GObject    *object,
211                       guint       param_id,
212                       GValue     *value,
213                       GParamSpec *pspec)
214 {
215         EmpathyContactPriv *priv;
216
217         priv = GET_PRIV (object);
218
219         switch (param_id) {
220         case PROP_ID:
221                 g_value_set_string (value,
222                                     empathy_contact_get_id (EMPATHY_CONTACT (object)));
223                 break;
224         case PROP_NAME:
225                 g_value_set_string (value,
226                                     empathy_contact_get_name (EMPATHY_CONTACT (object)));
227                 break;
228         case PROP_AVATAR:
229                 g_value_set_boxed (value, priv->avatar);
230                 break;
231         case PROP_ACCOUNT:
232                 g_value_set_object (value, priv->account);
233                 break;
234         case PROP_PRESENCE:
235                 g_value_set_uint (value, priv->presence);
236                 break;
237         case PROP_PRESENCE_MESSAGE:
238                 g_value_set_string (value, priv->presence_message);
239                 break;
240         case PROP_HANDLE:
241                 g_value_set_uint (value, priv->handle);
242                 break;
243         case PROP_CAPABILITIES:
244                 g_value_set_flags (value, priv->capabilities);
245                 break;
246         case PROP_IS_USER:
247                 g_value_set_boolean (value, priv->is_user);
248                 break;
249         default:
250                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
251                 break;
252         };
253 }
254
255 static void
256 contact_set_property (GObject      *object,
257                       guint         param_id,
258                       const GValue *value,
259                       GParamSpec   *pspec)
260 {
261         EmpathyContactPriv *priv;
262
263         priv = GET_PRIV (object);
264
265         switch (param_id) {
266         case PROP_ID:
267                 empathy_contact_set_id (EMPATHY_CONTACT (object),
268                                        g_value_get_string (value));
269                 break;
270         case PROP_NAME:
271                 empathy_contact_set_name (EMPATHY_CONTACT (object),
272                                          g_value_get_string (value));
273                 break;
274         case PROP_AVATAR:
275                 empathy_contact_set_avatar (EMPATHY_CONTACT (object),
276                                            g_value_get_boxed (value));
277                 break;
278         case PROP_ACCOUNT:
279                 empathy_contact_set_account (EMPATHY_CONTACT (object),
280                                             MC_ACCOUNT (g_value_get_object (value)));
281                 break;
282         case PROP_PRESENCE:
283                 empathy_contact_set_presence (EMPATHY_CONTACT (object),
284                                               g_value_get_uint (value));
285                 break;
286         case PROP_PRESENCE_MESSAGE:
287                 empathy_contact_set_presence_message (EMPATHY_CONTACT (object),
288                                                       g_value_get_string (value));
289                 break;
290         case PROP_HANDLE:
291                 empathy_contact_set_handle (EMPATHY_CONTACT (object),
292                                            g_value_get_uint (value));
293                 break;
294         case PROP_CAPABILITIES:
295                 empathy_contact_set_capabilities (EMPATHY_CONTACT (object),
296                                                   g_value_get_flags (value));
297                 break;
298         case PROP_IS_USER:
299                 empathy_contact_set_is_user (EMPATHY_CONTACT (object),
300                                             g_value_get_boolean (value));
301                 break;
302         default:
303                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
304                 break;
305         };
306 }
307
308 EmpathyContact *
309 empathy_contact_new (McAccount *account)
310 {
311         return g_object_new (EMPATHY_TYPE_CONTACT,
312                              "account", account,
313                              NULL);
314 }
315
316 EmpathyContact *
317 empathy_contact_new_full (McAccount   *account,
318                           const gchar *id,
319                           const gchar *name)
320 {
321         return g_object_new (EMPATHY_TYPE_CONTACT,
322                              "account", account,
323                              "name", name,
324                              "id", id,
325                              NULL);
326 }
327
328 const gchar *
329 empathy_contact_get_id (EmpathyContact *contact)
330 {
331         EmpathyContactPriv *priv;
332
333         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), "");
334
335         priv = GET_PRIV (contact);
336
337         if (priv->id) {
338                 return priv->id;
339         }
340
341         return "";
342 }
343
344 void
345 empathy_contact_set_id (EmpathyContact *contact,
346                        const gchar   *id)
347 {
348         EmpathyContactPriv *priv;
349
350         g_return_if_fail (EMPATHY_IS_CONTACT (contact));
351         g_return_if_fail (id != NULL);
352
353         priv = GET_PRIV (contact);
354
355         if (priv->id && strcmp (id, priv->id) == 0) {
356                 return;
357         }
358
359         g_free (priv->id);
360         priv->id = g_strdup (id);
361
362         g_object_notify (G_OBJECT (contact), "id");
363 }
364
365 const gchar *
366 empathy_contact_get_name (EmpathyContact *contact)
367 {
368         EmpathyContactPriv *priv;
369
370         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), "");
371
372         priv = GET_PRIV (contact);
373
374         if (G_STR_EMPTY (priv->name)) {
375                 return empathy_contact_get_id (contact);
376         }
377
378         return priv->name;
379 }
380
381 void
382 empathy_contact_set_name (EmpathyContact *contact,
383                          const gchar   *name)
384 {
385         EmpathyContactPriv *priv;
386
387         g_return_if_fail (EMPATHY_IS_CONTACT (contact));
388         g_return_if_fail (name != NULL);
389
390         priv = GET_PRIV (contact);
391
392         if (priv->name && strcmp (name, priv->name) == 0) {
393                 return;
394         }
395
396         g_free (priv->name);
397         priv->name = g_strdup (name);
398
399         g_object_notify (G_OBJECT (contact), "name");
400 }
401
402 EmpathyAvatar *
403 empathy_contact_get_avatar (EmpathyContact *contact)
404 {
405         EmpathyContactPriv *priv;
406
407         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
408
409         priv = GET_PRIV (contact);
410
411         return priv->avatar;
412 }
413
414 void
415 empathy_contact_set_avatar (EmpathyContact *contact,
416                            EmpathyAvatar  *avatar)
417 {
418         EmpathyContactPriv *priv;
419
420         g_return_if_fail (EMPATHY_IS_CONTACT (contact));
421
422         priv = GET_PRIV (contact);
423
424         if (priv->avatar == avatar) {
425                 return;
426         }
427
428         if (priv->avatar) {
429                 empathy_avatar_unref (priv->avatar);
430                 priv->avatar = NULL;
431         }
432
433         if (avatar) {
434                 priv->avatar = empathy_avatar_ref (avatar);
435         }
436
437         g_object_notify (G_OBJECT (contact), "avatar");
438 }
439
440 McAccount *
441 empathy_contact_get_account (EmpathyContact *contact)
442 {
443         EmpathyContactPriv *priv;
444
445         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
446
447         priv = GET_PRIV (contact);
448
449         return priv->account;
450 }
451
452 void
453 empathy_contact_set_account (EmpathyContact *contact,
454                              McAccount      *account)
455 {
456         EmpathyContactPriv *priv;
457
458         g_return_if_fail (EMPATHY_IS_CONTACT (contact));
459         g_return_if_fail (MC_IS_ACCOUNT (account));
460
461         priv = GET_PRIV (contact);
462
463         if (account == priv->account) {
464                 return;
465         }
466
467         if (priv->account) {
468                 g_object_unref (priv->account);
469         }
470         priv->account = g_object_ref (account);
471
472         g_object_notify (G_OBJECT (contact), "account");
473 }
474
475 McPresence
476 empathy_contact_get_presence (EmpathyContact *contact)
477 {
478         EmpathyContactPriv *priv;
479
480         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), MC_PRESENCE_UNSET);
481
482         priv = GET_PRIV (contact);
483
484         return priv->presence;
485 }
486
487 void
488 empathy_contact_set_presence (EmpathyContact *contact,
489                               McPresence      presence)
490 {
491         EmpathyContactPriv *priv;
492
493         g_return_if_fail (EMPATHY_IS_CONTACT (contact));
494
495         priv = GET_PRIV (contact);
496
497         if (presence == priv->presence) {
498                 return;
499         }
500
501         priv->presence = presence;
502
503         g_object_notify (G_OBJECT (contact), "presence");
504 }
505
506 const gchar *
507 empathy_contact_get_presence_message (EmpathyContact *contact)
508 {
509         EmpathyContactPriv *priv;
510
511         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
512
513         priv = GET_PRIV (contact);
514
515         return priv->presence_message;
516 }
517
518 void
519 empathy_contact_set_presence_message (EmpathyContact *contact,
520                                       const gchar    *message)
521 {
522         EmpathyContactPriv *priv = GET_PRIV (contact);
523
524         g_return_if_fail (EMPATHY_IS_CONTACT (contact));
525
526         if (!tp_strdiff (message, priv->presence_message)) {
527                 return;
528         }
529
530         g_free (priv->presence_message);
531         priv->presence_message = g_strdup (message);
532
533         g_object_notify (G_OBJECT (contact), "presence-message");
534 }
535
536 guint
537 empathy_contact_get_handle (EmpathyContact *contact)
538 {
539         EmpathyContactPriv *priv;
540
541         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), 0);
542
543         priv = GET_PRIV (contact);
544
545         return priv->handle;
546 }
547
548 void
549 empathy_contact_set_handle (EmpathyContact *contact,
550                            guint          handle)
551 {
552         EmpathyContactPriv *priv;
553
554         g_return_if_fail (EMPATHY_IS_CONTACT (contact));
555
556         priv = GET_PRIV (contact);
557
558         if (priv->handle == handle) {
559                 return;
560         }
561
562         priv->handle = handle;
563
564         g_object_notify (G_OBJECT (contact), "handle");
565 }
566
567 EmpathyCapabilities
568 empathy_contact_get_capabilities (EmpathyContact *contact)
569 {
570         EmpathyContactPriv *priv;
571
572         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), 0);
573
574         priv = GET_PRIV (contact);
575
576         return priv->capabilities;
577 }
578
579 void
580 empathy_contact_set_capabilities (EmpathyContact      *contact,
581                                   EmpathyCapabilities  capabilities)
582 {
583         EmpathyContactPriv *priv;
584
585         g_return_if_fail (EMPATHY_IS_CONTACT (contact));
586
587         priv = GET_PRIV (contact);
588
589         if (priv->capabilities == capabilities) {
590                 return;
591         }
592
593         priv->capabilities = capabilities;
594
595         g_object_notify (G_OBJECT (contact), "capabilities");
596 }
597
598 gboolean
599 empathy_contact_is_user (EmpathyContact *contact)
600 {
601         EmpathyContactPriv *priv;
602
603         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), FALSE);
604
605         priv = GET_PRIV (contact);
606
607         return priv->is_user;
608 }
609
610 void
611 empathy_contact_set_is_user (EmpathyContact *contact,
612                             gboolean       is_user)
613 {
614         EmpathyContactPriv *priv;
615
616         g_return_if_fail (EMPATHY_IS_CONTACT (contact));
617
618         priv = GET_PRIV (contact);
619
620         if (priv->is_user == is_user) {
621                 return;
622         }
623
624         priv->is_user = is_user;
625
626         g_object_notify (G_OBJECT (contact), "is-user");
627 }
628
629 gboolean
630 empathy_contact_is_online (EmpathyContact *contact)
631 {
632         EmpathyContactPriv *priv;
633
634         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), FALSE);
635
636         priv = GET_PRIV (contact);
637
638         return (priv->presence > MC_PRESENCE_OFFLINE);
639 }
640
641 const gchar *
642 empathy_contact_get_status (EmpathyContact *contact)
643 {
644         EmpathyContactPriv *priv;
645
646         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), "");
647
648         priv = GET_PRIV (contact);
649
650         if (priv->presence_message) {
651                 return priv->presence_message;
652         }
653
654         return empathy_presence_get_default_message (priv->presence);
655 }
656
657 gboolean
658 empathy_contact_can_voip (EmpathyContact *contact)
659 {
660         EmpathyContactPriv *priv;
661
662         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), FALSE);
663
664         priv = GET_PRIV (contact);
665
666         return priv->capabilities & (EMPATHY_CAPABILITIES_AUDIO |
667                                      EMPATHY_CAPABILITIES_VIDEO);
668 }
669
670 gboolean
671 empathy_contact_equal (gconstpointer v1,
672                       gconstpointer v2)
673 {
674         McAccount   *account_a;
675         McAccount   *account_b;
676         const gchar *id_a;
677         const gchar *id_b;
678
679         g_return_val_if_fail (EMPATHY_IS_CONTACT (v1), FALSE);
680         g_return_val_if_fail (EMPATHY_IS_CONTACT (v2), FALSE);
681
682         account_a = empathy_contact_get_account (EMPATHY_CONTACT (v1));
683         account_b = empathy_contact_get_account (EMPATHY_CONTACT (v2));
684
685         id_a = empathy_contact_get_id (EMPATHY_CONTACT (v1));
686         id_b = empathy_contact_get_id (EMPATHY_CONTACT (v2));
687
688         return empathy_account_equal (account_a, account_b) && g_str_equal (id_a, id_b);
689 }
690
691 guint
692 empathy_contact_hash (gconstpointer key)
693 {
694         EmpathyContactPriv *priv;
695         guint              hash;
696
697         g_return_val_if_fail (EMPATHY_IS_CONTACT (key), +1);
698
699         priv = GET_PRIV (EMPATHY_CONTACT (key));
700
701         hash = empathy_account_hash (empathy_contact_get_account (EMPATHY_CONTACT (key)));
702         hash += g_str_hash (empathy_contact_get_id (EMPATHY_CONTACT (key)));
703
704         return hash;
705 }
706