Fix warning when selecting all accounts.
[empathy.git] / libempathy-gtk / empathy-main-window.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 <sys/stat.h>
26 #include <gtk/gtk.h>
27 #include <glade/glade.h>
28 #include <glib/gi18n.h>
29
30 #include <libempathy/gossip-conf.h>
31 #include <libempathy/gossip-contact.h>
32 #include <libempathy/gossip-debug.h>
33 #include <libempathy/gossip-utils.h>
34 #include <libempathy/gossip-chatroom-manager.h>
35 #include <libempathy/gossip-chatroom.h>
36 #include <libempathy/empathy-contact-list.h>
37 #include <libempathy/empathy-contact-manager.h>
38
39 #include "empathy-main-window.h"
40 #include "ephy-spinner.h"
41 #include "gossip-contact-list-store.h"
42 #include "gossip-contact-list-view.h"
43 #include "gossip-presence-chooser.h"
44 #include "gossip-ui-utils.h"
45 #include "gossip-status-presets.h"
46 #include "gossip-geometry.h"
47 #include "gossip-preferences.h"
48 #include "gossip-accounts-dialog.h"
49 #include "gossip-about-dialog.h"
50 #include "gossip-new-chatroom-dialog.h"
51 #include "gossip-chatrooms-window.h"
52
53 #define DEBUG_DOMAIN "MainWindow"
54
55 /* Minimum width of roster window if something goes wrong. */
56 #define MIN_WIDTH 50
57
58 /* Accels (menu shortcuts) can be configured and saved */
59 #define ACCELS_FILENAME "accels.txt"
60
61 /* Name in the geometry file */
62 #define GEOMETRY_NAME "main-window"
63
64 typedef struct {
65         GossipContactListView  *list_view;
66         GossipContactListStore *list_store;
67         MissionControl         *mc;
68         GossipChatroomManager  *chatroom_manager;
69
70         /* Main widgets */
71         GtkWidget              *window;
72         GtkWidget              *main_vbox;
73
74         /* Tooltips for all widgets */
75         GtkTooltips            *tooltips;
76
77         /* Menu widgets */
78         GtkWidget              *room;
79         GtkWidget              *room_menu;
80         GtkWidget              *room_sep;
81         GtkWidget              *room_join_favorites;
82         GtkWidget              *edit_context;
83         GtkWidget              *edit_context_separator;
84
85         /* Throbber */
86         GtkWidget              *throbber;
87
88         /* Widgets that are enabled when there is... */
89         GList                  *widgets_connected;      /* ... connected accounts */
90         GList                  *widgets_disconnected;   /* ... disconnected accounts */
91
92         /* Status popup */
93         GtkWidget              *presence_toolbar;
94         GtkWidget              *presence_chooser;
95
96         /* Misc */
97         guint                   size_timeout_id;
98 } EmpathyMainWindow;
99
100 static void     main_window_destroy_cb                         (GtkWidget                       *widget,
101                                                                 EmpathyMainWindow               *window);
102 static void     main_window_favorite_chatroom_menu_setup       (EmpathyMainWindow               *window);
103 static void     main_window_favorite_chatroom_menu_added_cb    (GossipChatroomManager           *manager,
104                                                                 GossipChatroom                  *chatroom,
105                                                                 EmpathyMainWindow               *window);
106 static void     main_window_favorite_chatroom_menu_removed_cb  (GossipChatroomManager           *manager,
107                                                                 GossipChatroom                  *chatroom,
108                                                                 EmpathyMainWindow               *window);
109 static void     main_window_favorite_chatroom_menu_activate_cb (GtkMenuItem                     *menu_item,
110                                                                 GossipChatroom                  *chatroom);
111 static void     main_window_favorite_chatroom_menu_update      (EmpathyMainWindow               *window);
112 static void     main_window_favorite_chatroom_menu_add         (EmpathyMainWindow               *window,
113                                                                 GossipChatroom                  *chatroom);
114 static void     main_window_chat_quit_cb                       (GtkWidget                       *widget,
115                                                                 EmpathyMainWindow               *window);
116 static void     main_window_chat_new_message_cb                (GtkWidget                       *widget,
117                                                                 EmpathyMainWindow               *window);
118 static void     main_window_chat_history_cb                    (GtkWidget                       *widget,
119                                                                 EmpathyMainWindow               *window);
120 static void     main_window_room_join_new_cb                   (GtkWidget                       *widget,
121                                                                 EmpathyMainWindow               *window);
122 static void     main_window_room_join_favorites_cb             (GtkWidget                       *widget,
123                                                                 EmpathyMainWindow               *window);
124 static void     main_window_room_manage_favorites_cb           (GtkWidget                       *widget,
125                                                                 EmpathyMainWindow               *window);
126 static void     main_window_chat_add_contact_cb                (GtkWidget                       *widget,
127                                                                 EmpathyMainWindow               *window);
128 static void     main_window_chat_show_offline_cb               (GtkCheckMenuItem                *item,
129                                                                 EmpathyMainWindow               *window);
130 static gboolean main_window_edit_button_press_event_cb         (GtkWidget                       *widget,
131                                                                 GdkEventButton                  *event,
132                                                                 EmpathyMainWindow               *window);
133 static void     main_window_edit_accounts_cb                   (GtkWidget                       *widget,
134                                                                 EmpathyMainWindow               *window);
135 static void     main_window_edit_personal_information_cb       (GtkWidget                       *widget,
136                                                                 EmpathyMainWindow               *window);
137 static void     main_window_edit_preferences_cb                (GtkWidget                       *widget,
138                                                                 EmpathyMainWindow               *window);
139 static void     main_window_help_about_cb                      (GtkWidget                       *widget,
140                                                                 EmpathyMainWindow               *window);
141 static void     main_window_help_contents_cb                   (GtkWidget                       *widget,
142                                                                 EmpathyMainWindow               *window);
143 static gboolean main_window_throbber_button_press_event_cb     (GtkWidget                       *throbber_ebox,
144                                                                 GdkEventButton                  *event,
145                                                                 EmpathyMainWindow               *window);
146 static void     main_window_status_changed_cb                  (MissionControl                  *mc,
147                                                                 TelepathyConnectionStatus        status,
148                                                                 McPresence                       presence,
149                                                                 TelepathyConnectionStatusReason  reason,
150                                                                 const gchar                     *unique_name,
151                                                                 EmpathyMainWindow               *window);
152 static void     main_window_update_status                      (EmpathyMainWindow               *window);
153 static void     main_window_accels_load                        (void);
154 static void     main_window_accels_save                        (void);
155 static void     main_window_connection_items_setup             (EmpathyMainWindow               *window,
156                                                                 GladeXML                        *glade);
157 static gboolean main_window_configure_event_timeout_cb         (EmpathyMainWindow               *window);
158 static gboolean main_window_configure_event_cb                 (GtkWidget                       *widget,
159                                                                 GdkEventConfigure               *event,
160                                                                 EmpathyMainWindow               *window);
161 static void     main_window_notify_show_offline_cb             (GossipConf                      *conf,
162                                                                 const gchar                     *key,
163                                                                 gpointer                         check_menu_item);
164 static void     main_window_notify_show_avatars_cb             (GossipConf                      *conf,
165                                                                 const gchar                     *key,
166                                                                 EmpathyMainWindow               *window);
167 static void     main_window_notify_compact_contact_list_cb     (GossipConf                      *conf,
168                                                                 const gchar                     *key,
169                                                                 EmpathyMainWindow               *window);
170 static void     main_window_notify_sort_criterium_cb           (GossipConf                      *conf,
171                                                                 const gchar                     *key,
172                                                                 EmpathyMainWindow               *window);
173
174 GtkWidget *
175 empathy_main_window_show (void)
176 {
177         static EmpathyMainWindow *window = NULL;
178         EmpathyContactList       *list_iface;
179         GladeXML                 *glade;
180         GossipConf               *conf;
181         GtkWidget                *sw;
182         GtkWidget                *show_offline_widget;
183         GtkWidget                *ebox;
184         GtkToolItem              *item;
185         gchar                    *str;
186         gboolean                  show_offline;
187         gboolean                  show_avatars;
188         gboolean                  compact_contact_list;
189         gint                      x, y, w, h;
190
191         if (window) {
192                 gtk_window_present (GTK_WINDOW (window->window));
193                 return window->window;
194         }
195
196         window = g_new0 (EmpathyMainWindow, 1);
197
198         /* Set up interface */
199         glade = gossip_glade_get_file ("empathy-main-window.glade",
200                                        "main_window",
201                                        NULL,
202                                        "main_window", &window->window,
203                                        "main_vbox", &window->main_vbox,
204                                        "chat_show_offline", &show_offline_widget,
205                                        "room", &window->room,
206                                        "room_sep", &window->room_sep,
207                                        "room_join_favorites", &window->room_join_favorites,
208                                        "edit_context", &window->edit_context,
209                                        "edit_context_separator", &window->edit_context_separator,
210                                        "presence_toolbar", &window->presence_toolbar,
211                                        "roster_scrolledwindow", &sw,
212                                        NULL);
213
214         gossip_glade_connect (glade,
215                               window,
216                               "main_window", "destroy", main_window_destroy_cb,
217                               "main_window", "configure_event", main_window_configure_event_cb,
218                               "chat_quit", "activate", main_window_chat_quit_cb,
219                               "chat_new_message", "activate", main_window_chat_new_message_cb,
220                               "chat_history", "activate", main_window_chat_history_cb,
221                               "room_join_new", "activate", main_window_room_join_new_cb,
222                               "room_join_favorites", "activate", main_window_room_join_favorites_cb,
223                               "room_manage_favorites", "activate", main_window_room_manage_favorites_cb,
224                               "chat_add_contact", "activate", main_window_chat_add_contact_cb,
225                               "chat_show_offline", "toggled", main_window_chat_show_offline_cb,
226                               "edit", "button-press-event", main_window_edit_button_press_event_cb,
227                               "edit_accounts", "activate", main_window_edit_accounts_cb,
228                               "edit_personal_information", "activate", main_window_edit_personal_information_cb,
229                               "edit_preferences", "activate", main_window_edit_preferences_cb,
230                               "help_about", "activate", main_window_help_about_cb,
231                               "help_contents", "activate", main_window_help_contents_cb,
232                               NULL);
233
234         /* Set up connection related widgets. */
235         main_window_connection_items_setup (window, glade);
236         g_object_unref (glade);
237
238         window->tooltips = g_object_ref_sink (gtk_tooltips_new ());
239         window->mc = gossip_mission_control_new ();
240         dbus_g_proxy_connect_signal (DBUS_G_PROXY (window->mc), "AccountStatusChanged",
241                                      G_CALLBACK (main_window_status_changed_cb),
242                                      window, NULL);
243
244         /* Set up menu */
245         main_window_favorite_chatroom_menu_setup (window);
246
247         gtk_widget_hide (window->edit_context);
248         gtk_widget_hide (window->edit_context_separator);
249
250         /* Set up presence chooser */
251         window->presence_chooser = gossip_presence_chooser_new ();
252         gtk_widget_show (window->presence_chooser);
253         item = gtk_tool_item_new ();
254         gtk_widget_show (GTK_WIDGET (item));
255         gtk_container_add (GTK_CONTAINER (item), window->presence_chooser);
256         gtk_tool_item_set_is_important (item, TRUE);
257         gtk_tool_item_set_expand (item, TRUE);
258         gtk_toolbar_insert (GTK_TOOLBAR (window->presence_toolbar), item, -1);
259
260         /* Set up the throbber */
261         ebox = gtk_event_box_new ();
262         gtk_event_box_set_visible_window (GTK_EVENT_BOX (ebox), FALSE);
263
264         window->throbber = ephy_spinner_new ();
265         ephy_spinner_set_size (EPHY_SPINNER (window->throbber), GTK_ICON_SIZE_LARGE_TOOLBAR);
266         gtk_container_add (GTK_CONTAINER (ebox), window->throbber);
267
268         item = gtk_tool_item_new ();
269         gtk_container_add (GTK_CONTAINER (item), ebox);
270         gtk_widget_show_all (GTK_WIDGET (item));
271
272         gtk_toolbar_insert (GTK_TOOLBAR (window->presence_toolbar), item, -1);
273
274         str = _("Show and edit accounts");
275         gtk_tooltips_set_tip (GTK_TOOLTIPS (window->tooltips),
276                               ebox, str, str);
277
278         g_signal_connect (ebox,
279                           "button-press-event",
280                           G_CALLBACK (main_window_throbber_button_press_event_cb),
281                           window);
282
283         /* Set up contact list. */
284         gossip_status_presets_get_all ();
285
286         list_iface = EMPATHY_CONTACT_LIST (empathy_contact_manager_new ());
287         empathy_contact_list_setup (list_iface);
288         window->list_store = gossip_contact_list_store_new (list_iface);
289         window->list_view = gossip_contact_list_view_new (window->list_store);
290         g_object_unref (list_iface);
291
292         gtk_widget_show (GTK_WIDGET (window->list_view));
293         gtk_container_add (GTK_CONTAINER (sw),
294                            GTK_WIDGET (window->list_view));
295
296         /* Load user-defined accelerators. */
297         main_window_accels_load ();
298
299         /* Set window size. */
300         gossip_geometry_load (GEOMETRY_NAME, &x, &y, &w, &h);
301
302         if (w >= 1 && h >= 1) {
303                 /* Use the defaults from the glade file if we
304                  * don't have good w, h geometry.
305                  */
306                 gossip_debug (DEBUG_DOMAIN, "Configuring window default size w:%d, h:%d", w, h);
307                 gtk_window_set_default_size (GTK_WINDOW (window->window), w, h);
308         }
309
310         if (x >= 0 && y >= 0) {
311                 /* Let the window manager position it if we
312                  * don't have good x, y coordinates.
313                  */
314                 gossip_debug (DEBUG_DOMAIN, "Configuring window default position x:%d, y:%d", x, y);
315                 gtk_window_move (GTK_WINDOW (window->window), x, y);
316         }
317
318         conf = gossip_conf_get ();
319         
320         /* Show offline ? */
321         gossip_conf_get_bool (conf,
322                               GOSSIP_PREFS_CONTACTS_SHOW_OFFLINE,
323                               &show_offline);
324         gossip_conf_notify_add (conf,
325                                 GOSSIP_PREFS_CONTACTS_SHOW_OFFLINE,
326                                 main_window_notify_show_offline_cb,
327                                 show_offline_widget);
328
329         gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (show_offline_widget),
330                                         show_offline);
331
332         /* Show avatars ? */
333         gossip_conf_get_bool (conf,
334                               GOSSIP_PREFS_UI_SHOW_AVATARS,
335                               &show_avatars);
336         gossip_conf_notify_add (conf,
337                                 GOSSIP_PREFS_UI_SHOW_AVATARS,
338                                 (GossipConfNotifyFunc) main_window_notify_show_avatars_cb,
339                                 window);
340         gossip_contact_list_store_set_show_avatars (window->list_store, show_avatars);
341
342         /* Is compact ? */
343         gossip_conf_get_bool (conf,
344                               GOSSIP_PREFS_UI_COMPACT_CONTACT_LIST,
345                               &compact_contact_list);
346         gossip_conf_notify_add (conf,
347                                 GOSSIP_PREFS_UI_COMPACT_CONTACT_LIST,
348                                 (GossipConfNotifyFunc) main_window_notify_compact_contact_list_cb,
349                                 window);
350         gossip_contact_list_store_set_is_compact (window->list_store, compact_contact_list);
351
352         /* Sort criterium */
353         gossip_conf_notify_add (conf,
354                                 GOSSIP_PREFS_CONTACTS_SORT_CRITERIUM,
355                                 (GossipConfNotifyFunc) main_window_notify_sort_criterium_cb,
356                                 window);
357         main_window_notify_sort_criterium_cb (conf,
358                                               GOSSIP_PREFS_CONTACTS_SORT_CRITERIUM,
359                                               window);
360
361         main_window_update_status (window);
362
363         return window->window;
364 }
365
366 static void
367 main_window_destroy_cb (GtkWidget         *widget,
368                         EmpathyMainWindow *window)
369 {
370         /* Save user-defined accelerators. */
371         main_window_accels_save ();
372
373         dbus_g_proxy_disconnect_signal (DBUS_G_PROXY (window->mc), "AccountStatusChanged",
374                                         G_CALLBACK (main_window_status_changed_cb),
375                                         window);
376
377         if (window->size_timeout_id) {
378                 g_source_remove (window->size_timeout_id);
379         }
380
381         g_list_free (window->widgets_connected);
382         g_list_free (window->widgets_disconnected);
383
384         g_object_unref (window->tooltips);
385         g_object_unref (window->mc);
386         g_object_unref (window->list_store);
387
388         g_free (window);
389 }
390
391 static void
392 main_window_favorite_chatroom_menu_setup (EmpathyMainWindow *window)
393 {
394         GList *chatrooms, *l;
395
396         window->chatroom_manager = gossip_chatroom_manager_new ();
397         chatrooms = gossip_chatroom_manager_get_chatrooms (window->chatroom_manager, NULL);
398         window->room_menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (window->room));
399
400         for (l = chatrooms; l; l = l->next) {
401                 main_window_favorite_chatroom_menu_add (window, l->data);
402         }
403
404         if (!chatrooms) {
405                 gtk_widget_hide (window->room_sep);
406         }
407
408         gtk_widget_set_sensitive (window->room_join_favorites, chatrooms != NULL);
409
410         g_signal_connect (window->chatroom_manager, "chatroom-added",
411                           G_CALLBACK (main_window_favorite_chatroom_menu_added_cb),
412                           window);
413         g_signal_connect (window->chatroom_manager, "chatroom-removed",
414                           G_CALLBACK (main_window_favorite_chatroom_menu_removed_cb),
415                           window);
416
417         g_list_free (chatrooms);
418 }
419
420 static void
421 main_window_favorite_chatroom_menu_added_cb (GossipChatroomManager *manager,
422                                              GossipChatroom        *chatroom,
423                                              EmpathyMainWindow     *window)
424 {
425         main_window_favorite_chatroom_menu_add (window, chatroom);
426         gtk_widget_show (window->room_sep);
427         gtk_widget_set_sensitive (window->room_join_favorites, TRUE);
428 }
429
430 static void
431 main_window_favorite_chatroom_menu_removed_cb (GossipChatroomManager *manager,
432                                                GossipChatroom        *chatroom,
433                                                EmpathyMainWindow     *window)
434 {
435         GtkWidget *menu_item;
436
437         menu_item = g_object_get_data (G_OBJECT (chatroom), "menu_item");
438
439         g_object_set_data (G_OBJECT (chatroom), "menu_item", NULL);
440         gtk_widget_destroy (menu_item);
441
442         main_window_favorite_chatroom_menu_update (window);
443 }
444
445 static void
446 main_window_favorite_chatroom_menu_activate_cb (GtkMenuItem    *menu_item,
447                                                 GossipChatroom *chatroom)
448 {
449 /*FIXME:
450         GossipSession          *session;
451         GossipAccount          *account;
452         GossipChatroomProvider *provider;
453
454         session = gossip_app_get_session ();
455         account = gossip_chatroom_get_account (chatroom);
456         provider = gossip_session_get_chatroom_provider (session, account);
457
458         gossip_group_chat_new (provider, chatroom);
459 */
460 }
461
462 static void
463 main_window_favorite_chatroom_menu_update (EmpathyMainWindow *window)
464 {
465         GList *chatrooms;
466
467         chatrooms = gossip_chatroom_manager_get_chatrooms (window->chatroom_manager, NULL);
468
469         if (chatrooms) {
470                 gtk_widget_show (window->room_sep);
471         } else {
472                 gtk_widget_hide (window->room_sep);
473         }
474
475         gtk_widget_set_sensitive (window->room_join_favorites, chatrooms != NULL);
476         g_list_free (chatrooms);
477 }
478
479 static void
480 main_window_favorite_chatroom_menu_add (EmpathyMainWindow *window,
481                                         GossipChatroom    *chatroom)
482 {
483         GtkWidget   *menu_item;
484         const gchar *name;
485
486         if (g_object_get_data (G_OBJECT (chatroom), "menu_item")) {
487                 return;
488         }
489
490         name = gossip_chatroom_get_name (chatroom);
491         menu_item = gtk_menu_item_new_with_label (name);
492
493         g_object_set_data (G_OBJECT (chatroom), "menu_item", menu_item);
494         g_signal_connect (menu_item, "activate",
495                           G_CALLBACK (main_window_favorite_chatroom_menu_activate_cb),
496                           chatroom);
497
498         gtk_menu_shell_insert (GTK_MENU_SHELL (window->room_menu),
499                                menu_item, 3);
500
501         gtk_widget_show (menu_item);
502 }
503
504 static void
505 main_window_chat_quit_cb (GtkWidget         *widget,
506                           EmpathyMainWindow *window)
507 {
508         gtk_main_quit ();
509 }
510
511 static void
512 main_window_chat_new_message_cb (GtkWidget         *widget,
513                                  EmpathyMainWindow *window)
514 {
515         //gossip_new_message_dialog_show (GTK_WINDOW (window->window));
516 }
517
518 static void
519 main_window_chat_history_cb (GtkWidget         *widget,
520                              EmpathyMainWindow *window)
521 {
522         //gossip_log_window_show (NULL, NULL);
523 }
524
525 static void
526 main_window_room_join_new_cb (GtkWidget         *widget,
527                               EmpathyMainWindow *window)
528 {
529         gossip_new_chatroom_dialog_show (GTK_WINDOW (window->window));
530 }
531
532 static void
533 main_window_room_join_favorites_cb (GtkWidget         *widget,
534                                     EmpathyMainWindow *window)
535 {
536         //gossip_session_chatroom_join_favorites (window->session);
537 }
538
539 static void
540 main_window_room_manage_favorites_cb (GtkWidget         *widget,
541                                       EmpathyMainWindow *window)
542 {
543         gossip_chatrooms_window_show (GTK_WINDOW (window->window));
544 }
545
546 static void
547 main_window_chat_add_contact_cb (GtkWidget         *widget,
548                                  EmpathyMainWindow *window)
549 {
550         //gossip_add_contact_dialog_show (GTK_WINDOW (window->window), NULL);
551 }
552
553 static void
554 main_window_chat_show_offline_cb (GtkCheckMenuItem  *item,
555                                   EmpathyMainWindow *window)
556 {
557         gboolean current;
558
559         current = gtk_check_menu_item_get_active (item);
560
561         gossip_conf_set_bool (gossip_conf_get (),
562                               GOSSIP_PREFS_CONTACTS_SHOW_OFFLINE,
563                               current);
564
565         /* Turn off sound just while we alter the contact list. */
566         // FIXME: gossip_sound_set_enabled (FALSE);
567         gossip_contact_list_store_set_show_offline (window->list_store, current);
568         //gossip_sound_set_enabled (TRUE);
569 }
570
571 static gboolean
572 main_window_edit_button_press_event_cb (GtkWidget         *widget,
573                                         GdkEventButton    *event,
574                                         EmpathyMainWindow *window)
575 {
576         GossipContact *contact;
577         gchar         *group;
578
579         if (!event->button == 1) {
580                 return FALSE;
581         }
582
583         group = gossip_contact_list_view_get_selected_group (window->list_view);
584         if (group) {
585                 GtkMenuItem *item;
586                 GtkWidget   *label;
587                 GtkWidget   *submenu;
588
589                 item = GTK_MENU_ITEM (window->edit_context);
590                 label = gtk_bin_get_child (GTK_BIN (item));
591                 gtk_label_set_text (GTK_LABEL (label), _("Group"));
592
593                 gtk_widget_show (window->edit_context);
594                 gtk_widget_show (window->edit_context_separator);
595
596                 submenu = gossip_contact_list_view_get_group_menu (window->list_view);
597                 gtk_menu_item_set_submenu (item, submenu);
598
599                 g_free (group);
600
601                 return FALSE;
602         }
603
604         contact = gossip_contact_list_view_get_selected (window->list_view);
605         if (contact) {
606                 GtkMenuItem *item;
607                 GtkWidget   *label;
608                 GtkWidget   *submenu;
609
610                 item = GTK_MENU_ITEM (window->edit_context);
611                 label = gtk_bin_get_child (GTK_BIN (item));
612                 gtk_label_set_text (GTK_LABEL (label), _("Contact"));
613
614                 gtk_widget_show (window->edit_context);
615                 gtk_widget_show (window->edit_context_separator);
616
617                 submenu = gossip_contact_list_view_get_contact_menu (window->list_view,
618                                                                      contact);
619                 gtk_menu_item_set_submenu (item, submenu);
620
621                 g_object_unref (contact);
622
623                 return FALSE;
624         }
625
626         gtk_widget_hide (window->edit_context);
627         gtk_widget_hide (window->edit_context_separator);
628
629         return FALSE;
630 }
631
632 static void
633 main_window_edit_accounts_cb (GtkWidget         *widget,
634                               EmpathyMainWindow *window)
635 {
636         gossip_accounts_dialog_show (GTK_WINDOW (window->window));
637 }
638
639 static void
640 main_window_edit_personal_information_cb (GtkWidget         *widget,
641                                           EmpathyMainWindow *window)
642 {
643         //gossip_vcard_dialog_show (GTK_WINDOW (window->window));
644 }
645
646 static void
647 main_window_edit_preferences_cb (GtkWidget         *widget,
648                                  EmpathyMainWindow *window)
649 {
650         gossip_preferences_show (GTK_WINDOW (window->window));
651 }
652
653 static void
654 main_window_help_about_cb (GtkWidget         *widget,
655                            EmpathyMainWindow *window)
656 {
657         gossip_about_dialog_new (GTK_WINDOW (window->window));
658 }
659
660 static void
661 main_window_help_contents_cb (GtkWidget         *widget,
662                               EmpathyMainWindow *window)
663 {
664         //gossip_help_show ();
665 }
666
667 static gboolean
668 main_window_throbber_button_press_event_cb (GtkWidget         *throbber_ebox,
669                                             GdkEventButton    *event,
670                                             EmpathyMainWindow *window)
671 {
672         if (event->type != GDK_BUTTON_PRESS ||
673             event->button != 1) {
674                 return FALSE;
675         }
676
677         gossip_accounts_dialog_show (GTK_WINDOW (window->window));
678
679         return FALSE;
680 }
681
682 static void
683 main_window_status_changed_cb (MissionControl                  *mc,
684                                TelepathyConnectionStatus        status,
685                                McPresence                       presence,
686                                TelepathyConnectionStatusReason  reason,
687                                const gchar                     *unique_name,
688                                EmpathyMainWindow               *window)
689 {
690         main_window_update_status (window);
691 }
692
693 static void
694 main_window_update_status (EmpathyMainWindow *window)
695 {
696         GList *accounts, *l;
697         guint  connected = 0;
698         guint  connecting = 0;
699         guint  disconnected = 0;
700
701         /* Count number of connected/connecting/disconnected accounts */
702         accounts = mc_accounts_list (); 
703         for (l = accounts; l; l = l->next) {
704                 McAccount *account;
705                 guint      status;
706
707                 account = l->data;
708
709                 status = mission_control_get_connection_status (window->mc,
710                                                                 account,
711                                                                 NULL);
712
713                 if (status == 0) {
714                         connected++;
715                 } else if (status == 1) {
716                         connecting++;
717                 } else if (status == 2) {
718                         disconnected++;
719                 }
720
721                 g_object_unref (account);
722         }
723         g_list_free (accounts);
724
725         /* Update the spinner state */
726         if (connecting > 0) {
727                 ephy_spinner_start (EPHY_SPINNER (window->throbber));
728         } else {
729                 ephy_spinner_stop (EPHY_SPINNER (window->throbber));
730         }
731
732         /* Update widgets sensibility */
733         for (l = window->widgets_connected; l; l = l->next) {
734                 gtk_widget_set_sensitive (l->data, (connected > 0));
735         }
736
737         for (l = window->widgets_disconnected; l; l = l->next) {
738                 gtk_widget_set_sensitive (l->data, (disconnected > 0));
739         }
740 }
741
742 /*
743  * Accels
744  */
745 static void
746 main_window_accels_load (void)
747 {
748         gchar *filename;
749
750         filename = g_build_filename (g_get_home_dir (), ".gnome2", PACKAGE_NAME, ACCELS_FILENAME, NULL);
751         if (g_file_test (filename, G_FILE_TEST_EXISTS)) {
752                 gossip_debug (DEBUG_DOMAIN, "Loading from:'%s'", filename);
753                 gtk_accel_map_load (filename);
754         }
755
756         g_free (filename);
757 }
758
759 static void
760 main_window_accels_save (void)
761 {
762         gchar *dir;
763         gchar *file_with_path;
764
765         dir = g_build_filename (g_get_home_dir (), ".gnome2", PACKAGE_NAME, NULL);
766         g_mkdir_with_parents (dir, S_IRUSR | S_IWUSR | S_IXUSR);
767         file_with_path = g_build_filename (dir, ACCELS_FILENAME, NULL);
768         g_free (dir);
769
770         gossip_debug (DEBUG_DOMAIN, "Saving to:'%s'", file_with_path);
771         gtk_accel_map_save (file_with_path);
772
773         g_free (file_with_path);
774 }
775
776 static void
777 main_window_connection_items_setup (EmpathyMainWindow *window,
778                                     GladeXML          *glade)
779 {
780         GList         *list;
781         GtkWidget     *w;
782         gint           i;
783         const gchar *widgets_connected[] = {
784                 "room",
785                 "chat_new_message",
786                 "chat_add_contact",
787                 "edit_personal_information"
788         };
789         const gchar *widgets_disconnected[] = {
790         };
791
792         for (i = 0, list = NULL; i < G_N_ELEMENTS (widgets_connected); i++) {
793                 w = glade_xml_get_widget (glade, widgets_connected[i]);
794                 list = g_list_prepend (list, w);
795         }
796
797         window->widgets_connected = list;
798
799         for (i = 0, list = NULL; i < G_N_ELEMENTS (widgets_disconnected); i++) {
800                 w = glade_xml_get_widget (glade, widgets_disconnected[i]);
801                 list = g_list_prepend (list, w);
802         }
803
804         window->widgets_disconnected = list;
805 }
806
807 static gboolean
808 main_window_configure_event_timeout_cb (EmpathyMainWindow *window)
809 {
810         gint x, y, w, h;
811
812         gtk_window_get_size (GTK_WINDOW (window->window), &w, &h);
813         gtk_window_get_position (GTK_WINDOW (window->window), &x, &y);
814
815         gossip_geometry_save (GEOMETRY_NAME, x, y, w, h);
816
817         window->size_timeout_id = 0;
818
819         return FALSE;
820 }
821
822 static gboolean
823 main_window_configure_event_cb (GtkWidget         *widget,
824                                 GdkEventConfigure *event,
825                                 EmpathyMainWindow *window)
826 {
827         if (window->size_timeout_id) {
828                 g_source_remove (window->size_timeout_id);
829         }
830
831         window->size_timeout_id = g_timeout_add (500,
832                                                (GSourceFunc) main_window_configure_event_timeout_cb,
833                                                window);
834
835         return FALSE;
836 }
837
838 static void
839 main_window_notify_show_offline_cb (GossipConf  *conf,
840                                     const gchar *key,
841                                     gpointer     check_menu_item)
842 {
843         gboolean show_offline;
844
845         if (gossip_conf_get_bool (conf, key, &show_offline)) {
846                 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (check_menu_item),
847                                                 show_offline);
848         }
849 }
850
851 static void
852 main_window_notify_show_avatars_cb (GossipConf        *conf,
853                                     const gchar       *key,
854                                     EmpathyMainWindow *window)
855 {
856         gboolean show_avatars;
857
858         if (gossip_conf_get_bool (conf, key, &show_avatars)) {
859                 gossip_contact_list_store_set_show_avatars (window->list_store,
860                                                             show_avatars);
861         }
862 }
863
864 static void
865 main_window_notify_compact_contact_list_cb (GossipConf        *conf,
866                                             const gchar       *key,
867                                             EmpathyMainWindow *window)
868 {
869         gboolean compact_contact_list;
870
871         if (gossip_conf_get_bool (conf, key, &compact_contact_list)) {
872                 gossip_contact_list_store_set_is_compact (window->list_store,
873                                                           compact_contact_list);
874         }
875 }
876
877 static void
878 main_window_notify_sort_criterium_cb (GossipConf        *conf,
879                                       const gchar       *key,
880                                       EmpathyMainWindow *window)
881 {
882         gchar *str = NULL;
883
884         if (gossip_conf_get_string (conf, key, &str)) {
885                 GType       type;
886                 GEnumClass *enum_class;
887                 GEnumValue *enum_value;
888
889                 type = gossip_contact_list_store_sort_get_type ();
890                 enum_class = G_ENUM_CLASS (g_type_class_peek (type));
891                 enum_value = g_enum_get_value_by_nick (enum_class, str);
892                 g_free (str);
893
894                 if (enum_value) {
895                         gossip_contact_list_store_set_sort_criterium (window->list_store, 
896                                                                       enum_value->value);
897                 }
898         }
899 }
900