]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-contact-widget.c
Updated Spanish translation
[empathy.git] / libempathy-gtk / empathy-contact-widget.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2007-2009 Collabora Ltd.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  *
19  * Authors: Xavier Claessens <xclaesse@gmail.com>
20  */
21
22 #include "config.h"
23 #include "empathy-contact-widget.h"
24
25 #include <glib/gi18n-lib.h>
26 #include <tp-account-widgets/tpaw-builder.h>
27 #include <tp-account-widgets/tpaw-string-parser.h>
28 #include <tp-account-widgets/tpaw-utils.h>
29
30 #include "empathy-avatar-image.h"
31 #include "empathy-client-factory.h"
32 #include "empathy-groups-widget.h"
33 #include "empathy-ui-utils.h"
34 #include "empathy-utils.h"
35
36 #define DEBUG_FLAG EMPATHY_DEBUG_CONTACT
37 #include "empathy-debug.h"
38
39 /**
40  * SECTION:empathy-contact-widget
41  * @title:EmpathyContactWidget
42  * @short_description: A widget used to display and edit details about a contact
43  * @include: libempathy-empathy-contact-widget.h
44  *
45  * #EmpathyContactWidget is a widget which displays appropriate widgets
46  * with details about a contact, also allowing changing these details,
47  * if desired.
48  */
49
50 /**
51  * EmpathyContactWidget:
52  * @parent: parent object
53  *
54  * Widget which displays appropriate widgets with details about a contact,
55  * also allowing changing these details, if desired.
56  */
57
58 G_DEFINE_TYPE (EmpathyContactWidget, empathy_contact_widget, GTK_TYPE_BOX)
59
60 /* Delay before updating the widget when the id entry changed (seconds) */
61 #define ID_CHANGED_TIMEOUT 1
62
63 #define DATA_FIELD "contact-info-field"
64
65 struct _EmpathyContactWidgetPriv
66 {
67   EmpathyContact *contact;
68   guint widget_id_timeout;
69   gulong fav_sig_id;
70
71   /* Contact */
72   GtkWidget *widget_avatar;
73   GtkWidget *widget_account;
74   GtkWidget *image_account;
75   GtkWidget *label_account;
76   GtkWidget *widget_id;
77   GtkWidget *widget_alias;
78   GtkWidget *label_alias;
79   GtkWidget *hbox_presence;
80   GtkWidget *image_state;
81   GtkWidget *label_status;
82   GtkWidget *grid_contact;
83   GtkWidget *vbox_avatar;
84   GtkWidget *favourite_checkbox;
85   GtkWidget *label_details;
86   GtkWidget *label_left_account;
87
88   /* Groups */
89   GtkWidget *groups_widget;
90
91   /* Client */
92   GtkWidget *vbox_client;
93   GtkWidget *grid_client;
94   GtkWidget *hbox_client_requested;
95 };
96
97 typedef struct
98 {
99   EmpathyContactWidget *self;
100   const gchar *name;
101   gboolean found;
102   GtkTreeIter found_iter;
103 } FindName;
104
105 enum
106 {
107   COL_NAME,
108   COL_ENABLED,
109   COL_EDITABLE,
110   COL_COUNT
111 };
112
113
114 static void
115 contact_widget_client_update (EmpathyContactWidget *self)
116 {
117   /* FIXME: Needs new telepathy spec */
118 }
119
120 static void
121 contact_widget_client_setup (EmpathyContactWidget *self)
122 {
123   /* FIXME: Needs new telepathy spec */
124   gtk_widget_hide (self->priv->vbox_client);
125 }
126
127 static void
128 contact_widget_groups_update (EmpathyContactWidget *self)
129 {
130   if (self->priv->contact != NULL)
131     {
132       FolksPersona *persona =
133           empathy_contact_get_persona (self->priv->contact);
134
135       if (FOLKS_IS_GROUP_DETAILS (persona))
136         {
137           empathy_groups_widget_set_group_details (
138               EMPATHY_GROUPS_WIDGET (self->priv->groups_widget),
139               FOLKS_GROUP_DETAILS (persona));
140           gtk_widget_show (self->priv->groups_widget);
141
142           return;
143         }
144     }
145
146   /* In case of failure */
147   gtk_widget_hide (self->priv->groups_widget);
148 }
149
150 static void
151 save_avatar_menu_activate_cb (GtkWidget *widget,
152     EmpathyContactWidget *self)
153 {
154   GtkWidget *dialog;
155   EmpathyAvatar *avatar;
156   gchar *ext = NULL, *filename;
157
158   dialog = gtk_file_chooser_dialog_new (_("Save Avatar"),
159       NULL,
160       GTK_FILE_CHOOSER_ACTION_SAVE,
161       GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
162       GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
163       NULL);
164
165   gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog),
166       TRUE);
167
168   /* look for the avatar extension */
169   avatar = empathy_contact_get_avatar (self->priv->contact);
170   if (avatar->format != NULL)
171     {
172       gchar **splitted;
173
174       splitted = g_strsplit (avatar->format, "/", 2);
175       if (splitted[0] != NULL && splitted[1] != NULL)
176           ext = g_strdup (splitted[1]);
177
178       g_strfreev (splitted);
179     }
180   else
181     {
182       /* Avatar was loaded from the cache so was converted to PNG */
183       ext = g_strdup ("png");
184     }
185
186   if (ext != NULL)
187     {
188       gchar *id;
189
190       id = tp_escape_as_identifier (empathy_contact_get_id (
191             self->priv->contact));
192
193       filename = g_strdup_printf ("%s.%s", id, ext);
194       gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), filename);
195
196       g_free (id);
197       g_free (ext);
198       g_free (filename);
199     }
200
201   if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
202     {
203       GError *error = NULL;
204
205       filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
206
207       if (!empathy_avatar_save_to_file (avatar, filename, &error))
208         {
209           /* Save error */
210           GtkWidget *error_dialog;
211
212           error_dialog = gtk_message_dialog_new (NULL, 0,
213               GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
214               _("Unable to save avatar"));
215
216           gtk_message_dialog_format_secondary_text (
217               GTK_MESSAGE_DIALOG (error_dialog), "%s", error->message);
218
219           g_signal_connect (error_dialog, "response",
220               G_CALLBACK (gtk_widget_destroy), NULL);
221
222           gtk_window_present (GTK_WINDOW (error_dialog));
223
224           g_clear_error (&error);
225         }
226
227       g_free (filename);
228     }
229
230   gtk_widget_destroy (dialog);
231 }
232
233 static void
234 popup_avatar_menu (EmpathyContactWidget *self,
235                    GtkWidget *parent,
236                    GdkEventButton *event)
237 {
238   GtkWidget *menu, *item;
239   gint button, event_time;
240
241   if (self->priv->contact == NULL ||
242       empathy_contact_get_avatar (self->priv->contact) == NULL)
243       return;
244
245   menu = empathy_context_menu_new (parent);
246
247   /* Add "Save as..." entry */
248   item = gtk_image_menu_item_new_from_stock (GTK_STOCK_SAVE_AS, NULL);
249   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
250   gtk_widget_show (item);
251
252   g_signal_connect (item, "activate",
253       G_CALLBACK (save_avatar_menu_activate_cb), self);
254
255   if (event)
256     {
257       button = event->button;
258       event_time = event->time;
259     }
260   else
261     {
262       button = 0;
263       event_time = gtk_get_current_event_time ();
264     }
265
266   gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
267       button, event_time);
268 }
269
270 static gboolean
271 widget_avatar_popup_menu_cb (GtkWidget *widget,
272                              EmpathyContactWidget *self)
273 {
274   popup_avatar_menu (self, widget, NULL);
275
276   return TRUE;
277 }
278
279 static gboolean
280 widget_avatar_button_press_event_cb (GtkWidget *widget,
281                                      GdkEventButton *event,
282                                      EmpathyContactWidget *self)
283 {
284   /* Ignore double-clicks and triple-clicks */
285   if (event->button == 3 && event->type == GDK_BUTTON_PRESS)
286     {
287       popup_avatar_menu (self, widget, event);
288       return TRUE;
289     }
290
291   return FALSE;
292 }
293
294 static void
295 set_nickname_cb (GObject *source,
296     GAsyncResult *res,
297     gpointer user_data)
298 {
299   GError *error = NULL;
300
301   if (!tp_account_set_nickname_finish (TP_ACCOUNT (source), res, &error))
302     {
303       DEBUG ("Failed to set Account.Nickname: %s", error->message);
304       g_error_free (error);
305     }
306 }
307
308 static gboolean
309 contact_widget_entry_alias_focus_event_cb (GtkEditable *editable,
310     GdkEventFocus *event,
311     EmpathyContactWidget *self)
312 {
313   if (self->priv->contact)
314     {
315       const gchar *alias;
316
317       alias = gtk_entry_get_text (GTK_ENTRY (editable));
318
319       if (empathy_contact_is_user (self->priv->contact))
320         {
321           TpAccount * account;
322           const gchar *current_nickname;
323
324           account = empathy_contact_get_account (self->priv->contact);
325           current_nickname = tp_account_get_nickname (account);
326
327           if (tp_strdiff (current_nickname, alias))
328             {
329               DEBUG ("Set Account.Nickname to %s", alias);
330
331               tp_account_set_nickname_async (account, alias, set_nickname_cb,
332                   NULL);
333             }
334         }
335       else
336         {
337           empathy_contact_set_alias (self->priv->contact, alias);
338         }
339     }
340
341   return FALSE;
342 }
343
344 static void
345 contact_widget_name_notify_cb (EmpathyContactWidget *self)
346 {
347   if (GTK_IS_ENTRY (self->priv->widget_alias))
348       gtk_entry_set_text (GTK_ENTRY (self->priv->widget_alias),
349           empathy_contact_get_alias (self->priv->contact));
350   else
351       gtk_label_set_label (GTK_LABEL (self->priv->widget_alias),
352           empathy_contact_get_alias (self->priv->contact));
353 }
354
355 static void
356 contact_widget_presence_notify_cb (EmpathyContactWidget *self)
357 {
358   const gchar *status;
359   gchar *markup_text = NULL;
360
361   status = empathy_contact_get_status (self->priv->contact);
362   if (status != NULL)
363     markup_text = tpaw_add_link_markup (status);
364   gtk_label_set_markup (GTK_LABEL (self->priv->label_status), markup_text);
365   g_free (markup_text);
366
367   gtk_image_set_from_icon_name (GTK_IMAGE (self->priv->image_state),
368       empathy_icon_name_for_contact (self->priv->contact),
369       GTK_ICON_SIZE_BUTTON);
370   gtk_widget_show (self->priv->image_state);
371 }
372
373 static void
374 contact_widget_remove_contact (EmpathyContactWidget *self)
375 {
376   if (self->priv->contact)
377     {
378       g_signal_handlers_disconnect_by_func (self->priv->contact,
379           contact_widget_name_notify_cb, self);
380       g_signal_handlers_disconnect_by_func (self->priv->contact,
381           contact_widget_presence_notify_cb, self);
382
383       g_object_unref (self->priv->contact);
384       self->priv->contact = NULL;
385     }
386 }
387
388 static void contact_widget_change_contact (EmpathyContactWidget *self);
389
390 static void
391 contact_widget_contact_update (EmpathyContactWidget *self)
392 {
393   TpAccount *account = NULL;
394   const gchar *id = NULL;
395
396   /* Connect and get info from new contact */
397   if (self->priv->contact)
398     {
399       g_signal_connect_swapped (self->priv->contact, "notify::name",
400           G_CALLBACK (contact_widget_name_notify_cb), self);
401       g_signal_connect_swapped (self->priv->contact, "notify::presence",
402           G_CALLBACK (contact_widget_presence_notify_cb), self);
403       g_signal_connect_swapped (self->priv->contact,
404           "notify::presence-message",
405           G_CALLBACK (contact_widget_presence_notify_cb), self);
406
407       account = empathy_contact_get_account (self->priv->contact);
408       id = empathy_contact_get_id (self->priv->contact);
409     }
410
411   /* Update account widget */
412   if (account)
413     {
414       g_signal_handlers_block_by_func (self->priv->widget_account,
415                contact_widget_change_contact,
416                self);
417       empathy_account_chooser_set_account (
418           EMPATHY_ACCOUNT_CHOOSER (self->priv->widget_account), account);
419       g_signal_handlers_unblock_by_func (self->priv->widget_account,
420           contact_widget_change_contact, self);
421     }
422
423   /* Update id widget */
424   gtk_entry_set_text (GTK_ENTRY (self->priv->widget_id), id ? id : "");
425
426   /* Update other widgets */
427   if (self->priv->contact)
428     {
429       contact_widget_name_notify_cb (self);
430       contact_widget_presence_notify_cb (self);
431
432       gtk_widget_show (self->priv->label_alias);
433       gtk_widget_show (self->priv->widget_alias);
434       gtk_widget_show (self->priv->widget_avatar);
435
436       gtk_widget_set_visible (self->priv->hbox_presence, TRUE);
437     }
438   else
439     {
440       gtk_widget_hide (self->priv->label_alias);
441       gtk_widget_hide (self->priv->widget_alias);
442       gtk_widget_hide (self->priv->hbox_presence);
443       gtk_widget_hide (self->priv->widget_avatar);
444     }
445 }
446
447 static void
448 contact_widget_set_contact (EmpathyContactWidget *self,
449                             EmpathyContact *contact)
450 {
451   if (contact == self->priv->contact)
452     return;
453
454   contact_widget_remove_contact (self);
455   if (contact)
456     self->priv->contact = g_object_ref (contact);
457
458   /* set the selected account to be the account this contact came from */
459   if (contact && EMPATHY_IS_ACCOUNT_CHOOSER (self->priv->widget_account)) {
460       empathy_account_chooser_set_account (
461                       EMPATHY_ACCOUNT_CHOOSER (self->priv->widget_account),
462                       empathy_contact_get_account (contact));
463   }
464
465   /* Update self for widgets */
466   contact_widget_contact_update (self);
467   contact_widget_groups_update (self);
468   contact_widget_client_update (self);
469 }
470
471 static void
472 contact_widget_got_contact_cb (GObject *source,
473     GAsyncResult *result,
474     gpointer user_data)
475 {
476   EmpathyContactWidget *self = user_data;
477   GError *error = NULL;
478   EmpathyContact *contact;
479
480   contact = empathy_client_factory_dup_contact_by_id_finish (
481       EMPATHY_CLIENT_FACTORY (source), result, &error);
482
483   if (contact == NULL)
484     {
485       DEBUG ("Error: %s", error->message);
486       g_error_free (error);
487       goto out;
488     }
489
490   contact_widget_set_contact (self, contact);
491
492   g_object_unref (contact);
493 out:
494   g_object_unref (self);
495 }
496
497 static void
498 contact_widget_change_contact (EmpathyContactWidget *self)
499 {
500   TpConnection *connection;
501   const gchar *id;
502
503   connection = empathy_account_chooser_get_connection (
504       EMPATHY_ACCOUNT_CHOOSER (self->priv->widget_account));
505   if (!connection)
506       return;
507
508   id = gtk_entry_get_text (GTK_ENTRY (self->priv->widget_id));
509   if (!TPAW_STR_EMPTY (id))
510     {
511       EmpathyClientFactory *factory;
512
513       factory = empathy_client_factory_dup ();
514
515       empathy_client_factory_dup_contact_by_id_async (factory, connection,
516           id, contact_widget_got_contact_cb, g_object_ref (self));
517
518       g_object_unref (factory);
519     }
520 }
521
522 static gboolean
523 contact_widget_id_activate_timeout (EmpathyContactWidget *self)
524 {
525   contact_widget_change_contact (self);
526   return FALSE;
527 }
528
529 static void
530 contact_widget_id_changed_cb (GtkEntry *entry,
531                               EmpathyContactWidget *self)
532 {
533   if (self->priv->widget_id_timeout != 0)
534     {
535       g_source_remove (self->priv->widget_id_timeout);
536     }
537
538   self->priv->widget_id_timeout =
539     g_timeout_add_seconds (ID_CHANGED_TIMEOUT,
540         (GSourceFunc) contact_widget_id_activate_timeout, self);
541 }
542
543 static gboolean
544 contact_widget_id_focus_out_cb (GtkWidget *widget,
545                                 GdkEventFocus *event,
546                                 EmpathyContactWidget *self)
547 {
548   contact_widget_change_contact (self);
549   return FALSE;
550 }
551
552 static void
553 contact_widget_contact_setup (EmpathyContactWidget *self)
554 {
555   self->priv->label_status = gtk_label_new ("");
556   gtk_label_set_line_wrap_mode (GTK_LABEL (self->priv->label_status),
557                                 PANGO_WRAP_WORD_CHAR);
558   gtk_label_set_line_wrap (GTK_LABEL (self->priv->label_status),
559                            TRUE);
560   gtk_misc_set_alignment (GTK_MISC (self->priv->label_status), 0, 0.5);
561
562   gtk_label_set_selectable (GTK_LABEL (self->priv->label_status), TRUE);
563
564   gtk_box_pack_start (GTK_BOX (self->priv->hbox_presence),
565         self->priv->label_status, TRUE, TRUE, 0);
566   gtk_widget_show (self->priv->label_status);
567
568   /* Setup account chooser */
569   self->priv->widget_account = empathy_account_chooser_new ();
570   g_signal_connect_swapped (self->priv->widget_account, "changed",
571         G_CALLBACK (contact_widget_change_contact),
572         self);
573   gtk_grid_attach (GTK_GRID (self->priv->grid_contact),
574       self->priv->widget_account,
575       2, 0, 1, 1);
576   gtk_widget_show (self->priv->widget_account);
577
578   /* Set up avatar display */
579   self->priv->widget_avatar = empathy_avatar_image_new ();
580
581   g_signal_connect (self->priv->widget_avatar, "popup-menu",
582       G_CALLBACK (widget_avatar_popup_menu_cb), self);
583   g_signal_connect (self->priv->widget_avatar, "button-press-event",
584       G_CALLBACK (widget_avatar_button_press_event_cb), self);
585   gtk_box_pack_start (GTK_BOX (self->priv->vbox_avatar),
586           self->priv->widget_avatar,
587           FALSE, FALSE,
588           6);
589   gtk_widget_show (self->priv->widget_avatar);
590
591   /* Setup id entry */
592   self->priv->widget_id = gtk_entry_new ();
593   g_signal_connect (self->priv->widget_id, "focus-out-event",
594         G_CALLBACK (contact_widget_id_focus_out_cb),
595         self);
596   g_signal_connect (self->priv->widget_id, "changed",
597         G_CALLBACK (contact_widget_id_changed_cb),
598         self);
599   gtk_grid_attach (GTK_GRID (self->priv->grid_contact), self->priv->widget_id,
600       2, 1, 1, 1);
601   gtk_widget_set_hexpand (self->priv->widget_id, TRUE);
602
603   gtk_widget_show (self->priv->widget_id);
604
605   /* Setup alias entry */
606   self->priv->widget_alias = gtk_entry_new ();
607
608   g_signal_connect (self->priv->widget_alias, "focus-out-event",
609         G_CALLBACK (contact_widget_entry_alias_focus_event_cb),
610         self);
611
612   /* Make return activate the window default (the Close button) */
613   gtk_entry_set_activates_default (GTK_ENTRY (self->priv->widget_alias),
614       TRUE);
615
616   gtk_grid_attach (GTK_GRID (self->priv->grid_contact),
617       self->priv->widget_alias, 2, 2, 1, 1);
618   gtk_widget_set_hexpand (self->priv->widget_alias, TRUE);
619
620   gtk_label_set_selectable (GTK_LABEL (self->priv->label_status), FALSE);
621   gtk_widget_show (self->priv->widget_alias);
622 }
623
624 static void
625 empathy_contact_widget_finalize (GObject *object)
626 {
627   EmpathyContactWidget *self = EMPATHY_CONTACT_WIDGET (object);
628   void (*chain_up) (GObject *) =
629       ((GObjectClass *) empathy_contact_widget_parent_class)->finalize;
630
631   contact_widget_remove_contact (self);
632
633   if (self->priv->widget_id_timeout != 0)
634     {
635       g_source_remove (self->priv->widget_id_timeout);
636     }
637
638
639   if (chain_up != NULL)
640     chain_up (object);
641 }
642
643 /**
644  * empathy_contact_widget_new:
645  * @contact: an #EmpathyContact
646  *
647  * Creates a new #EmpathyContactWidget.
648  *
649  * Return value: a new #EmpathyContactWidget
650  */
651 GtkWidget *
652 empathy_contact_widget_new (EmpathyContact *contact)
653 {
654   EmpathyContactWidget *self;
655   gchar *filename;
656   GtkWidget *main_vbox;
657   GtkBuilder *gui;
658
659   g_return_val_if_fail (contact == NULL || EMPATHY_IS_CONTACT (contact), NULL);
660
661   self = g_object_new (EMPATHY_TYPE_CONTACT_WIDGET, NULL);
662
663   filename = empathy_file_lookup ("empathy-contact-widget.ui",
664       "libempathy-gtk");
665   gui = tpaw_builder_get_file (filename,
666        "vbox_contact_widget", &main_vbox,
667        "hbox_presence", &self->priv->hbox_presence,
668        "label_alias", &self->priv->label_alias,
669        "image_state", &self->priv->image_state,
670        "grid_contact", &self->priv->grid_contact,
671        "vbox_avatar", &self->priv->vbox_avatar,
672        "groups_widget", &self->priv->groups_widget,
673        "vbox_client", &self->priv->vbox_client,
674        "grid_client", &self->priv->grid_client,
675        "hbox_client_requested", &self->priv->hbox_client_requested,
676        "label_details", &self->priv->label_details,
677        "label_left_account", &self->priv->label_left_account,
678        NULL);
679   g_free (filename);
680
681   gtk_container_add (GTK_CONTAINER (self), main_vbox);
682   gtk_widget_show (GTK_WIDGET (main_vbox));
683
684   /* Create widgets */
685   contact_widget_contact_setup (self);
686   contact_widget_client_setup (self);
687
688   gtk_widget_hide (self->priv->label_details);
689
690   if (contact != NULL)
691     contact_widget_set_contact (self, contact);
692   else
693     contact_widget_change_contact (self);
694
695   g_object_unref (gui);
696
697   return GTK_WIDGET (self);
698 }
699
700 /**
701  * empathy_contact_widget_get_contact:
702  * @widget: an #EmpathyContactWidget
703  *
704  * Get the #EmpathyContact related with the #EmpathyContactWidget @widget.
705  *
706  * Returns: the #EmpathyContact associated with @widget
707  */
708 EmpathyContact *
709 empathy_contact_widget_get_contact (GtkWidget *widget)
710 {
711   EmpathyContactWidget *self = EMPATHY_CONTACT_WIDGET (widget);
712
713   return self->priv->contact;
714 }
715
716 const gchar *
717 empathy_contact_widget_get_alias (GtkWidget *widget)
718 {
719   EmpathyContactWidget *self = EMPATHY_CONTACT_WIDGET (widget);
720
721   return gtk_entry_get_text (GTK_ENTRY (self->priv->widget_alias));
722 }
723
724 /**
725  * empathy_contact_widget_set_contact:
726  * @widget: an #EmpathyContactWidget
727  * @contact: a different #EmpathyContact
728  *
729  * Change the #EmpathyContact related with the #EmpathyContactWidget @widget.
730  */
731 void
732 empathy_contact_widget_set_contact (GtkWidget *widget,
733                                     EmpathyContact *contact)
734 {
735   EmpathyContactWidget *self = EMPATHY_CONTACT_WIDGET (widget);
736
737   g_return_if_fail (EMPATHY_IS_CONTACT (contact));
738
739   contact_widget_set_contact (self, contact);
740 }
741
742 /**
743  * empathy_contact_widget_set_account_filter:
744  * @widget: an #EmpathyContactWidget
745  * @filter: a #EmpathyAccountChooserFilterFunc
746  * @user_data: user data to pass to @filter, or %NULL
747  *
748  * Set a filter on the #EmpathyAccountChooser included in the
749  * #EmpathyContactWidget.
750  */
751 void
752 empathy_contact_widget_set_account_filter (
753     GtkWidget *widget,
754     EmpathyAccountChooserFilterFunc filter,
755     gpointer user_data)
756 {
757   EmpathyContactWidget *self = EMPATHY_CONTACT_WIDGET (widget);
758   EmpathyAccountChooser *chooser;
759
760   chooser = EMPATHY_ACCOUNT_CHOOSER (self->priv->widget_account);
761   if (chooser)
762       empathy_account_chooser_set_filter (chooser, filter, user_data);
763 }
764
765 static void
766 empathy_contact_widget_class_init (
767     EmpathyContactWidgetClass *klass)
768 {
769   GObjectClass *oclass = G_OBJECT_CLASS (klass);
770
771   oclass->finalize = empathy_contact_widget_finalize;
772
773   g_type_class_add_private (klass, sizeof (EmpathyContactWidgetPriv));
774 }
775
776 static void
777 empathy_contact_widget_init (EmpathyContactWidget *self)
778 {
779   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
780       EMPATHY_TYPE_CONTACT_WIDGET, EmpathyContactWidgetPriv);
781 }