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