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