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