set unsensitive the add button if there is no profile installed and tell
[empathy-mirror.git] / libempathy-gtk / empathy-contact-widget.c
blob34a8023fe74967efb6a715945873f7a7e25993b5
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * Copyright (C) 2007 Collabora Ltd.
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.
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.
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.
20 * Authors: Xavier Claessens <xclaesse@gmail.com>
23 #include <config.h>
25 #include <string.h>
26 #include <stdlib.h>
28 #include <gtk/gtk.h>
29 #include <glade/glade.h>
30 #include <glib/gi18n.h>
32 #include <libmissioncontrol/mc-account.h>
34 #include <libempathy/empathy-contact-factory.h>
35 #include <libempathy/empathy-contact-manager.h>
36 #include <libempathy/empathy-contact-list.h>
37 #include <libempathy/empathy-utils.h>
39 #include "empathy-contact-widget.h"
40 #include "empathy-account-chooser.h"
41 #include "empathy-avatar-chooser.h"
42 #include "empathy-avatar-image.h"
43 #include "empathy-ui-utils.h"
45 /* Delay before updating the widget when the id entry changed (seconds) */
46 #define ID_CHANGED_TIMEOUT 1
48 typedef struct {
49 EmpathyContactFactory *factory;
50 EmpathyContactManager *manager;
51 EmpathyContact *contact;
52 EmpathyContactWidgetFlags flags;
53 GtkCellRenderer *renderer;
54 guint widget_id_timeout;
56 GtkWidget *vbox_contact_widget;
58 /* Contact */
59 GtkWidget *vbox_contact;
60 GtkWidget *widget_avatar;
61 GtkWidget *widget_account;
62 GtkWidget *widget_id;
63 GtkWidget *widget_alias;
64 GtkWidget *label_alias;
65 GtkWidget *entry_alias;
66 GtkWidget *hbox_presence;
67 GtkWidget *image_state;
68 GtkWidget *label_status;
69 GtkWidget *table_contact;
70 GtkWidget *vbox_avatar;
72 /* Groups */
73 GtkWidget *vbox_groups;
74 GtkWidget *entry_group;
75 GtkWidget *button_group;
76 GtkWidget *treeview_groups;
78 /* Details */
79 GtkWidget *vbox_details;
80 GtkWidget *table_details;
81 GtkWidget *hbox_details_requested;
83 /* Client */
84 GtkWidget *vbox_client;
85 GtkWidget *table_client;
86 GtkWidget *hbow_client_requested;
87 } EmpathyContactWidget;
89 typedef struct {
90 EmpathyContactWidget *information;
91 const gchar *name;
92 gboolean found;
93 GtkTreeIter found_iter;
94 } FindName;
96 static void contact_widget_destroy_cb (GtkWidget *widget,
97 EmpathyContactWidget *information);
98 static void contact_widget_remove_contact (EmpathyContactWidget *information);
99 static void contact_widget_set_contact (EmpathyContactWidget *information,
100 EmpathyContact *contact);
101 static void contact_widget_contact_setup (EmpathyContactWidget *information);
102 static void contact_widget_contact_update (EmpathyContactWidget *information);
103 static void contact_widget_change_contact (EmpathyContactWidget *information);
104 static void contact_widget_avatar_changed_cb (EmpathyAvatarChooser *chooser,
105 EmpathyContactWidget *information);
106 static void contact_widget_account_changed_cb (GtkComboBox *widget,
107 EmpathyContactWidget *information);
108 static gboolean contact_widget_id_focus_out_cb (GtkWidget *widget,
109 GdkEventFocus *event,
110 EmpathyContactWidget *information);
111 static gboolean contact_widget_entry_alias_focus_event_cb (GtkEditable *editable,
112 GdkEventFocus *event,
113 EmpathyContactWidget *information);
114 static void contact_widget_name_notify_cb (EmpathyContactWidget *information);
115 static void contact_widget_presence_notify_cb (EmpathyContactWidget *information);
116 static void contact_widget_avatar_notify_cb (EmpathyContactWidget *information);
117 static void contact_widget_groups_setup (EmpathyContactWidget *information);
118 static void contact_widget_groups_update (EmpathyContactWidget *information);
119 static void contact_widget_model_setup (EmpathyContactWidget *information);
120 static void contact_widget_model_populate_columns (EmpathyContactWidget *information);
121 static void contact_widget_groups_populate_data (EmpathyContactWidget *information);
122 static void contact_widget_groups_notify_cb (EmpathyContactWidget *information);
123 static gboolean contact_widget_model_find_name (EmpathyContactWidget *information,
124 const gchar *name,
125 GtkTreeIter *iter);
126 static gboolean contact_widget_model_find_name_foreach (GtkTreeModel *model,
127 GtkTreePath *path,
128 GtkTreeIter *iter,
129 FindName *data);
130 static void contact_widget_cell_toggled (GtkCellRendererToggle *cell,
131 gchar *path_string,
132 EmpathyContactWidget *information);
133 static void contact_widget_entry_group_changed_cb (GtkEditable *editable,
134 EmpathyContactWidget *information);
135 static void contact_widget_entry_group_activate_cb (GtkEntry *entry,
136 EmpathyContactWidget *information);
137 static void contact_widget_button_group_clicked_cb (GtkButton *button,
138 EmpathyContactWidget *information);
139 static void contact_widget_details_setup (EmpathyContactWidget *information);
140 static void contact_widget_details_update (EmpathyContactWidget *information);
141 static void contact_widget_client_setup (EmpathyContactWidget *information);
142 static void contact_widget_client_update (EmpathyContactWidget *information);
144 enum {
145 COL_NAME,
146 COL_ENABLED,
147 COL_EDITABLE,
148 COL_COUNT
151 GtkWidget *
152 empathy_contact_widget_new (EmpathyContact *contact,
153 EmpathyContactWidgetFlags flags)
155 EmpathyContactWidget *information;
156 GladeXML *glade;
158 information = g_slice_new0 (EmpathyContactWidget);
159 information->flags = flags;
160 information->factory = empathy_contact_factory_new ();
162 glade = empathy_glade_get_file ("empathy-contact-widget.glade",
163 "vbox_contact_widget",
164 NULL,
165 "vbox_contact_widget", &information->vbox_contact_widget,
166 "vbox_contact", &information->vbox_contact,
167 "hbox_presence", &information->hbox_presence,
168 "label_alias", &information->label_alias,
169 "image_state", &information->image_state,
170 "label_status", &information->label_status,
171 "table_contact", &information->table_contact,
172 "vbox_avatar", &information->vbox_avatar,
173 "vbox_groups", &information->vbox_groups,
174 "entry_group", &information->entry_group,
175 "button_group", &information->button_group,
176 "treeview_groups", &information->treeview_groups,
177 "vbox_details", &information->vbox_details,
178 "table_details", &information->table_details,
179 "hbox_details_requested", &information->hbox_details_requested,
180 "vbox_client", &information->vbox_client,
181 "table_client", &information->table_client,
182 "hbox_client_requested", &information->hbow_client_requested,
183 NULL);
185 empathy_glade_connect (glade,
186 information,
187 "vbox_contact_widget", "destroy", contact_widget_destroy_cb,
188 "entry_group", "changed", contact_widget_entry_group_changed_cb,
189 "entry_group", "activate", contact_widget_entry_group_activate_cb,
190 "button_group", "clicked", contact_widget_button_group_clicked_cb,
191 NULL);
193 g_object_unref (glade);
195 g_object_set_data (G_OBJECT (information->vbox_contact_widget),
196 "EmpathyContactWidget",
197 information);
199 /* Create widgets */
200 contact_widget_contact_setup (information);
201 contact_widget_groups_setup (information);
202 contact_widget_details_setup (information);
203 contact_widget_client_setup (information);
205 contact_widget_set_contact (information, contact);
207 gtk_widget_show (information->vbox_contact_widget);
209 return information->vbox_contact_widget;
212 EmpathyContact *
213 empathy_contact_widget_get_contact (GtkWidget *widget)
215 EmpathyContactWidget *information;
217 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
219 information = g_object_get_data (G_OBJECT (widget), "EmpathyContactWidget");
220 if (!information) {
221 return NULL;
224 return information->contact;
227 static void
228 contact_widget_destroy_cb (GtkWidget *widget,
229 EmpathyContactWidget *information)
231 contact_widget_remove_contact (information);
233 if (information->widget_id_timeout != 0) {
234 g_source_remove (information->widget_id_timeout);
236 if (information->factory) {
237 g_object_unref (information->factory);
239 if (information->manager) {
240 g_object_unref (information->manager);
243 g_slice_free (EmpathyContactWidget, information);
246 static void
247 contact_widget_remove_contact (EmpathyContactWidget *information)
249 if (information->contact) {
250 g_signal_handlers_disconnect_by_func (information->contact,
251 contact_widget_name_notify_cb,
252 information);
253 g_signal_handlers_disconnect_by_func (information->contact,
254 contact_widget_presence_notify_cb,
255 information);
256 g_signal_handlers_disconnect_by_func (information->contact,
257 contact_widget_avatar_notify_cb,
258 information);
259 g_signal_handlers_disconnect_by_func (information->contact,
260 contact_widget_groups_notify_cb,
261 information);
263 g_object_unref (information->contact);
264 information->contact = NULL;
268 static void
269 contact_widget_set_contact (EmpathyContactWidget *information,
270 EmpathyContact *contact)
272 contact_widget_remove_contact (information);
273 if (contact) {
274 information->contact = g_object_ref (contact);
277 /* Update information for widgets */
278 contact_widget_contact_update (information);
279 contact_widget_groups_update (information);
280 contact_widget_details_update (information);
281 contact_widget_client_update (information);
284 static gboolean
285 contact_widget_can_add_contact_to_account (McAccount *account,
286 gpointer user_data)
288 MissionControl *mc;
289 TpConn *tp_conn;
290 McProfile *profile;
291 const gchar *protocol_name;
293 mc = empathy_mission_control_new ();
294 tp_conn = mission_control_get_connection (mc, account, NULL);
295 g_object_unref (mc);
296 if (tp_conn == NULL) {
297 /* Account is disconnected */
298 return FALSE;
300 g_object_unref (tp_conn);
302 profile = mc_account_get_profile (account);
303 protocol_name = mc_profile_get_protocol_name (profile);
304 if (strcmp (protocol_name, "local-xmpp") == 0) {
305 /* We can't add accounts to a XMPP LL connection
306 * FIXME: We should inspect the flags of the contact list group interface
308 g_object_unref (profile);
309 return FALSE;
312 g_object_unref (profile);
313 return TRUE;
316 static gboolean
317 contact_widget_id_activate_timeout (EmpathyContactWidget *self)
319 contact_widget_change_contact (self);
320 return FALSE;
323 static void
324 contact_widget_id_changed_cb (GtkEntry *entry,
325 EmpathyContactWidget *self)
327 if (self->widget_id_timeout != 0) {
328 g_source_remove (self->widget_id_timeout);
331 self->widget_id_timeout =
332 g_timeout_add_seconds (ID_CHANGED_TIMEOUT,
333 (GSourceFunc) contact_widget_id_activate_timeout,
334 self);
337 static void
338 contact_widget_contact_setup (EmpathyContactWidget *information)
340 if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_AVATAR) {
341 information->widget_avatar = empathy_avatar_chooser_new ();
342 g_signal_connect (information->widget_avatar, "changed",
343 G_CALLBACK (contact_widget_avatar_changed_cb),
344 information);
345 } else {
346 information->widget_avatar = empathy_avatar_image_new ();
348 gtk_box_pack_start (GTK_BOX (information->vbox_avatar),
349 information->widget_avatar,
350 FALSE, FALSE,
352 gtk_widget_show (information->widget_avatar);
354 /* Setup account label/chooser */
355 if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ACCOUNT) {
356 information->widget_account = empathy_account_chooser_new ();
357 empathy_account_chooser_set_filter (
358 EMPATHY_ACCOUNT_CHOOSER (information->widget_account),
359 contact_widget_can_add_contact_to_account,
360 NULL);
362 g_signal_connect (information->widget_account, "changed",
363 G_CALLBACK (contact_widget_account_changed_cb),
364 information);
365 } else {
366 information->widget_account = gtk_label_new (NULL);
367 gtk_label_set_selectable (GTK_LABEL (information->widget_account), TRUE);
368 gtk_misc_set_alignment (GTK_MISC (information->widget_account), 0, 0.5);
370 gtk_table_attach_defaults (GTK_TABLE (information->table_contact),
371 information->widget_account,
372 1, 2, 0, 1);
373 gtk_widget_show (information->widget_account);
375 /* Setup id label/entry */
376 if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ID) {
377 information->widget_id = gtk_entry_new ();
378 g_signal_connect (information->widget_id, "focus-out-event",
379 G_CALLBACK (contact_widget_id_focus_out_cb),
380 information);
381 g_signal_connect (information->widget_id, "changed",
382 G_CALLBACK (contact_widget_id_changed_cb),
383 information);
384 } else {
385 information->widget_id = gtk_label_new (NULL);
386 gtk_label_set_selectable (GTK_LABEL (information->widget_id), TRUE);
387 gtk_misc_set_alignment (GTK_MISC (information->widget_id), 0, 0.5);
389 gtk_table_attach_defaults (GTK_TABLE (information->table_contact),
390 information->widget_id,
391 1, 2, 1, 2);
392 gtk_widget_show (information->widget_id);
394 /* Setup alias label/entry */
395 if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ALIAS) {
396 information->widget_alias = gtk_entry_new ();
397 g_signal_connect (information->widget_alias, "focus-out-event",
398 G_CALLBACK (contact_widget_entry_alias_focus_event_cb),
399 information);
400 } else {
401 information->widget_alias = gtk_label_new (NULL);
402 gtk_label_set_selectable (GTK_LABEL (information->widget_alias), TRUE);
403 gtk_misc_set_alignment (GTK_MISC (information->widget_alias), 0, 0.5);
405 gtk_table_attach_defaults (GTK_TABLE (information->table_contact),
406 information->widget_alias,
407 1, 2, 2, 3);
408 gtk_widget_show (information->widget_alias);
411 static void
412 contact_widget_contact_update (EmpathyContactWidget *information)
414 McAccount *account = NULL;
415 const gchar *id = NULL;
417 /* Connect and get info from new contact */
418 if (information->contact) {
419 g_signal_connect_swapped (information->contact, "notify::name",
420 G_CALLBACK (contact_widget_name_notify_cb),
421 information);
422 g_signal_connect_swapped (information->contact, "notify::presence",
423 G_CALLBACK (contact_widget_presence_notify_cb),
424 information);
425 g_signal_connect_swapped (information->contact, "notify::avatar",
426 G_CALLBACK (contact_widget_avatar_notify_cb),
427 information);
429 account = empathy_contact_get_account (information->contact);
430 id = empathy_contact_get_id (information->contact);
433 /* Update account widget */
434 if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ACCOUNT) {
435 if (account) {
436 g_signal_handlers_block_by_func (information->widget_account,
437 contact_widget_account_changed_cb,
438 information);
439 empathy_account_chooser_set_account (EMPATHY_ACCOUNT_CHOOSER (information->widget_account),
440 account);
441 g_signal_handlers_unblock_by_func (information->widget_account,
442 contact_widget_account_changed_cb,
443 information);
445 } else {
446 if (account) {
447 const gchar *name;
449 name = mc_account_get_display_name (account);
450 gtk_label_set_label (GTK_LABEL (information->widget_account), name);
454 /* Update id widget */
455 if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ID) {
456 gtk_entry_set_text (GTK_ENTRY (information->widget_id), id ? id : "");
457 } else {
458 gtk_label_set_label (GTK_LABEL (information->widget_id), id ? id : "");
460 /* Update other widgets */
461 if (information->contact) {
462 contact_widget_name_notify_cb (information);
463 contact_widget_presence_notify_cb (information);
464 contact_widget_avatar_notify_cb (information);
466 gtk_widget_show (information->label_alias);
467 gtk_widget_show (information->widget_alias);
468 gtk_widget_show (information->hbox_presence);
469 gtk_widget_show (information->widget_avatar);
470 } else {
471 gtk_widget_hide (information->label_alias);
472 gtk_widget_hide (information->widget_alias);
473 gtk_widget_hide (information->hbox_presence);
474 gtk_widget_hide (information->widget_avatar);
478 static void
479 contact_widget_change_contact (EmpathyContactWidget *information)
481 EmpathyContact *contact;
482 McAccount *account;
484 account = empathy_account_chooser_get_account (EMPATHY_ACCOUNT_CHOOSER (information->widget_account));
485 if (!account) {
486 return;
489 if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_ID) {
490 const gchar *id;
492 id = gtk_entry_get_text (GTK_ENTRY (information->widget_id));
493 if (G_STR_EMPTY (id)) {
494 return;
497 contact = empathy_contact_factory_get_from_id (information->factory,
498 account, id);
499 } else {
500 contact = empathy_contact_factory_get_user (information->factory,
501 account);
504 if (contact) {
505 contact_widget_set_contact (information, contact);
506 g_object_unref (contact);
510 static void
511 contact_widget_avatar_changed_cb (EmpathyAvatarChooser *chooser,
512 EmpathyContactWidget *information)
514 McAccount *account;
515 gchar *data;
516 gsize size;
518 account = empathy_contact_get_account (information->contact);
519 empathy_avatar_chooser_get_image_data (EMPATHY_AVATAR_CHOOSER (information->widget_avatar),
520 &data, &size);
521 mc_account_set_avatar_from_data (account, data, size, "png");
524 static void
525 contact_widget_account_changed_cb (GtkComboBox *widget,
526 EmpathyContactWidget *information)
528 contact_widget_change_contact (information);
531 static gboolean
532 contact_widget_id_focus_out_cb (GtkWidget *widget,
533 GdkEventFocus *event,
534 EmpathyContactWidget *information)
536 contact_widget_change_contact (information);
537 return FALSE;
540 static gboolean
541 contact_widget_entry_alias_focus_event_cb (GtkEditable *editable,
542 GdkEventFocus *event,
543 EmpathyContactWidget *information)
545 if (information->contact) {
546 const gchar *name;
548 name = gtk_entry_get_text (GTK_ENTRY (editable));
549 empathy_contact_factory_set_name (information->factory,
550 information->contact,
551 name);
554 return FALSE;
557 static void
558 contact_widget_name_notify_cb (EmpathyContactWidget *information)
560 if (GTK_IS_ENTRY (information->widget_alias)) {
561 gtk_entry_set_text (GTK_ENTRY (information->widget_alias),
562 empathy_contact_get_name (information->contact));
563 } else {
564 gtk_label_set_label (GTK_LABEL (information->widget_alias),
565 empathy_contact_get_name (information->contact));
569 static void
570 contact_widget_presence_notify_cb (EmpathyContactWidget *information)
572 gtk_label_set_text (GTK_LABEL (information->label_status),
573 empathy_contact_get_status (information->contact));
574 gtk_image_set_from_icon_name (GTK_IMAGE (information->image_state),
575 empathy_icon_name_for_contact (information->contact),
576 GTK_ICON_SIZE_BUTTON);
580 static void
581 contact_widget_avatar_notify_cb (EmpathyContactWidget *information)
583 EmpathyAvatar *avatar = NULL;
585 if (information->contact) {
586 avatar = empathy_contact_get_avatar (information->contact);
588 if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_AVATAR) {
589 g_signal_handlers_block_by_func (information->widget_avatar,
590 contact_widget_avatar_changed_cb,
591 information);
592 empathy_avatar_chooser_set (EMPATHY_AVATAR_CHOOSER (information->widget_avatar),
593 avatar);
594 g_signal_handlers_unblock_by_func (information->widget_avatar,
595 contact_widget_avatar_changed_cb,
596 information);
597 } else {
598 empathy_avatar_image_set (EMPATHY_AVATAR_IMAGE (information->widget_avatar),
599 avatar);
603 static void
604 contact_widget_groups_setup (EmpathyContactWidget *information)
606 if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_GROUPS) {
607 information->manager = empathy_contact_manager_new ();
608 contact_widget_model_setup (information);
612 static void
613 contact_widget_groups_update (EmpathyContactWidget *information)
615 if (information->flags & EMPATHY_CONTACT_WIDGET_EDIT_GROUPS &&
616 information->contact) {
617 g_signal_connect_swapped (information->contact, "notify::groups",
618 G_CALLBACK (contact_widget_groups_notify_cb),
619 information);
620 contact_widget_groups_populate_data (information);
622 gtk_widget_show (information->vbox_groups);
623 } else {
624 gtk_widget_hide (information->vbox_groups);
628 static void
629 contact_widget_model_setup (EmpathyContactWidget *information)
631 GtkTreeView *view;
632 GtkListStore *store;
633 GtkTreeSelection *selection;
635 view = GTK_TREE_VIEW (information->treeview_groups);
637 store = gtk_list_store_new (COL_COUNT,
638 G_TYPE_STRING, /* name */
639 G_TYPE_BOOLEAN, /* enabled */
640 G_TYPE_BOOLEAN); /* editable */
642 gtk_tree_view_set_model (view, GTK_TREE_MODEL (store));
644 selection = gtk_tree_view_get_selection (view);
645 gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
647 contact_widget_model_populate_columns (information);
649 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
650 COL_NAME, GTK_SORT_ASCENDING);
652 g_object_unref (store);
655 static void
656 contact_widget_model_populate_columns (EmpathyContactWidget *information)
658 GtkTreeView *view;
659 GtkTreeModel *model;
660 GtkTreeViewColumn *column;
661 GtkCellRenderer *renderer;
662 guint col_offset;
664 view = GTK_TREE_VIEW (information->treeview_groups);
665 model = gtk_tree_view_get_model (view);
667 renderer = gtk_cell_renderer_toggle_new ();
668 g_signal_connect (renderer, "toggled",
669 G_CALLBACK (contact_widget_cell_toggled),
670 information);
672 column = gtk_tree_view_column_new_with_attributes (_("Select"), renderer,
673 "active", COL_ENABLED,
674 NULL);
676 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
677 gtk_tree_view_column_set_fixed_width (column, 50);
678 gtk_tree_view_append_column (view, column);
680 renderer = gtk_cell_renderer_text_new ();
681 col_offset = gtk_tree_view_insert_column_with_attributes (view,
682 -1, _("Group"),
683 renderer,
684 "text", COL_NAME,
685 /* "editable", COL_EDITABLE, */
686 NULL);
688 g_object_set_data (G_OBJECT (renderer),
689 "column", GINT_TO_POINTER (COL_NAME));
691 column = gtk_tree_view_get_column (view, col_offset - 1);
692 gtk_tree_view_column_set_sort_column_id (column, COL_NAME);
693 gtk_tree_view_column_set_resizable (column,FALSE);
694 gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
696 if (information->renderer) {
697 g_object_unref (information->renderer);
700 information->renderer = g_object_ref (renderer);
703 static void
704 contact_widget_groups_populate_data (EmpathyContactWidget *information)
706 GtkTreeView *view;
707 GtkListStore *store;
708 GtkTreeIter iter;
709 GList *my_groups, *l;
710 GList *all_groups;
712 view = GTK_TREE_VIEW (information->treeview_groups);
713 store = GTK_LIST_STORE (gtk_tree_view_get_model (view));
714 gtk_list_store_clear (store);
716 all_groups = empathy_contact_list_get_all_groups (EMPATHY_CONTACT_LIST (information->manager));
717 my_groups = empathy_contact_list_get_groups (EMPATHY_CONTACT_LIST (information->manager),
718 information->contact);
720 for (l = all_groups; l; l = l->next) {
721 const gchar *group_str;
722 gboolean enabled;
724 group_str = l->data;
726 enabled = g_list_find_custom (my_groups,
727 group_str,
728 (GCompareFunc) strcmp) != NULL;
730 gtk_list_store_append (store, &iter);
731 gtk_list_store_set (store, &iter,
732 COL_NAME, group_str,
733 COL_EDITABLE, TRUE,
734 COL_ENABLED, enabled,
735 -1);
738 g_list_foreach (all_groups, (GFunc) g_free, NULL);
739 g_list_foreach (my_groups, (GFunc) g_free, NULL);
740 g_list_free (all_groups);
741 g_list_free (my_groups);
744 static void
745 contact_widget_groups_notify_cb (EmpathyContactWidget *information)
747 /* FIXME: not implemented */
750 static gboolean
751 contact_widget_model_find_name (EmpathyContactWidget *information,
752 const gchar *name,
753 GtkTreeIter *iter)
755 GtkTreeView *view;
756 GtkTreeModel *model;
757 FindName data;
759 if (G_STR_EMPTY (name)) {
760 return FALSE;
763 data.information = information;
764 data.name = name;
765 data.found = FALSE;
767 view = GTK_TREE_VIEW (information->treeview_groups);
768 model = gtk_tree_view_get_model (view);
770 gtk_tree_model_foreach (model,
771 (GtkTreeModelForeachFunc) contact_widget_model_find_name_foreach,
772 &data);
774 if (data.found == TRUE) {
775 *iter = data.found_iter;
776 return TRUE;
779 return FALSE;
782 static gboolean
783 contact_widget_model_find_name_foreach (GtkTreeModel *model,
784 GtkTreePath *path,
785 GtkTreeIter *iter,
786 FindName *data)
788 gchar *name;
790 gtk_tree_model_get (model, iter,
791 COL_NAME, &name,
792 -1);
794 if (!name) {
795 return FALSE;
798 if (data->name && strcmp (data->name, name) == 0) {
799 data->found = TRUE;
800 data->found_iter = *iter;
802 g_free (name);
804 return TRUE;
807 g_free (name);
809 return FALSE;
812 static void
813 contact_widget_cell_toggled (GtkCellRendererToggle *cell,
814 gchar *path_string,
815 EmpathyContactWidget *information)
817 GtkTreeView *view;
818 GtkTreeModel *model;
819 GtkListStore *store;
820 GtkTreePath *path;
821 GtkTreeIter iter;
822 gboolean enabled;
823 gchar *group;
825 view = GTK_TREE_VIEW (information->treeview_groups);
826 model = gtk_tree_view_get_model (view);
827 store = GTK_LIST_STORE (model);
829 path = gtk_tree_path_new_from_string (path_string);
831 gtk_tree_model_get_iter (model, &iter, path);
832 gtk_tree_model_get (model, &iter,
833 COL_ENABLED, &enabled,
834 COL_NAME, &group,
835 -1);
837 gtk_list_store_set (store, &iter, COL_ENABLED, !enabled, -1);
838 gtk_tree_path_free (path);
840 if (group) {
841 if (enabled) {
842 empathy_contact_list_remove_from_group (EMPATHY_CONTACT_LIST (information->manager),
843 information->contact,
844 group);
845 } else {
846 empathy_contact_list_add_to_group (EMPATHY_CONTACT_LIST (information->manager),
847 information->contact,
848 group);
851 g_free (group);
855 static void
856 contact_widget_entry_group_changed_cb (GtkEditable *editable,
857 EmpathyContactWidget *information)
859 GtkTreeIter iter;
860 const gchar *group;
862 group = gtk_entry_get_text (GTK_ENTRY (information->entry_group));
864 if (contact_widget_model_find_name (information, group, &iter)) {
865 gtk_widget_set_sensitive (GTK_WIDGET (information->button_group), FALSE);
867 } else {
868 gtk_widget_set_sensitive (GTK_WIDGET (information->button_group),
869 !G_STR_EMPTY (group));
873 static void
874 contact_widget_entry_group_activate_cb (GtkEntry *entry,
875 EmpathyContactWidget *information)
877 gtk_widget_activate (GTK_WIDGET (information->button_group));
880 static void
881 contact_widget_button_group_clicked_cb (GtkButton *button,
882 EmpathyContactWidget *information)
884 GtkTreeView *view;
885 GtkListStore *store;
886 GtkTreeIter iter;
887 const gchar *group;
889 view = GTK_TREE_VIEW (information->treeview_groups);
890 store = GTK_LIST_STORE (gtk_tree_view_get_model (view));
892 group = gtk_entry_get_text (GTK_ENTRY (information->entry_group));
894 gtk_list_store_append (store, &iter);
895 gtk_list_store_set (store, &iter,
896 COL_NAME, group,
897 COL_ENABLED, TRUE,
898 -1);
900 empathy_contact_list_add_to_group (EMPATHY_CONTACT_LIST (information->manager),
901 information->contact,
902 group);
905 static void
906 contact_widget_details_setup (EmpathyContactWidget *information)
908 /* FIXME: Needs new telepathy spec */
909 gtk_widget_hide (information->vbox_details);
912 static void
913 contact_widget_details_update (EmpathyContactWidget *information)
915 /* FIXME: Needs new telepathy spec */
918 static void
919 contact_widget_client_setup (EmpathyContactWidget *information)
921 /* FIXME: Needs new telepathy spec */
922 gtk_widget_hide (information->vbox_client);
925 static void
926 contact_widget_client_update (EmpathyContactWidget *information)
928 /* FIXME: Needs new telepathy spec */