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