]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-contact-widget.c
Rename all filenames starting with "gossip" by "empathy", change namespace
[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 Collabora Ltd.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program 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  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public
16  * License along with this program; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Authors: Xavier Claessens <xclaesse@gmail.com>
21  */
22
23 #include <config.h>
24
25 #include <string.h>
26 #include <stdlib.h>
27
28 #include <gtk/gtk.h>
29 #include <glade/glade.h>
30 #include <glib/gi18n.h>
31
32 #include <libmissioncontrol/mc-account.h>
33
34 #include <libempathy/empathy-contact-manager.h>
35
36 #include "empathy-contact-widget.h"
37 #include "empathy-account-chooser.h"
38 #include "empathy-ui-utils.h"
39
40 typedef struct {
41         EmpathyContact   *contact;
42         gboolean         is_user;
43         gboolean         editable;
44         gboolean         can_change_contact;
45         GtkCellRenderer *renderer;
46
47         GtkWidget       *vbox_contact_widget;
48
49         /* Contact */
50         GtkWidget       *vbox_contact;
51         GtkWidget       *widget_avatar;
52         GtkWidget       *widget_account;
53         GtkWidget       *widget_id;
54         GtkWidget       *widget_alias;
55         GtkWidget       *label_alias;
56         GtkWidget       *entry_alias;
57         GtkWidget       *hbox_presence;
58         GtkWidget       *image_state;
59         GtkWidget       *label_status;
60         GtkWidget       *table_contact;
61         GtkWidget       *hbox_contact;
62
63         /* Groups */
64         GtkWidget       *vbox_groups;
65         GtkWidget       *entry_group;
66         GtkWidget       *button_group;
67         GtkWidget       *treeview_groups;
68
69         /* Details */
70         GtkWidget       *vbox_details;
71         GtkWidget       *table_details;
72         GtkWidget       *hbox_details_requested;
73
74         /* Client */
75         GtkWidget       *vbox_client;
76         GtkWidget       *table_client;
77         GtkWidget       *hbow_client_requested;
78
79 } EmpathyContactWidget;
80
81 typedef struct {
82         EmpathyContactWidget *information;
83         const gchar          *name;
84         gboolean              found;
85         GtkTreeIter           found_iter;
86 } FindName;
87
88 static void     contact_widget_destroy_cb                 (GtkWidget             *widget,
89                                                            EmpathyContactWidget  *information);
90 static void     contact_widget_remove_contact             (EmpathyContactWidget  *information);
91 static void     contact_widget_set_contact                (EmpathyContactWidget  *information,
92                                                            EmpathyContact         *contact);
93 static void     contact_widget_contact_setup              (EmpathyContactWidget  *information);
94 static void     contact_widget_contact_update             (EmpathyContactWidget  *information);
95 static gboolean contact_widget_update_contact             (EmpathyContactWidget  *information);
96 static void     contact_widget_account_changed_cb         (GtkComboBox           *widget,
97                                                            EmpathyContactWidget  *information);
98 static gboolean contact_widget_id_focus_out_cb            (GtkWidget             *widget,
99                                                            GdkEventFocus         *event,
100                                                            EmpathyContactWidget  *information);
101 static gboolean contact_widget_entry_alias_focus_event_cb (GtkEditable           *editable,
102                                                            GdkEventFocus         *event,
103                                                            EmpathyContactWidget  *information);
104 static void     contact_widget_name_notify_cb             (EmpathyContactWidget  *information);
105 static void     contact_widget_presence_notify_cb         (EmpathyContactWidget  *information);
106 static void     contact_widget_avatar_notify_cb           (EmpathyContactWidget  *information);
107 static void     contact_widget_groups_setup               (EmpathyContactWidget  *information);
108 static void     contact_widget_groups_update              (EmpathyContactWidget  *information);
109 static void     contact_widget_model_setup                (EmpathyContactWidget  *information);
110 static void     contact_widget_model_populate_columns     (EmpathyContactWidget  *information);
111 static void     contact_widget_groups_populate_data       (EmpathyContactWidget  *information);
112 static void     contact_widget_groups_notify_cb           (EmpathyContactWidget  *information);
113 static gboolean contact_widget_model_find_name            (EmpathyContactWidget  *information,
114                                                            const gchar           *name,
115                                                            GtkTreeIter           *iter);
116 static gboolean contact_widget_model_find_name_foreach    (GtkTreeModel          *model,
117                                                            GtkTreePath           *path,
118                                                            GtkTreeIter           *iter,
119                                                            FindName              *data);
120 static void     contact_widget_cell_toggled               (GtkCellRendererToggle *cell,
121                                                            gchar                 *path_string,
122                                                            EmpathyContactWidget  *information);
123 static void     contact_widget_entry_group_changed_cb     (GtkEditable           *editable,
124                                                            EmpathyContactWidget  *information);
125 static void     contact_widget_entry_group_activate_cb    (GtkEntry              *entry,
126                                                            EmpathyContactWidget  *information);
127 static void     contact_widget_button_group_clicked_cb    (GtkButton             *button,
128                                                            EmpathyContactWidget  *information);
129 static void     contact_widget_details_setup              (EmpathyContactWidget  *information);
130 static void     contact_widget_details_update             (EmpathyContactWidget  *information);
131 static void     contact_widget_client_setup               (EmpathyContactWidget  *information);
132 static void     contact_widget_client_update              (EmpathyContactWidget  *information);
133
134 enum {
135         COL_NAME,
136         COL_ENABLED,
137         COL_EDITABLE,
138         COL_COUNT
139 };
140
141 GtkWidget *
142 empathy_contact_widget_new (EmpathyContact *contact,
143                             gboolean       editable)
144 {
145         EmpathyContactWidget *information;
146         GladeXML             *glade;
147
148         information = g_slice_new0 (EmpathyContactWidget);
149         information->editable = editable;
150         if (contact) {
151                 information->is_user = empathy_contact_is_user (contact);
152                 information->can_change_contact = FALSE;
153         } else {
154                 information->is_user = FALSE;
155                 information->can_change_contact = TRUE;
156         }
157
158         glade = empathy_glade_get_file ("empathy-contact-widget.glade",
159                                        "vbox_contact_widget",
160                                        NULL,
161                                        "vbox_contact_widget", &information->vbox_contact_widget,
162                                        "vbox_contact", &information->vbox_contact,
163                                        "hbox_presence", &information->hbox_presence,
164                                        "label_alias", &information->label_alias,
165                                        "image_state", &information->image_state,
166                                        "label_status", &information->label_status,
167                                        "table_contact", &information->table_contact,
168                                        "hbox_contact", &information->hbox_contact,
169                                        "vbox_groups", &information->vbox_groups,
170                                        "entry_group", &information->entry_group,
171                                        "button_group", &information->button_group,
172                                        "treeview_groups", &information->treeview_groups,
173                                        "vbox_details", &information->vbox_details,
174                                        "table_details", &information->table_details,
175                                        "hbox_details_requested", &information->hbox_details_requested,
176                                        "vbox_client", &information->vbox_client,
177                                        "table_client", &information->table_client,
178                                        "hbox_client_requested", &information->hbow_client_requested,
179                                        NULL);
180
181         empathy_glade_connect (glade,
182                               information,
183                               "vbox_contact_widget", "destroy", contact_widget_destroy_cb,
184                               "entry_group", "changed", contact_widget_entry_group_changed_cb,
185                               "entry_group", "activate", contact_widget_entry_group_activate_cb,
186                               "button_group", "clicked", contact_widget_button_group_clicked_cb,
187                               NULL);
188
189         g_object_unref (glade);
190
191         g_object_set_data (G_OBJECT (information->vbox_contact_widget),
192                            "EmpathyContactWidget",
193                            information);
194
195         /* Create widgets */
196         contact_widget_contact_setup (information);
197         contact_widget_groups_setup (information);
198         contact_widget_details_setup (information);
199         contact_widget_client_setup (information);
200
201         contact_widget_set_contact (information, contact);
202
203         gtk_widget_show (information->vbox_contact_widget);
204
205         return information->vbox_contact_widget;
206 }
207
208 EmpathyContact *
209 empathy_contact_widget_get_contact (GtkWidget *widget)
210 {
211         EmpathyContactWidget *information;
212
213         g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
214
215         information = g_object_get_data (G_OBJECT (widget), "EmpathyContactWidget");
216         if (!information) {
217                 return NULL;
218         }
219
220         return information->contact;
221 }
222         
223 static void
224 contact_widget_destroy_cb (GtkWidget            *widget,
225                            EmpathyContactWidget *information)
226 {
227         contact_widget_remove_contact (information);
228         g_slice_free (EmpathyContactWidget, information);
229 }
230
231 static void
232 contact_widget_remove_contact (EmpathyContactWidget *information)
233 {
234         if (information->contact) {
235                 g_signal_handlers_disconnect_by_func (information->contact,
236                                                       contact_widget_name_notify_cb,
237                                                       information);
238                 g_signal_handlers_disconnect_by_func (information->contact,
239                                                       contact_widget_presence_notify_cb,
240                                                       information);
241                 g_signal_handlers_disconnect_by_func (information->contact,
242                                                       contact_widget_avatar_notify_cb,
243                                                       information);
244                 g_signal_handlers_disconnect_by_func (information->contact,
245                                                       contact_widget_groups_notify_cb,
246                                                       information);
247
248                 g_object_unref (information->contact);
249                 information->contact = NULL;
250         }
251 }
252
253 static void
254 contact_widget_set_contact (EmpathyContactWidget *information,
255                             EmpathyContact        *contact)
256 {
257         contact_widget_remove_contact (information);
258         if (contact) {
259                 information->contact = g_object_ref (contact);
260         }
261
262         /* Update information for widgets */
263         contact_widget_contact_update (information);
264         contact_widget_groups_update (information);
265         contact_widget_details_update (information);
266         contact_widget_client_update (information);
267 }
268
269 static void
270 contact_widget_contact_setup (EmpathyContactWidget *information)
271 {
272         /* FIXME: Use EmpathyAvatarImage if (editable && is_user)  */
273         information->widget_avatar = gtk_image_new ();
274         gtk_box_pack_end (GTK_BOX (information->hbox_contact),
275                           information->widget_avatar,
276                           FALSE, FALSE,
277                           6);
278
279         /* Setup account label/chooser */
280         if (information->can_change_contact) {
281                 information->widget_account = empathy_account_chooser_new ();
282                 g_signal_connect (information->widget_account, "changed",
283                                   G_CALLBACK (contact_widget_account_changed_cb),
284                                   information);
285         } else {
286                 information->widget_account = gtk_label_new (NULL);
287                 gtk_label_set_selectable (GTK_LABEL (information->widget_account), TRUE);
288         }
289         gtk_table_attach_defaults (GTK_TABLE (information->table_contact),
290                                    information->widget_account,
291                                    1, 2, 0, 1);
292         gtk_widget_show (information->widget_account);
293
294         /* Setup id label/entry */
295         if (information->can_change_contact) {
296                 information->widget_id = gtk_entry_new ();
297                 g_signal_connect (information->widget_id, "focus-out-event",
298                                   G_CALLBACK (contact_widget_id_focus_out_cb),
299                                   information);
300         } else {
301                 information->widget_id = gtk_label_new (NULL);
302                 gtk_label_set_selectable (GTK_LABEL (information->widget_id), TRUE);
303         }
304         gtk_table_attach_defaults (GTK_TABLE (information->table_contact),
305                                    information->widget_id,
306                                    1, 2, 1, 2);
307         gtk_widget_show (information->widget_id);
308
309         /* Setup alias label/entry */
310         if (information->editable) {
311                 information->widget_alias = gtk_entry_new ();
312                 g_signal_connect (information->widget_alias, "focus-out-event",
313                                   G_CALLBACK (contact_widget_entry_alias_focus_event_cb),
314                                   information);
315         } else {
316                 information->widget_alias = gtk_label_new (NULL);
317                 gtk_label_set_selectable (GTK_LABEL (information->widget_alias), TRUE);
318         }
319         gtk_table_attach_defaults (GTK_TABLE (information->table_contact),
320                                    information->widget_alias,
321                                    1, 2, 2, 3);
322         gtk_widget_show (information->widget_alias);
323 }
324
325 static void
326 contact_widget_contact_update (EmpathyContactWidget *information)
327 {
328         McAccount   *account = NULL;
329         const gchar *id = NULL;
330
331         /* Connect and get info from new contact */
332         if (information->contact) {
333                 g_signal_connect_swapped (information->contact, "notify::name",
334                                           G_CALLBACK (contact_widget_name_notify_cb),
335                                           information);
336                 g_signal_connect_swapped (information->contact, "notify::presence",
337                                           G_CALLBACK (contact_widget_presence_notify_cb),
338                                           information);
339                 g_signal_connect_swapped (information->contact, "notify::avatar",
340                                           G_CALLBACK (contact_widget_avatar_notify_cb),
341                                           information);
342
343                 account = empathy_contact_get_account (information->contact);
344                 id = empathy_contact_get_id (information->contact);
345         }
346
347         /* Update account widget */
348         if (information->can_change_contact) {
349                 if (account) {
350                         g_signal_handlers_block_by_func (information->widget_account,
351                                                          contact_widget_account_changed_cb,
352                                                          information);
353                         empathy_account_chooser_set_account (EMPATHY_ACCOUNT_CHOOSER (information->widget_account),
354                                                             account);
355                         g_signal_handlers_unblock_by_func (information->widget_account,
356                                                            contact_widget_account_changed_cb,
357                                                            information);
358                 }
359         }
360         else if (account) {
361                 const gchar *name;
362
363                 name = mc_account_get_display_name (account);
364                 gtk_label_set_label (GTK_LABEL (information->widget_account), name);
365         }
366
367         /* Update id widget */
368         if (information->can_change_contact) {
369                 if (!G_STR_EMPTY (id)) {
370                         gtk_entry_set_text (GTK_ENTRY (information->widget_id), id);
371                 }
372         } else {
373                 gtk_label_set_label (GTK_LABEL (information->widget_id), id);
374         }
375
376         /* Update other widgets */
377         if (information->contact) {
378                 contact_widget_name_notify_cb (information);
379                 contact_widget_presence_notify_cb (information);
380                 contact_widget_avatar_notify_cb (information);
381
382                 gtk_widget_show (information->label_alias);
383                 gtk_widget_show (information->widget_alias);
384                 gtk_widget_show (information->hbox_presence);
385         } else {
386                 gtk_widget_hide (information->label_alias);
387                 gtk_widget_hide (information->widget_alias);
388                 gtk_widget_hide (information->hbox_presence);
389                 gtk_widget_hide (information->widget_avatar);
390         }
391 }
392
393 static gboolean
394 contact_widget_update_contact (EmpathyContactWidget *information)
395 {
396         McAccount   *account;
397         const gchar *id;
398
399         account = empathy_account_chooser_get_account (EMPATHY_ACCOUNT_CHOOSER (information->widget_account));
400         id = gtk_entry_get_text (GTK_ENTRY (information->widget_id));
401
402         if (account && !G_STR_EMPTY (id)) {
403                 EmpathyContactManager *manager;
404                 EmpathyContact         *contact;
405
406                 manager = empathy_contact_manager_new ();
407                 contact = empathy_contact_manager_create (manager, account, id);
408                 contact_widget_set_contact (information, contact);
409
410                 if (contact) {
411                         g_object_unref (contact);
412                 }
413                 g_object_unref (manager);
414         }
415
416         return FALSE;
417 }
418
419 static void
420 contact_widget_account_changed_cb (GtkComboBox          *widget,
421                                    EmpathyContactWidget *information)
422 {
423         contact_widget_update_contact (information);
424 }
425
426 static gboolean
427 contact_widget_id_focus_out_cb (GtkWidget            *widget,
428                                 GdkEventFocus        *event,
429                                 EmpathyContactWidget *information)
430 {
431         contact_widget_update_contact (information);
432         return FALSE;
433 }
434
435 static gboolean
436 contact_widget_entry_alias_focus_event_cb (GtkEditable          *editable,
437                                            GdkEventFocus        *event,
438                                            EmpathyContactWidget *information)
439 {
440         if (information->contact) {
441                 const gchar *name;
442
443                 name = gtk_entry_get_text (GTK_ENTRY (editable));
444                 empathy_contact_set_name (information->contact, name);
445         }
446
447         return FALSE;
448 }
449
450 static void
451 contact_widget_name_notify_cb (EmpathyContactWidget *information)
452 {
453         if (information->editable) {
454                 gtk_entry_set_text (GTK_ENTRY (information->widget_alias),
455                                     empathy_contact_get_name (information->contact));
456         } else {
457                 gtk_label_set_label (GTK_LABEL (information->widget_alias),
458                                      empathy_contact_get_name (information->contact));
459         }
460 }
461
462 static void
463 contact_widget_presence_notify_cb (EmpathyContactWidget *information)
464 {
465         gtk_label_set_text (GTK_LABEL (information->label_status),
466                             empathy_contact_get_status (information->contact));
467         gtk_image_set_from_icon_name (GTK_IMAGE (information->image_state),
468                                       empathy_icon_name_for_contact (information->contact),
469                                       GTK_ICON_SIZE_BUTTON);
470
471 }
472
473 static void
474 contact_widget_avatar_notify_cb (EmpathyContactWidget *information)
475 {
476         GdkPixbuf *avatar_pixbuf;
477
478         avatar_pixbuf = empathy_pixbuf_avatar_from_contact_scaled (information->contact,
479                                                                   48, 48);
480
481         if (avatar_pixbuf) {
482                 gtk_image_set_from_pixbuf (GTK_IMAGE (information->widget_avatar),
483                                            avatar_pixbuf);
484                 gtk_widget_show  (information->widget_avatar);
485                 g_object_unref (avatar_pixbuf);
486         } else {
487                 gtk_widget_hide  (information->widget_avatar);
488         }
489 }
490
491 static void
492 contact_widget_groups_setup (EmpathyContactWidget *information)
493 {
494         if (information->editable) {
495                 contact_widget_model_setup (information);
496         }
497 }
498
499 static void
500 contact_widget_groups_update (EmpathyContactWidget *information)
501 {
502         if (information->editable && information->contact) {
503                 g_signal_connect_swapped (information->contact, "notify::groups",
504                                           G_CALLBACK (contact_widget_groups_notify_cb),
505                                           information);
506                 contact_widget_groups_populate_data (information);
507
508                 gtk_widget_show (information->vbox_groups);
509         } else {
510                 gtk_widget_hide (information->vbox_groups);
511         }
512 }
513
514 static void
515 contact_widget_model_setup (EmpathyContactWidget *information)
516 {
517         GtkTreeView      *view;
518         GtkListStore     *store;
519         GtkTreeSelection *selection;
520
521         view = GTK_TREE_VIEW (information->treeview_groups);
522
523         store = gtk_list_store_new (COL_COUNT,
524                                     G_TYPE_STRING,   /* name */
525                                     G_TYPE_BOOLEAN,  /* enabled */
526                                     G_TYPE_BOOLEAN); /* editable */
527
528         gtk_tree_view_set_model (view, GTK_TREE_MODEL (store));
529
530         selection = gtk_tree_view_get_selection (view);
531         gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
532
533         contact_widget_model_populate_columns (information);
534
535         gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
536                                               COL_NAME, GTK_SORT_ASCENDING);
537
538         g_object_unref (store);
539 }
540
541 static void
542 contact_widget_model_populate_columns (EmpathyContactWidget *information)
543 {
544         GtkTreeView       *view;
545         GtkTreeModel      *model;
546         GtkTreeViewColumn *column;
547         GtkCellRenderer   *renderer;
548         guint              col_offset;
549
550         view = GTK_TREE_VIEW (information->treeview_groups);
551         model = gtk_tree_view_get_model (view);
552
553         renderer = gtk_cell_renderer_toggle_new ();
554         g_signal_connect (renderer, "toggled",
555                           G_CALLBACK (contact_widget_cell_toggled),
556                           information);
557
558         column = gtk_tree_view_column_new_with_attributes (_("Select"), renderer,
559                                                            "active", COL_ENABLED,
560                                                            NULL);
561
562         gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
563         gtk_tree_view_column_set_fixed_width (column, 50);
564         gtk_tree_view_append_column (view, column);
565
566         renderer = gtk_cell_renderer_text_new ();
567         col_offset = gtk_tree_view_insert_column_with_attributes (view,
568                                                                   -1, _("Group"),
569                                                                   renderer,
570                                                                   "text", COL_NAME,
571                                                                   /* "editable", COL_EDITABLE, */
572                                                                   NULL);
573
574         g_object_set_data (G_OBJECT (renderer),
575                            "column", GINT_TO_POINTER (COL_NAME));
576
577         column = gtk_tree_view_get_column (view, col_offset - 1);
578         gtk_tree_view_column_set_sort_column_id (column, COL_NAME);
579         gtk_tree_view_column_set_resizable (column,FALSE);
580         gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
581
582         if (information->renderer) {
583                 g_object_unref (information->renderer);
584         }
585
586         information->renderer = g_object_ref (renderer);
587 }
588
589 static void
590 contact_widget_groups_populate_data (EmpathyContactWidget *information)
591 {
592         EmpathyContactManager *manager;
593         GtkTreeView           *view;
594         GtkListStore          *store;
595         GtkTreeIter            iter;
596         GList                 *my_groups, *l;
597         GList                 *all_groups;
598
599         view = GTK_TREE_VIEW (information->treeview_groups);
600         store = GTK_LIST_STORE (gtk_tree_view_get_model (view));
601         gtk_list_store_clear (store);
602
603         manager = empathy_contact_manager_new ();
604         all_groups = empathy_contact_manager_get_groups (manager);
605         my_groups = empathy_contact_get_groups (information->contact);
606         g_object_unref (manager);
607
608         for (l = all_groups; l; l = l->next) {
609                 const gchar *group_str;
610                 gboolean     enabled;
611
612                 group_str = l->data;
613
614                 enabled = g_list_find_custom (my_groups,
615                                               group_str,
616                                               (GCompareFunc) strcmp) != NULL;
617
618                 gtk_list_store_append (store, &iter);
619                 gtk_list_store_set (store, &iter,
620                                     COL_NAME, group_str,
621                                     COL_EDITABLE, TRUE,
622                                     COL_ENABLED, enabled,
623                                     -1);
624         }
625
626         g_list_free (all_groups);
627 }
628
629 static void
630 contact_widget_groups_notify_cb (EmpathyContactWidget *information)
631 {
632         /* FIXME: not implemented */
633 }
634
635 static gboolean
636 contact_widget_model_find_name (EmpathyContactWidget *information,
637                                 const gchar          *name,
638                                 GtkTreeIter          *iter)
639 {
640         GtkTreeView  *view;
641         GtkTreeModel *model;
642         FindName      data;
643
644         if (G_STR_EMPTY (name)) {
645                 return FALSE;
646         }
647
648         data.information = information;
649         data.name = name;
650         data.found = FALSE;
651
652         view = GTK_TREE_VIEW (information->treeview_groups);
653         model = gtk_tree_view_get_model (view);
654
655         gtk_tree_model_foreach (model,
656                                 (GtkTreeModelForeachFunc) contact_widget_model_find_name_foreach,
657                                 &data);
658
659         if (data.found == TRUE) {
660                 *iter = data.found_iter;
661                 return TRUE;
662         }
663
664         return FALSE;
665 }
666
667 static gboolean
668 contact_widget_model_find_name_foreach (GtkTreeModel *model,
669                                         GtkTreePath  *path,
670                                         GtkTreeIter  *iter,
671                                         FindName     *data)
672 {
673         gchar *name;
674
675         gtk_tree_model_get (model, iter,
676                             COL_NAME, &name,
677                             -1);
678
679         if (!name) {
680                 return FALSE;
681         }
682
683         if (data->name && strcmp (data->name, name) == 0) {
684                 data->found = TRUE;
685                 data->found_iter = *iter;
686
687                 g_free (name);
688
689                 return TRUE;
690         }
691
692         g_free (name);
693
694         return FALSE;
695 }
696
697 static void
698 contact_widget_cell_toggled (GtkCellRendererToggle *cell,
699                              gchar                 *path_string,
700                              EmpathyContactWidget  *information)
701 {
702         GtkTreeView  *view;
703         GtkTreeModel *model;
704         GtkListStore *store;
705         GtkTreePath  *path;
706         GtkTreeIter   iter;
707         gboolean      enabled;
708         gchar        *group;
709
710         view = GTK_TREE_VIEW (information->treeview_groups);
711         model = gtk_tree_view_get_model (view);
712         store = GTK_LIST_STORE (model);
713
714         path = gtk_tree_path_new_from_string (path_string);
715
716         gtk_tree_model_get_iter (model, &iter, path);
717         gtk_tree_model_get (model, &iter,
718                             COL_ENABLED, &enabled,
719                             COL_NAME, &group,
720                             -1);
721
722         gtk_list_store_set (store, &iter, COL_ENABLED, !enabled, -1);
723         gtk_tree_path_free (path);
724
725         if (group) {
726                 if (enabled) {
727                         empathy_contact_remove_group (information->contact, group);
728                 } else {
729                         empathy_contact_add_group (information->contact, group);        
730                 }
731
732                 g_free (group);
733         }
734 }
735
736 static void
737 contact_widget_entry_group_changed_cb (GtkEditable           *editable,
738                                        EmpathyContactWidget  *information)
739 {
740         GtkTreeIter  iter;
741         const gchar *group;
742
743         group = gtk_entry_get_text (GTK_ENTRY (information->entry_group));
744
745         if (contact_widget_model_find_name (information, group, &iter)) {
746                 gtk_widget_set_sensitive (GTK_WIDGET (information->button_group), FALSE);
747
748         } else {
749                 gtk_widget_set_sensitive (GTK_WIDGET (information->button_group),
750                                           !G_STR_EMPTY (group));
751         }
752 }
753
754 static void
755 contact_widget_entry_group_activate_cb (GtkEntry              *entry,
756                                         EmpathyContactWidget  *information)
757 {
758         gtk_widget_activate (GTK_WIDGET (information->button_group));
759 }
760
761 static void
762 contact_widget_button_group_clicked_cb (GtkButton             *button,
763                                         EmpathyContactWidget  *information)
764 {
765         GtkTreeView  *view;
766         GtkListStore *store;
767         GtkTreeIter   iter;
768         const gchar  *group;
769
770         view = GTK_TREE_VIEW (information->treeview_groups);
771         store = GTK_LIST_STORE (gtk_tree_view_get_model (view));
772
773         group = gtk_entry_get_text (GTK_ENTRY (information->entry_group));
774
775         gtk_list_store_append (store, &iter);
776         gtk_list_store_set (store, &iter,
777                             COL_NAME, group,
778                             COL_ENABLED, TRUE,
779                             -1);
780
781         empathy_contact_add_group (information->contact, group);
782 }
783
784 static void
785 contact_widget_details_setup (EmpathyContactWidget *information)
786 {
787         /* FIXME: Needs new telepathy spec */
788         gtk_widget_hide (information->vbox_details);
789 }
790
791 static void
792 contact_widget_details_update (EmpathyContactWidget *information)
793 {
794         /* FIXME: Needs new telepathy spec */
795 }
796
797 static void
798 contact_widget_client_setup (EmpathyContactWidget *information)
799 {
800         /* FIXME: Needs new telepathy spec */
801         gtk_widget_hide (information->vbox_client);
802 }
803
804 static void
805 contact_widget_client_update (EmpathyContactWidget *information)
806 {
807         /* FIXME: Needs new telepathy spec */
808 }
809