]> git.0d.be Git - empathy.git/blob - libempathy/empathy-contact.c
Ready property on EmpathyContact is not a boolean but flags for each property.
[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         EmpathyContactReady 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_flags ("ready",
177                                                              "Contact ready flags",
178                                                              "Flags for ready properties",
179                                                              EMPATHY_TYPE_CONTACT_READY,
180                                                              EMPATHY_CONTACT_READY_NONE,
181                                                              G_PARAM_READABLE));
182
183         g_type_class_add_private (object_class, sizeof (EmpathyContactPriv));
184 }
185
186 static void
187 empathy_contact_init (EmpathyContact *contact)
188 {
189 }
190
191 static void
192 contact_finalize (GObject *object)
193 {
194         EmpathyContactPriv *priv;
195
196         priv = GET_PRIV (object);
197
198         empathy_debug (DEBUG_DOMAIN, "finalize: %p", object);
199
200         g_free (priv->name);
201         g_free (priv->id);
202         g_free (priv->presence_message);
203
204         if (priv->avatar) {
205                 empathy_avatar_unref (priv->avatar);
206         }
207
208         if (priv->account) {
209                 g_object_unref (priv->account);
210         }
211
212         G_OBJECT_CLASS (empathy_contact_parent_class)->finalize (object);
213 }
214
215 static void
216 contact_get_property (GObject    *object,
217                       guint       param_id,
218                       GValue     *value,
219                       GParamSpec *pspec)
220 {
221         EmpathyContactPriv *priv;
222
223         priv = GET_PRIV (object);
224
225         switch (param_id) {
226         case PROP_ID:
227                 g_value_set_string (value, priv->id);
228                 break;
229         case PROP_NAME:
230                 g_value_set_string (value,
231                                     empathy_contact_get_name (EMPATHY_CONTACT (object)));
232                 break;
233         case PROP_AVATAR:
234                 g_value_set_boxed (value, priv->avatar);
235                 break;
236         case PROP_ACCOUNT:
237                 g_value_set_object (value, priv->account);
238                 break;
239         case PROP_PRESENCE:
240                 g_value_set_uint (value, priv->presence);
241                 break;
242         case PROP_PRESENCE_MESSAGE:
243                 g_value_set_string (value, priv->presence_message);
244                 break;
245         case PROP_HANDLE:
246                 g_value_set_uint (value, priv->handle);
247                 break;
248         case PROP_CAPABILITIES:
249                 g_value_set_flags (value, priv->capabilities);
250                 break;
251         case PROP_IS_USER:
252                 g_value_set_boolean (value, priv->is_user);
253                 break;
254         case PROP_READY:
255                 g_value_set_flags (value, priv->ready);
256                 break;
257         default:
258                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
259                 break;
260         };
261 }
262
263 static void
264 contact_set_property (GObject      *object,
265                       guint         param_id,
266                       const GValue *value,
267                       GParamSpec   *pspec)
268 {
269         EmpathyContactPriv *priv;
270
271         priv = GET_PRIV (object);
272
273         switch (param_id) {
274         case PROP_ID:
275                 empathy_contact_set_id (EMPATHY_CONTACT (object),
276                                        g_value_get_string (value));
277                 break;
278         case PROP_NAME:
279                 empathy_contact_set_name (EMPATHY_CONTACT (object),
280                                          g_value_get_string (value));
281                 break;
282         case PROP_AVATAR:
283                 empathy_contact_set_avatar (EMPATHY_CONTACT (object),
284                                            g_value_get_boxed (value));
285                 break;
286         case PROP_ACCOUNT:
287                 empathy_contact_set_account (EMPATHY_CONTACT (object),
288                                             MC_ACCOUNT (g_value_get_object (value)));
289                 break;
290         case PROP_PRESENCE:
291                 empathy_contact_set_presence (EMPATHY_CONTACT (object),
292                                               g_value_get_uint (value));
293                 break;
294         case PROP_PRESENCE_MESSAGE:
295                 empathy_contact_set_presence_message (EMPATHY_CONTACT (object),
296                                                       g_value_get_string (value));
297                 break;
298         case PROP_HANDLE:
299                 empathy_contact_set_handle (EMPATHY_CONTACT (object),
300                                            g_value_get_uint (value));
301                 break;
302         case PROP_CAPABILITIES:
303                 empathy_contact_set_capabilities (EMPATHY_CONTACT (object),
304                                                   g_value_get_flags (value));
305                 break;
306         case PROP_IS_USER:
307                 empathy_contact_set_is_user (EMPATHY_CONTACT (object),
308                                             g_value_get_boolean (value));
309                 break;
310         default:
311                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
312                 break;
313         };
314 }
315
316 EmpathyContact *
317 empathy_contact_new (McAccount *account)
318 {
319         return g_object_new (EMPATHY_TYPE_CONTACT,
320                              "account", account,
321                              NULL);
322 }
323
324 EmpathyContact *
325 empathy_contact_new_full (McAccount   *account,
326                           const gchar *id,
327                           const gchar *name)
328 {
329         return g_object_new (EMPATHY_TYPE_CONTACT,
330                              "account", account,
331                              "name", name,
332                              "id", id,
333                              NULL);
334 }
335
336 const gchar *
337 empathy_contact_get_id (EmpathyContact *contact)
338 {
339         EmpathyContactPriv *priv;
340
341         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
342
343         priv = GET_PRIV (contact);
344
345         return priv->id;
346 }
347
348 void
349 empathy_contact_set_id (EmpathyContact *contact,
350                        const gchar   *id)
351 {
352         EmpathyContactPriv *priv;
353
354         g_return_if_fail (EMPATHY_IS_CONTACT (contact));
355         g_return_if_fail (id != NULL);
356
357         priv = GET_PRIV (contact);
358
359         if (!tp_strdiff (id, priv->id)) {
360                 return;
361         }
362
363         g_free (priv->id);
364         priv->id = g_strdup (id);
365
366         g_object_notify (G_OBJECT (contact), "id");
367         if (G_STR_EMPTY (priv->name)) {
368                 g_object_notify (G_OBJECT (contact), "name");
369         }
370 }
371
372 const gchar *
373 empathy_contact_get_name (EmpathyContact *contact)
374 {
375         EmpathyContactPriv *priv;
376
377         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
378
379         priv = GET_PRIV (contact);
380
381         if (G_STR_EMPTY (priv->name)) {
382                 return empathy_contact_get_id (contact);
383         }
384
385         return priv->name;
386 }
387
388 void
389 empathy_contact_set_name (EmpathyContact *contact,
390                          const gchar   *name)
391 {
392         EmpathyContactPriv *priv;
393
394         g_return_if_fail (EMPATHY_IS_CONTACT (contact));
395
396         priv = GET_PRIV (contact);
397
398         if (!tp_strdiff (name, priv->name)) {
399                 return;
400         }
401
402         g_free (priv->name);
403         priv->name = g_strdup (name);
404
405         g_object_notify (G_OBJECT (contact), "name");
406 }
407
408 EmpathyAvatar *
409 empathy_contact_get_avatar (EmpathyContact *contact)
410 {
411         EmpathyContactPriv *priv;
412
413         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
414
415         priv = GET_PRIV (contact);
416
417         return priv->avatar;
418 }
419
420 void
421 empathy_contact_set_avatar (EmpathyContact *contact,
422                            EmpathyAvatar  *avatar)
423 {
424         EmpathyContactPriv *priv;
425
426         g_return_if_fail (EMPATHY_IS_CONTACT (contact));
427
428         priv = GET_PRIV (contact);
429
430         if (priv->avatar == avatar) {
431                 return;
432         }
433
434         if (priv->avatar) {
435                 empathy_avatar_unref (priv->avatar);
436                 priv->avatar = NULL;
437         }
438
439         if (avatar) {
440                 priv->avatar = empathy_avatar_ref (avatar);
441         }
442
443         g_object_notify (G_OBJECT (contact), "avatar");
444 }
445
446 McAccount *
447 empathy_contact_get_account (EmpathyContact *contact)
448 {
449         EmpathyContactPriv *priv;
450
451         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
452
453         priv = GET_PRIV (contact);
454
455         return priv->account;
456 }
457
458 void
459 empathy_contact_set_account (EmpathyContact *contact,
460                              McAccount      *account)
461 {
462         EmpathyContactPriv *priv;
463
464         g_return_if_fail (EMPATHY_IS_CONTACT (contact));
465         g_return_if_fail (MC_IS_ACCOUNT (account));
466
467         priv = GET_PRIV (contact);
468
469         if (account == priv->account) {
470                 return;
471         }
472
473         if (priv->account) {
474                 g_object_unref (priv->account);
475         }
476         priv->account = g_object_ref (account);
477
478         g_object_notify (G_OBJECT (contact), "account");
479 }
480
481 McPresence
482 empathy_contact_get_presence (EmpathyContact *contact)
483 {
484         EmpathyContactPriv *priv;
485
486         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), MC_PRESENCE_UNSET);
487
488         priv = GET_PRIV (contact);
489
490         return priv->presence;
491 }
492
493 void
494 empathy_contact_set_presence (EmpathyContact *contact,
495                               McPresence      presence)
496 {
497         EmpathyContactPriv *priv;
498
499         g_return_if_fail (EMPATHY_IS_CONTACT (contact));
500
501         priv = GET_PRIV (contact);
502
503         if (presence == priv->presence) {
504                 return;
505         }
506
507         priv->presence = presence;
508
509         g_object_notify (G_OBJECT (contact), "presence");
510 }
511
512 const gchar *
513 empathy_contact_get_presence_message (EmpathyContact *contact)
514 {
515         EmpathyContactPriv *priv;
516
517         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
518
519         priv = GET_PRIV (contact);
520
521         return priv->presence_message;
522 }
523
524 void
525 empathy_contact_set_presence_message (EmpathyContact *contact,
526                                       const gchar    *message)
527 {
528         EmpathyContactPriv *priv = GET_PRIV (contact);
529
530         g_return_if_fail (EMPATHY_IS_CONTACT (contact));
531
532         if (!tp_strdiff (message, priv->presence_message)) {
533                 return;
534         }
535
536         g_free (priv->presence_message);
537         priv->presence_message = g_strdup (message);
538
539         g_object_notify (G_OBJECT (contact), "presence-message");
540 }
541
542 guint
543 empathy_contact_get_handle (EmpathyContact *contact)
544 {
545         EmpathyContactPriv *priv;
546
547         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), 0);
548
549         priv = GET_PRIV (contact);
550
551         return priv->handle;
552 }
553
554 void
555 empathy_contact_set_handle (EmpathyContact *contact,
556                            guint          handle)
557 {
558         EmpathyContactPriv *priv;
559
560         g_return_if_fail (EMPATHY_IS_CONTACT (contact));
561
562         priv = GET_PRIV (contact);
563
564         if (priv->handle == handle) {
565                 return;
566         }
567
568         priv->handle = handle;
569
570         g_object_notify (G_OBJECT (contact), "handle");
571 }
572
573 EmpathyCapabilities
574 empathy_contact_get_capabilities (EmpathyContact *contact)
575 {
576         EmpathyContactPriv *priv;
577
578         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), 0);
579
580         priv = GET_PRIV (contact);
581
582         return priv->capabilities;
583 }
584
585 void
586 empathy_contact_set_capabilities (EmpathyContact      *contact,
587                                   EmpathyCapabilities  capabilities)
588 {
589         EmpathyContactPriv *priv;
590
591         g_return_if_fail (EMPATHY_IS_CONTACT (contact));
592
593         priv = GET_PRIV (contact);
594
595         if (priv->capabilities == capabilities) {
596                 return;
597         }
598
599         priv->capabilities = capabilities;
600
601         g_object_notify (G_OBJECT (contact), "capabilities");
602 }
603
604 gboolean
605 empathy_contact_is_user (EmpathyContact *contact)
606 {
607         EmpathyContactPriv *priv;
608
609         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), FALSE);
610
611         priv = GET_PRIV (contact);
612
613         return priv->is_user;
614 }
615
616 void
617 empathy_contact_set_is_user (EmpathyContact *contact,
618                             gboolean       is_user)
619 {
620         EmpathyContactPriv *priv;
621
622         g_return_if_fail (EMPATHY_IS_CONTACT (contact));
623
624         priv = GET_PRIV (contact);
625
626         if (priv->is_user == is_user) {
627                 return;
628         }
629
630         priv->is_user = is_user;
631
632         g_object_notify (G_OBJECT (contact), "is-user");
633 }
634
635 gboolean
636 empathy_contact_is_online (EmpathyContact *contact)
637 {
638         EmpathyContactPriv *priv;
639
640         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), FALSE);
641
642         priv = GET_PRIV (contact);
643
644         return (priv->presence > MC_PRESENCE_OFFLINE);
645 }
646
647 const gchar *
648 empathy_contact_get_status (EmpathyContact *contact)
649 {
650         EmpathyContactPriv *priv;
651
652         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), "");
653
654         priv = GET_PRIV (contact);
655
656         if (priv->presence_message) {
657                 return priv->presence_message;
658         }
659
660         return empathy_presence_get_default_message (priv->presence);
661 }
662
663 gboolean
664 empathy_contact_can_voip (EmpathyContact *contact)
665 {
666         EmpathyContactPriv *priv;
667
668         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), FALSE);
669
670         priv = GET_PRIV (contact);
671
672         return priv->capabilities & (EMPATHY_CAPABILITIES_AUDIO |
673                                      EMPATHY_CAPABILITIES_VIDEO);
674 }
675
676 EmpathyContactReady
677 empathy_contact_get_ready (EmpathyContact *contact)
678 {
679         EmpathyContactPriv *priv;
680
681         g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), FALSE);
682
683         priv = GET_PRIV (contact);
684
685         return priv->ready;
686 }
687
688 gboolean
689 empathy_contact_equal (gconstpointer v1,
690                       gconstpointer v2)
691 {
692         McAccount   *account_a;
693         McAccount   *account_b;
694         const gchar *id_a;
695         const gchar *id_b;
696
697         g_return_val_if_fail (EMPATHY_IS_CONTACT (v1), FALSE);
698         g_return_val_if_fail (EMPATHY_IS_CONTACT (v2), FALSE);
699
700         account_a = empathy_contact_get_account (EMPATHY_CONTACT (v1));
701         account_b = empathy_contact_get_account (EMPATHY_CONTACT (v2));
702
703         id_a = empathy_contact_get_id (EMPATHY_CONTACT (v1));
704         id_b = empathy_contact_get_id (EMPATHY_CONTACT (v2));
705
706         return empathy_account_equal (account_a, account_b) && g_str_equal (id_a, id_b);
707 }
708
709 guint
710 empathy_contact_hash (gconstpointer key)
711 {
712         EmpathyContactPriv *priv;
713
714         g_return_val_if_fail (EMPATHY_IS_CONTACT (key), +1);
715
716         priv = GET_PRIV (EMPATHY_CONTACT (key));
717
718         if (priv->hash == 0) {
719                 priv->hash = empathy_account_hash (priv->account) + g_str_hash (priv->id);
720         }
721
722         return priv->hash;
723 }
724