After a deep refactoring, finally finished to split the window manager
[modest] / src / maemo / modest-main-window.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include <glib/gi18n.h>
31 #include <gtk/gtktreeviewcolumn.h>
32 #include <tny-account-store-view.h>
33 #include <tny-simple-list.h>
34 #include <tny-list.h>
35 #include <tny-iterator.h>
36 #include <tny-error.h>
37 #include "modest-hildon-includes.h"
38 #include "modest-defs.h"
39 #include <string.h>
40 #include "widgets/modest-header-view-priv.h"
41 #include "widgets/modest-main-window.h"
42 #include "widgets/modest-msg-edit-window.h"
43 #include "widgets/modest-account-view-window.h"
44 #include "modest-runtime.h"
45 #include "modest-account-mgr-helpers.h"
46 #include "modest-platform.h"
47 #include "modest-widget-memory.h"
48 #include "modest-window-priv.h"
49 #include "modest-main-window-ui.h"
50 #include "modest-main-window-ui-dimming.h"
51 #include "modest-account-mgr.h"
52 #include "modest-tny-account.h"
53 #include "modest-tny-folder.h"
54 #include "modest-conf.h"
55 #include <modest-utils.h>
56 #include <modest-maemo-utils.h>
57 #include "modest-tny-platform-factory.h"
58 #include "modest-tny-msg.h"
59 #include "modest-mail-operation.h"
60 #include "modest-icon-names.h"
61 #include "modest-progress-bar.h"
62 #include "modest-text-utils.h"
63 #include "modest-ui-dimming-manager.h"
64 #include "maemo/modest-osso-state-saving.h"
65 #include "modest-text-utils.h"
66 #include "modest-signal-mgr.h"
67
68 #define MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS "ModestMainWindowActionAdditions"
69
70 #define XALIGN 0.5
71 #define YALIGN 0.0
72 #define XSPACE 1
73 #define YSPACE 0
74
75 /* 'private'/'protected' functions */
76 static void modest_main_window_class_init  (ModestMainWindowClass *klass);
77 static void modest_main_window_init        (ModestMainWindow *obj);
78 static void modest_main_window_finalize    (GObject *obj);
79
80 static gboolean modest_main_window_window_state_event (GtkWidget *widget, 
81                                                        GdkEventWindowState *event, 
82                                                        gpointer userdata);
83
84 static void connect_signals (ModestMainWindow *self);
85
86 static void modest_main_window_disconnect_signals (ModestWindow *self);
87
88 static void restore_settings (ModestMainWindow *self, 
89                               gboolean do_folder_view_too);
90
91 static void save_state (ModestWindow *self);
92
93 static void update_menus (ModestMainWindow* self);
94
95 static void modest_main_window_show_toolbar   (ModestWindow *window,
96                                                gboolean show_toolbar);
97
98 static void cancel_progressbar (GtkToolButton *toolbutton,
99                                 ModestMainWindow *self);
100
101 static void on_queue_changed   (ModestMailOperationQueue *queue,
102                                 ModestMailOperation *mail_op,
103                                 ModestMailOperationQueueNotification type,
104                                 ModestMainWindow *self);
105
106 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
107
108 static void on_account_inserted (TnyAccountStore *accoust_store,
109                                  TnyAccount *account,
110                                  gpointer user_data);
111
112 static void on_account_removed  (TnyAccountStore *accoust_store,
113                                  TnyAccount *account,
114                                  gpointer user_data);
115
116 static void on_account_changed  (TnyAccountStore *account_store,
117                                  TnyAccount *account,
118                                  gpointer user_data);
119
120 static void on_default_account_changed (ModestAccountMgr* mgr,
121                                         gpointer user_data);
122
123 static gboolean on_inner_widgets_key_pressed  (GtkWidget *widget,
124                                                GdkEventKey *event,
125                                                gpointer user_data);
126
127 static void on_configuration_key_changed      (ModestConf* conf, 
128                                                const gchar *key, 
129                                                ModestConfEvent event,
130                                                ModestConfNotificationId id,
131                                                ModestMainWindow *self);
132
133 static void set_toolbar_mode                  (ModestMainWindow *self, 
134                                                ModestToolBarModes mode);
135
136 static gboolean set_toolbar_transfer_mode     (ModestMainWindow *self); 
137
138 static void on_show_account_action_toggled      (GtkToggleAction *action,
139                                                  gpointer user_data);
140
141 static void on_refresh_account_action_activated   (GtkAction *action,
142                                                    gpointer user_data);
143
144 static void on_send_receive_csm_activated         (GtkMenuItem *item,
145                                                    gpointer user_data);
146
147 static void on_msg_count_changed (ModestHeaderView *header_view,
148                                   TnyFolder *folder,
149                                   TnyFolderChange *change,
150                                   ModestMainWindow *main_window);
151
152 static void modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self);
153
154
155 static GtkWidget * create_empty_view (void);
156
157 static gboolean  on_folder_view_focus_in (GtkWidget *widget,
158                                           GdkEventFocus *event,
159                                           gpointer userdata);
160
161 static gboolean  on_header_view_focus_in (GtkWidget *widget,
162                                           GdkEventFocus *event,
163                                           gpointer userdata);
164
165 static void      on_folder_selection_changed (ModestFolderView *folder_view,
166                                               TnyFolderStore *folder_store, 
167                                               gboolean selected,
168                                               ModestMainWindow *main_window);
169                                                 
170 static void set_at_least_one_account_visible(ModestMainWindow *self);
171
172 static void on_updating_msg_list (ModestHeaderView *header_view,
173                                   gboolean starting,
174                                   gpointer user_data);
175
176 static gboolean restore_paned_timeout_handler (gpointer *data);
177
178 static gboolean show_opening_banner (gpointer user_data);
179
180 static void on_window_destroy (GtkObject *widget,
181                                gpointer userdata);
182
183 static void on_window_hide (GObject    *gobject,
184                             GParamSpec *arg1,
185                             gpointer    user_data);
186
187 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
188 struct _ModestMainWindowPrivate {
189         GtkWidget *msg_paned;
190         GtkWidget *main_paned;
191         GtkWidget *main_vbox;
192         GtkWidget *contents_widget;
193         GtkWidget *empty_view;
194
195         /* Progress observers */
196         GtkWidget   *progress_bar;
197         GSList      *progress_widgets;
198
199         /* Tollbar items */
200         GtkWidget   *progress_toolitem;
201         GtkWidget   *cancel_toolitem;
202         GtkWidget   *sort_toolitem;
203         GtkWidget   *refresh_toolitem;
204         ModestToolBarModes current_toolbar_mode;
205
206         /* Merge ids used to add/remove accounts to the ViewMenu*/
207         GByteArray *merge_ids;
208         GtkActionGroup *view_additions_group;
209
210         /* On-demand widgets */
211         GtkWidget *accounts_popup;
212         GtkWidget *details_widget;
213
214         /* Optimized view enabled */
215         gboolean optimized_view;
216
217         /* Optimized view enabled */
218         gboolean send_receive_in_progress;
219
220         ModestHeaderView *header_view;
221         ModestFolderView *folder_view;
222
223         ModestMainWindowStyle style;
224         ModestMainWindowContentsStyle contents_style;
225         gboolean wait_for_settings;
226
227         guint progress_bar_timeout;
228         guint restore_paned_timeout;
229
230         /* Signal handler UIDs */
231         GList *queue_err_signals;
232         GSList *sighandlers;
233
234         /* "Updating" banner for header view */
235         GtkWidget *updating_banner;
236         guint updating_banner_timeout;
237
238         /* "Opening" banner for header view */
239         GtkWidget *opening_banner;
240         guint opening_banner_timeout;
241
242         /* Display state */
243         osso_display_state_t display_state;
244 };
245 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
246                                                 MODEST_TYPE_MAIN_WINDOW, \
247                                                 ModestMainWindowPrivate))
248
249 typedef struct _GetMsgAsyncHelper {
250         ModestMainWindowPrivate *main_window_private;
251         guint action;
252         ModestTnyMsgReplyType reply_type;
253         ModestTnyMsgForwardType forward_type;
254         gchar *from;
255         TnyIterator *iter;
256 } GetMsgAsyncHelper;
257
258
259 /* globals */
260 static GtkWindowClass *parent_class = NULL;
261
262
263 /* Private actions */
264 /* This is the context sensitive menu: */
265 static const GtkActionEntry modest_folder_view_action_entries [] = {
266
267         /* Folder View CSM actions */
268         { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
269         { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
270         { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL,  G_CALLBACK (modest_ui_actions_on_paste)},
271         { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
272         { "FolderViewCSMSearchMessages", NULL, N_("mcen_me_inbox_search"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_search_messages) },
273         { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_csm_help) },
274 };
275
276 static const GtkActionEntry modest_header_view_action_entries [] = {
277
278         /* Header View CSM actions */
279         { "HeaderViewCSMOpen",          NULL,  N_("mcen_me_inbox_open"),        NULL,       NULL, G_CALLBACK (modest_ui_actions_on_open) },
280         { "HeaderViewCSMReply",         NULL,  N_("mcen_me_inbox_reply"),       NULL,      NULL, G_CALLBACK (modest_ui_actions_on_reply) },
281         { "HeaderViewCSMReplyAll",      NULL,  N_("mcen_me_inbox_replytoall"),  NULL,      NULL, G_CALLBACK (modest_ui_actions_on_reply_all) },
282         { "HeaderViewCSMForward",       NULL,  N_("mcen_me_inbox_forward"),     NULL,      NULL, G_CALLBACK (modest_ui_actions_on_forward) },
283         { "HeaderViewCSMCut",           NULL,  N_("mcen_me_inbox_cut"),         "<CTRL>X", NULL, G_CALLBACK (modest_ui_actions_on_cut) },
284         { "HeaderViewCSMCopy",          NULL,  N_("mcen_me_inbox_copy"),        "<CTRL>C", NULL, G_CALLBACK (modest_ui_actions_on_copy) },
285         { "HeaderViewCSMPaste",         NULL,  N_("mcen_me_inbox_paste"),       "<CTRL>V", NULL, G_CALLBACK (modest_ui_actions_on_paste) },
286         { "HeaderViewCSMDelete",        NULL,  N_("mcen_me_inbox_delete"),      NULL,      NULL, G_CALLBACK (modest_ui_actions_on_delete_message) },
287         { "HeaderViewCSMCancelSending", NULL,  N_("mcen_me_outbox_cancelsend"), NULL,      NULL, G_CALLBACK (modest_ui_actions_cancel_send) },
288         { "HeaderViewCSMHelp",          NULL,  N_("mcen_me_inbox_help"),        NULL,      NULL, G_CALLBACK (modest_ui_actions_on_help) },
289 };
290
291 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
292         { "ToggleFolders",     MODEST_STOCK_SPLIT_VIEW, N_("mcen_me_inbox_hidefolders"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), TRUE },
293 };
294
295 /************************************************************************/
296
297 GType
298 modest_main_window_get_type (void)
299 {
300         static GType my_type = 0;
301         if (!my_type) {
302                 static const GTypeInfo my_info = {
303                         sizeof(ModestMainWindowClass),
304                         NULL,           /* base init */
305                         NULL,           /* base finalize */
306                         (GClassInitFunc) modest_main_window_class_init,
307                         NULL,           /* class finalize */
308                         NULL,           /* class data */
309                         sizeof(ModestMainWindow),
310                         1,              /* n_preallocs */
311                         (GInstanceInitFunc) modest_main_window_init,
312                         NULL
313                 };
314                 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
315                                                   "ModestMainWindow",
316                                                   &my_info, 0);
317         }
318         return my_type;
319 }
320
321 static void
322 modest_main_window_class_init (ModestMainWindowClass *klass)
323 {
324         GObjectClass *gobject_class;
325         gobject_class = (GObjectClass*) klass;
326         ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
327
328         parent_class            = g_type_class_peek_parent (klass);
329         gobject_class->finalize = modest_main_window_finalize;
330
331         g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
332         
333         modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
334         modest_window_class->save_state_func = save_state;
335         modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
336         modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
337         modest_window_class->disconnect_signals_func = modest_main_window_disconnect_signals;
338 }
339
340 static void
341 modest_main_window_init (ModestMainWindow *obj)
342 {
343         ModestMainWindowPrivate *priv;
344
345         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
346
347         priv->queue_err_signals = NULL;
348         priv->msg_paned    = NULL;
349         priv->main_paned   = NULL;      
350         priv->main_vbox    = NULL;
351         priv->header_view  = NULL;
352         priv->folder_view  = NULL;
353         priv->contents_widget  = NULL;
354         priv->accounts_popup  = NULL;
355         priv->details_widget  = NULL;
356         priv->empty_view  = NULL;
357         priv->progress_widgets  = NULL;
358         priv->progress_bar = NULL;
359         priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
360         priv->style  = MODEST_MAIN_WINDOW_STYLE_SPLIT;
361         priv->wait_for_settings = TRUE;
362         priv->contents_style  = -1; /* invalid contents style. We need this to select it for the first time */
363         priv->merge_ids = NULL;
364         priv->optimized_view  = FALSE;
365         priv->send_receive_in_progress  = FALSE;
366         priv->progress_bar_timeout = 0;
367         priv->restore_paned_timeout = 0;
368         priv->sighandlers = NULL;
369         priv->updating_banner = NULL;
370         priv->updating_banner_timeout = 0;
371         priv->opening_banner = NULL;
372         priv->opening_banner_timeout = 0;
373         priv->display_state = OSSO_DISPLAY_ON;
374         
375         modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
376                                             GTK_WINDOW(obj),
377                                             "applications_email_mainview");
378 }
379
380 static void
381 modest_main_window_finalize (GObject *obj)
382 {
383         ModestMainWindowPrivate *priv;
384
385         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
386
387         /* Sanity check: shouldn't be needed, the window mgr should
388            call this function before */
389         modest_main_window_disconnect_signals (MODEST_WINDOW (obj));    
390         modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj);
391
392         if (priv->empty_view) {
393                 g_object_unref (priv->empty_view);
394                 priv->empty_view = NULL;
395         }
396         
397         if (priv->header_view) {
398                 g_object_unref (priv->header_view);
399                 priv->header_view = NULL;
400         }
401         
402         g_slist_free (priv->progress_widgets);
403
404         g_byte_array_free (priv->merge_ids, TRUE);
405
406         if (priv->progress_bar_timeout > 0) {
407                 g_source_remove (priv->progress_bar_timeout);
408                 priv->progress_bar_timeout = 0;
409         }
410
411         if (priv->updating_banner_timeout > 0) {
412                 g_source_remove (priv->updating_banner_timeout);
413                 priv->updating_banner_timeout = 0;
414         }
415
416         if (priv->updating_banner) {
417                 gtk_widget_destroy (priv->updating_banner);
418                 priv->updating_banner = NULL;
419         }
420
421         if (priv->opening_banner_timeout > 0) {
422                 g_source_remove (priv->opening_banner_timeout);
423                 priv->opening_banner_timeout = 0;
424         }
425
426         if (priv->opening_banner) {
427                 gtk_widget_destroy (priv->opening_banner);
428                 priv->opening_banner = NULL;
429         }
430
431         if (priv->restore_paned_timeout > 0) {
432                 g_source_remove (priv->restore_paned_timeout);
433                 priv->restore_paned_timeout = 0;
434         }
435         
436         G_OBJECT_CLASS(parent_class)->finalize (obj);
437 }
438
439 GtkWidget*
440 modest_main_window_get_child_widget (ModestMainWindow *self,
441                                      ModestMainWindowWidgetType widget_type)
442 {
443         ModestMainWindowPrivate *priv;
444         GtkWidget *widget;
445         
446         g_return_val_if_fail (self && MODEST_IS_MAIN_WINDOW(self), NULL);
447         g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_MAIN_WINDOW_WIDGET_TYPE_NUM,
448                               NULL);
449         
450         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
451
452         switch (widget_type) {
453         case MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW:
454                 widget = (GtkWidget*)priv->header_view; break;
455         case MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW:
456                 widget = (GtkWidget*)priv->folder_view; break;
457         default:
458                 return NULL;
459         }
460
461         /* Note that the window could have been destroyed, and so
462            their children, but still have some references */
463         return (widget && GTK_IS_WIDGET(widget)) ? GTK_WIDGET(widget) : NULL;
464 }
465
466 static gboolean 
467 restore_paned_timeout_handler (gpointer *data)
468 {
469         ModestMainWindow *main_window = MODEST_MAIN_WINDOW (data);
470         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
471         ModestConf *conf;
472
473         /* Timeouts are outside the main lock */
474         gdk_threads_enter ();
475         if (GTK_WIDGET_VISIBLE (main_window)) {
476                 conf = modest_runtime_get_conf ();
477                 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
478                                               MODEST_CONF_MAIN_PANED_KEY);
479         }
480         gdk_threads_leave ();
481
482         return FALSE;
483 }
484
485
486 static void
487 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
488 {
489         ModestConf *conf;
490         ModestMainWindowPrivate *priv;
491
492         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
493
494         conf = modest_runtime_get_conf ();
495
496         modest_widget_memory_restore (conf, G_OBJECT(self),
497                                       MODEST_CONF_MAIN_WINDOW_KEY);
498
499         modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
500                                       MODEST_CONF_HEADER_VIEW_KEY);
501
502         if (do_folder_view_too)
503                 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
504                                       MODEST_CONF_FOLDER_VIEW_KEY);
505
506 /*      modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned), */
507 /*                                    MODEST_CONF_MAIN_PANED_KEY); */
508
509         g_timeout_add (250, (GSourceFunc) restore_paned_timeout_handler, self);
510
511         /* We need to force a redraw here in order to get the right
512            position of the horizontal paned separator */
513         gtk_widget_show (GTK_WIDGET (self));
514 }
515
516
517 static void
518 save_state (ModestWindow *window)
519 {
520         ModestConf *conf;
521         ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
522         ModestMainWindowPrivate *priv;
523                 
524         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
525         conf = modest_runtime_get_conf ();
526         
527         modest_widget_memory_save (conf,G_OBJECT(self), 
528                                    MODEST_CONF_MAIN_WINDOW_KEY);
529         /* Only save main paned position if we're in split mode */
530         if (priv->style == MODEST_MAIN_WINDOW_STYLE_SPLIT)
531                 modest_widget_memory_save (conf, G_OBJECT(priv->main_paned), 
532                                            MODEST_CONF_MAIN_PANED_KEY);
533         modest_widget_memory_save (conf, G_OBJECT(priv->folder_view), 
534                                    MODEST_CONF_FOLDER_VIEW_KEY);
535 }
536
537 static gint
538 compare_display_names (ModestAccountSettings *a,
539                        ModestAccountSettings *b)
540 {
541         return g_utf8_collate (modest_account_settings_get_display_name (a),
542                                modest_account_settings_get_display_name (b));
543
544 }
545
546 /* We use this function to prevent the send&receive CSM to be shown
547    when there are less than two account */
548 static gboolean
549 tap_and_hold_query_cb (GtkWidget *widget, GdkEvent *event)
550 {
551         return TRUE;
552 }
553
554 static void
555 update_menus (ModestMainWindow* self)
556 {       
557         GSList *account_names, *iter, *accounts;
558         ModestMainWindowPrivate *priv;
559         ModestWindowPrivate *parent_priv;
560         ModestAccountMgr *mgr;
561         gint i, num_accounts;
562         GList *groups;
563         gchar *default_account;
564         const gchar *active_account_name;
565         GtkWidget *send_receive_button, *item;
566         GtkAction *send_receive_all = NULL;
567         GSList *radio_group;
568
569         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
570         parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
571
572         /* Get enabled account IDs */
573         mgr = modest_runtime_get_account_mgr ();
574         account_names = modest_account_mgr_account_names (mgr, TRUE);
575         iter = account_names;
576         accounts = NULL;
577
578         while (iter) {
579                 ModestAccountSettings *settings = 
580                         modest_account_mgr_load_account_settings (mgr, (gchar*) iter->data);
581                 accounts = g_slist_prepend (accounts, settings);
582
583                 iter = iter->next;
584         }
585         modest_account_mgr_free_account_names (account_names);
586         account_names = NULL;
587
588         /* Order the list of accounts by its display name */
589         accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
590         num_accounts = g_slist_length (accounts);
591
592         send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager, 
593                                                       "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
594         gtk_action_set_visible (send_receive_all, num_accounts > 0);
595
596         /* Delete old send&receive popup items. We can not just do a
597            menu_detach because it does not work well with
598            tap_and_hold */
599         if (priv->accounts_popup)
600                 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup), 
601                                        (GtkCallback) gtk_widget_destroy, NULL);
602
603         /* Delete old entries in the View menu. Do not free groups, it
604            belongs to Gtk+ */
605         groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
606         while (groups) {
607                 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
608                              gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
609                         gtk_ui_manager_remove_action_group (parent_priv->ui_manager, 
610                                                             GTK_ACTION_GROUP (groups->data));
611                         groups = NULL;
612                         /* Remove uis */
613                         if (priv->merge_ids) {
614                                 for (i = 0; i < priv->merge_ids->len; i++)
615                                         gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
616                                 g_byte_array_free (priv->merge_ids, TRUE);
617                         }
618                         /* We need to call this in order to ensure
619                            that the new actions are added in the right
620                            order (alphabetical) */
621                         gtk_ui_manager_ensure_update (parent_priv->ui_manager);
622                 } else 
623                         groups = g_list_next (groups);
624         }
625         priv->merge_ids = g_byte_array_sized_new (num_accounts);
626
627         /* Get send receive button */
628         send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
629                                                           "/ToolBar/ToolbarSendReceive");
630
631         /* Create the menu */
632         if (num_accounts > 1) {
633                 if (!priv->accounts_popup)
634                         priv->accounts_popup = gtk_menu_new ();
635                 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
636                 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
637                 g_signal_connect (G_OBJECT (item), 
638                                   "activate", 
639                                   G_CALLBACK (on_send_receive_csm_activated),
640                                   NULL);
641                 item = gtk_separator_menu_item_new ();
642                 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
643         }
644
645         /* Create a new action group */
646         default_account = modest_account_mgr_get_default_account (mgr);
647         active_account_name = modest_window_get_active_account (MODEST_WINDOW (self));
648         
649         if (!active_account_name) 
650                 modest_window_set_active_account (MODEST_WINDOW (self), default_account);
651         
652         priv->view_additions_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
653         radio_group = NULL;
654         for (i = 0; i < num_accounts; i++) {
655                 gchar *display_name = NULL;     
656                 const gchar *account_name;
657                 ModestAccountSettings *settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
658
659                 if (!settings) {
660                         g_warning ("%s: BUG: account_data == NULL", __FUNCTION__);
661                         continue;
662                 }
663                 account_name = modest_account_settings_get_account_name (settings);
664         
665                 if (default_account && account_name && 
666                     !(strcmp (default_account, account_name) == 0)) {
667                         display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"), 
668                                                         modest_account_settings_get_display_name (settings));
669                 } else {
670                         display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"), 
671                                                         modest_account_settings_get_display_name (settings));
672                 }
673
674                 
675                 
676                 /* Create action and add it to the action group. The
677                    action name must be the account name, this way we
678                    could know in the handlers the account to show */
679                 if (settings && account_name) {
680                         gchar* item_name, *refresh_action_name;
681                         guint8 merge_id = 0;
682                         GtkAction *view_account_action, *refresh_account_action;
683                         gchar *escaped_display_name;
684
685                         escaped_display_name = modest_text_utils_escape_mnemonics (display_name);
686
687                         view_account_action = GTK_ACTION (gtk_radio_action_new (account_name,
688                                                                                 escaped_display_name, NULL, NULL, 0));
689                         g_free (escaped_display_name);
690                         gtk_action_group_add_action (priv->view_additions_group, view_account_action);
691                         gtk_radio_action_set_group (GTK_RADIO_ACTION (view_account_action), radio_group);
692                         radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (view_account_action));
693
694                         if (active_account_name) {
695                                 if (active_account_name && account_name && 
696                                     (strcmp (active_account_name, account_name) == 0)) {
697                                         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (view_account_action), TRUE);
698                                 }
699                         }
700
701                         /* Add ui from account data. We allow 2^9-1 account
702                            changes in a single execution because we're
703                            downcasting the guint to a guint8 in order to use a
704                            GByteArray. It should be enough :-) */
705                         item_name = g_strconcat (account_name, "Menu", NULL);
706                         merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
707                         priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
708                         gtk_ui_manager_add_ui (parent_priv->ui_manager,
709                                                merge_id,
710                                                "/MenuBar/ViewMenu/ViewMenuAdditions",
711                                                item_name,
712                                                account_name,
713                                                GTK_UI_MANAGER_MENUITEM,
714                                                FALSE);
715
716                         /* Connect the action signal "activate" */
717                         g_signal_connect_after (G_OBJECT (view_account_action),
718                                                 "toggled",
719                                                 G_CALLBACK (on_show_account_action_toggled),
720                                                 self);
721
722                         /* Create the items for the Tools->Send&Receive submenu */
723                         refresh_action_name = g_strconcat ("SendReceive", account_name, NULL);
724                         refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name, 
725                                                                  display_name, NULL, NULL);
726                         gtk_action_group_add_action (priv->view_additions_group, refresh_account_action);
727
728                         merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
729                         priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
730                         gtk_ui_manager_add_ui (parent_priv->ui_manager, 
731                                                merge_id,
732                                                "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
733                                                item_name,
734                                                refresh_action_name,
735                                                GTK_UI_MANAGER_MENUITEM,
736                                                FALSE);
737                         g_free (refresh_action_name);
738
739                         g_signal_connect_data (G_OBJECT (refresh_account_action), 
740                                                "activate", 
741                                                G_CALLBACK (on_refresh_account_action_activated), 
742                                                g_strdup (account_name),
743                                                (GClosureNotify) g_free,
744                                                0);
745
746                         /* Create item and add it to the send&receive
747                            CSM. If there is only one account then
748                            it'll be no menu */
749                         if (num_accounts > 1) {
750                                 GtkWidget *label = gtk_label_new(NULL);
751                                 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
752                                 if (default_account && (strcmp(account_name, default_account) == 0)) {
753                                         gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
754                                         gtk_label_set_markup (GTK_LABEL (label), escaped);
755                                         g_free (escaped);
756                                 } else {
757                                         gtk_label_set_text (GTK_LABEL (label), display_name);
758                                 }
759
760                                 item = gtk_menu_item_new ();
761                                 gtk_container_add (GTK_CONTAINER (item), label);
762
763                                 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), 
764                                                         GTK_WIDGET (item));
765                                 g_signal_connect_data (G_OBJECT (item), 
766                                                        "activate", 
767                                                        G_CALLBACK (on_send_receive_csm_activated),
768                                                        g_strdup (account_name),
769                                                        (GClosureNotify) g_free,
770                                                        0);
771                         }
772                         g_free (item_name);
773                 }
774
775                 /* Frees */
776                 g_free (display_name);
777         }
778
779         gtk_ui_manager_insert_action_group (parent_priv->ui_manager, priv->view_additions_group, 1);
780
781         /* We cannot do this in the loop above because this relies on the action
782          * group being inserted. This makes the default account appear in bold.
783          * I agree it is a rather ugly way, but I don't see another possibility. armin. */
784         for (i = 0; i < num_accounts; i++) {
785                 gchar *item_name, *path;
786                 GtkWidget *item;
787                 ModestAccountSettings *settings;
788                 const gchar *account_name;
789                 gboolean is_default;
790
791                 settings = (ModestAccountSettings *) g_slist_nth_data (accounts, i);
792                 account_name = modest_account_settings_get_account_name (settings);
793                 is_default = (account_name && default_account && !strcmp (account_name, default_account));
794
795                 /* Get the item of the view menu */
796                 item_name = g_strconcat (account_name, "Menu", NULL);
797                 path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
798                 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
799                 g_free(path);
800                 
801                 if (item) {
802                         GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
803                         if (GTK_IS_LABEL (child)) {
804                                 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
805                                 if (is_default) {
806                                         gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
807                                         gtk_label_set_markup (GTK_LABEL (child), bold_name);
808                                         g_free (bold_name);
809                                 }
810                                 gtk_label_set_ellipsize (GTK_LABEL (child),  PANGO_ELLIPSIZE_END);
811                         }
812                 }
813                         
814                 /* Get the item of the tools menu */
815                 path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
816                 item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
817                 g_free (path);
818
819                 if (item) {
820                         GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
821                         if (GTK_IS_LABEL (child)) {
822                                 const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
823                                 if (is_default) {
824                                         gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
825                                         gtk_label_set_markup (GTK_LABEL (child), bold_name);
826                                         g_free (bold_name);
827                                 }
828                                 gtk_label_set_ellipsize (GTK_LABEL (child),  PANGO_ELLIPSIZE_END);
829                         }
830                 }
831
832                 g_free(item_name);
833                 g_object_unref (settings);
834         }
835
836         if (num_accounts > 1) {
837                 /* Disconnect the tap-and-hold-query if it's connected */
838                 if (modest_signal_mgr_is_connected (priv->sighandlers, 
839                                                     G_OBJECT (send_receive_button),
840                                                     "tap-and-hold-query"))
841                         priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers, 
842                                                                           G_OBJECT (send_receive_button),
843                                                                           "tap-and-hold-query");
844
845                 /* Mandatory in order to view the menu contents */
846                 gtk_widget_show_all (priv->accounts_popup);
847
848                 /* Setup tap_and_hold just if was not done before*/
849                 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
850                         gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
851         } else {
852                 /* Connect the tap-and-hold-query in order not to show the CSM */
853                 if (!modest_signal_mgr_is_connected (priv->sighandlers, 
854                                                      G_OBJECT (send_receive_button),
855                                                      "tap-and-hold-query"))
856                         priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, 
857                                                                        G_OBJECT (send_receive_button),
858                                                                        "tap-and-hold-query",
859                                                                        G_CALLBACK (tap_and_hold_query_cb), 
860                                                                        NULL);
861         }
862
863         /* Frees */
864         g_slist_free (accounts);
865         g_free (default_account);
866
867
868         /* Make sure that at least one account is viewed if there are any 
869          * accounts, for instance when adding the first account: */
870         set_at_least_one_account_visible (self);
871 }
872
873 static void
874 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
875 {
876         if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
877                 gtk_scrolled_window_add_with_viewport
878                         (GTK_SCROLLED_WINDOW(win), widget);
879         else
880                 gtk_container_add (GTK_CONTAINER(win),
881                                    widget);
882 }
883
884
885 typedef struct {
886         TnySendQueue *queue;
887         guint signal;
888 } QueueErrorSignal;
889
890 static void
891 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
892 {
893         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
894
895         GList *oerrsignals = priv->queue_err_signals;
896         while (oerrsignals) {
897                 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
898                 g_signal_handler_disconnect (esignal->queue, esignal->signal);
899                 g_slice_free (QueueErrorSignal, esignal);
900                 oerrsignals = g_list_next (oerrsignals);
901         }
902         g_list_free (priv->queue_err_signals);
903         priv->queue_err_signals = NULL;
904 }
905
906
907 static void
908 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
909 {
910         g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
911
912         /* Update dimmed */
913         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW(user_data));
914 }
915
916 static void
917 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
918 {
919         g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
920
921         /* Update visibility */
922
923         /* Update dimmed */
924         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW(user_data));
925 }
926
927 static void
928 modest_main_window_disconnect_signals (ModestWindow *self)
929 {       
930         ModestMainWindowPrivate *priv;  
931         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
932
933         modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
934         priv->sighandlers = NULL;       
935 }
936
937 static void
938 connect_signals (ModestMainWindow *self)
939 {       
940         ModestWindowPrivate *parent_priv;
941         ModestMainWindowPrivate *priv;
942         GtkWidget *menu;
943         
944         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
945         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
946
947         /* folder view */
948         
949         priv->sighandlers = 
950                 modest_signal_mgr_connect (priv->sighandlers,
951                                            G_OBJECT(priv->folder_view), "key-press-event",
952                                            G_CALLBACK(on_inner_widgets_key_pressed), self);
953         priv->sighandlers = 
954                 modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), 
955                                            "folder_selection_changed",
956                                            G_CALLBACK (on_folder_selection_changed), 
957                                            self);
958         priv->sighandlers = 
959                 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view), 
960                                            "folder-display-name-changed",
961                                            G_CALLBACK (modest_ui_actions_on_folder_display_name_changed), 
962                                            self);
963         priv->sighandlers = 
964                 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->folder_view), 
965                                            "focus-in-event", 
966                                            G_CALLBACK (on_folder_view_focus_in), 
967                                            self);
968
969         /* Folder view CSM */
970         menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
971         gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
972         priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "tap-and-hold",
973                                                        G_CALLBACK(_folder_view_csm_menu_activated),
974                                                        self);
975         /* header view */
976         priv->sighandlers = 
977                 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
978                                            G_CALLBACK(modest_ui_actions_on_header_selected), self);
979         priv->sighandlers = 
980                 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
981                                            G_CALLBACK(modest_ui_actions_on_header_activated), self);
982         priv->sighandlers = 
983                 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
984                                            G_CALLBACK(modest_ui_actions_on_item_not_found), self);
985         priv->sighandlers = 
986                 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
987                                            G_CALLBACK(on_inner_widgets_key_pressed), self);
988         priv->sighandlers = 
989                 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
990                                            G_CALLBACK(on_msg_count_changed), self);
991         priv->sighandlers = 
992                 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->header_view), "focus-in-event",
993                                            G_CALLBACK (on_header_view_focus_in), self);
994         priv->sighandlers = 
995                 modest_signal_mgr_connect (priv->sighandlers,
996                                            G_OBJECT (priv->header_view), 
997                                            "updating-msg-list",
998                                            G_CALLBACK (on_updating_msg_list), 
999                                            self);
1000         
1001         /* Header view CSM */
1002         menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
1003         gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
1004         priv->sighandlers = 
1005                 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "tap-and-hold",
1006                                            G_CALLBACK(_header_view_csm_menu_activated),
1007                                            self);
1008         
1009         /* window */
1010         priv->sighandlers = 
1011                 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (self), "window-state-event",
1012                                            G_CALLBACK (modest_main_window_window_state_event),
1013                                            NULL);
1014         /* we don't register this in sighandlers, as it should be run after disconnecting all signals,
1015          * in destroy stage */
1016         g_signal_connect (G_OBJECT (self), "destroy", G_CALLBACK (on_window_destroy), NULL);
1017
1018         g_signal_connect (G_OBJECT (self), "notify::visible", G_CALLBACK (on_window_hide), NULL);
1019
1020         /* Mail Operation Queue */
1021         priv->sighandlers = 
1022                 modest_signal_mgr_connect (priv->sighandlers,
1023                                            G_OBJECT (modest_runtime_get_mail_operation_queue ()),
1024                                            "queue-changed", 
1025                                            G_CALLBACK (on_queue_changed), self);
1026         
1027         /* Track changes in the device name */
1028         priv->sighandlers = 
1029                 modest_signal_mgr_connect (priv->sighandlers,
1030                                            G_OBJECT(modest_runtime_get_conf ()),
1031                                            "key_changed", 
1032                                            G_CALLBACK (on_configuration_key_changed), 
1033                                            self);
1034         
1035         /* Track account changes. We need to refresh the toolbar */
1036         priv->sighandlers = 
1037                 modest_signal_mgr_connect (priv->sighandlers,
1038                                            G_OBJECT (modest_runtime_get_account_store ()),
1039                                            "account_inserted", 
1040                                            G_CALLBACK (on_account_inserted),
1041                                            self);
1042         priv->sighandlers = 
1043                 modest_signal_mgr_connect (priv->sighandlers,
1044                                            G_OBJECT (modest_runtime_get_account_store ()),
1045                                            "account_removed", 
1046                                            G_CALLBACK (on_account_removed),
1047                                            self);
1048
1049         /* We need to refresh the send & receive menu to change the bold
1050          * account when the default account changes. */
1051         priv->sighandlers = 
1052                 modest_signal_mgr_connect (priv->sighandlers,
1053                                            G_OBJECT (modest_runtime_get_account_mgr ()),
1054                                            "default_account_changed", 
1055                                            G_CALLBACK (on_default_account_changed),
1056                                            self);
1057
1058         /* Account store */
1059         priv->sighandlers = 
1060                 modest_signal_mgr_connect (priv->sighandlers,
1061                                            G_OBJECT (modest_runtime_get_account_store ()),
1062                                            "account_changed", 
1063                                            G_CALLBACK (on_account_changed),
1064                                            self);
1065 }
1066
1067 static void 
1068 on_hildon_program_is_topmost_notify(GObject *self,
1069                                     GParamSpec *propert_param, 
1070                                     gpointer user_data)
1071 {
1072         HildonProgram *app = HILDON_PROGRAM (self);
1073         
1074         /* Note that use of hildon_program_set_can_hibernate() 
1075          * is generally referred to as "setting the killable flag", 
1076          * though hibernation does not seem equal to death.
1077          * murrayc */
1078                  
1079         if (hildon_program_get_is_topmost (app)) {
1080                 /* Prevent hibernation when the progam comes to the foreground,
1081                  * because hibernation should only happen when the application 
1082                  * is in the background: */
1083                 hildon_program_set_can_hibernate (app, FALSE);
1084
1085                 /* Remove new mail visual notifications */
1086                 modest_platform_remove_new_mail_notifications (TRUE);
1087         } else {
1088                 /* Allow hibernation if the program has gone to the background: */
1089                 
1090                 /* However, prevent hibernation while the settings are being changed: */
1091                 const gboolean hibernation_prevented = 
1092                         modest_window_mgr_get_hibernation_is_prevented (
1093                                                                         modest_runtime_get_window_mgr ()); 
1094         
1095                 if (hibernation_prevented)
1096                         hildon_program_set_can_hibernate (app, FALSE);
1097                 else {
1098                         /* Allow hibernation, after saving the state: */
1099                         modest_osso_save_state();
1100                         hildon_program_set_can_hibernate (app, TRUE);
1101                 }
1102         }       
1103 }
1104
1105 typedef struct
1106 {
1107         GtkWidget *folder_win;
1108         gulong handler_id;
1109 } ShowHelper;
1110
1111 static void
1112 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
1113 {
1114         ShowHelper *helper = (ShowHelper *) user_data;
1115         GtkWidget *folder_win = helper->folder_win;
1116         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1117         
1118         priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
1119         wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
1120
1121         gtk_widget_show (GTK_WIDGET (priv->folder_view));
1122
1123         /* Connect signals */
1124         connect_signals (MODEST_MAIN_WINDOW (self));
1125
1126         /* Set account store */
1127         tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
1128                                                   TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
1129
1130         /* Load previous osso state, for instance if we are being restored from 
1131          * hibernation:  */
1132         modest_osso_load_state ();
1133
1134         /* Restore window & widget settings */  
1135         priv->wait_for_settings = TRUE;
1136         restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
1137         priv->wait_for_settings = FALSE;
1138
1139         /* Check if accounts exist and show the account wizard if not */
1140         gboolean accounts_exist = 
1141                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1142
1143         if (!accounts_exist) {
1144                 /* This is necessary to have the main window shown behind the dialog 
1145                 It's an ugly hack... jschmid */
1146                 gtk_widget_show_all(GTK_WIDGET(self));
1147                 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
1148         } else {
1149                 update_menus (MODEST_MAIN_WINDOW (self));
1150         }
1151
1152         /* Never call this function again (NOTE that it could happen
1153            as we hide the main window instead of closing it while
1154            there are operations ongoing) and free the helper */
1155         g_signal_handler_disconnect (self, helper->handler_id);
1156         g_slice_free (ShowHelper, helper);
1157 }
1158
1159 static void 
1160 osso_display_event_cb (osso_display_state_t state, 
1161                        gpointer data)
1162 {
1163         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
1164
1165         priv->display_state = state;
1166
1167         /* Stop blinking if the screen becomes on */
1168         if (priv->display_state == OSSO_DISPLAY_ON)
1169                 modest_platform_remove_new_mail_notifications (TRUE);
1170 }
1171
1172 ModestWindow *
1173 modest_main_window_new (void)
1174 {
1175         ModestMainWindow *self = NULL;  
1176         ModestMainWindowPrivate *priv = NULL;
1177         ModestWindowPrivate *parent_priv = NULL;
1178         GtkWidget *folder_win = NULL;
1179         ModestDimmingRulesGroup *menu_rules_group = NULL;
1180         ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1181         GtkActionGroup *action_group = NULL;
1182         GError *error = NULL;
1183         HildonProgram *app;
1184         ModestConf *conf = NULL;
1185         GtkAction *action = NULL;
1186         GdkPixbuf *window_icon;
1187         ShowHelper *helper;
1188         
1189         self  = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1190         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1191         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1192
1193         parent_priv->ui_manager = gtk_ui_manager_new();
1194         parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1195
1196         action_group = gtk_action_group_new ("ModestMainWindowActions");
1197         gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1198
1199         menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1200         toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1201
1202         /* Add common actions */
1203         gtk_action_group_add_actions (action_group,
1204                                       modest_action_entries,
1205                                       G_N_ELEMENTS (modest_action_entries),
1206                                       self);
1207
1208         gtk_action_group_add_actions (action_group,
1209                                       modest_folder_view_action_entries,
1210                                       G_N_ELEMENTS (modest_folder_view_action_entries),
1211                                       self);
1212
1213         gtk_action_group_add_actions (action_group,
1214                                       modest_header_view_action_entries,
1215                                       G_N_ELEMENTS (modest_header_view_action_entries),
1216                                       self);
1217
1218         gtk_action_group_add_toggle_actions (action_group,
1219                                              modest_toggle_action_entries,
1220                                              G_N_ELEMENTS (modest_toggle_action_entries),
1221                                              self);
1222
1223         gtk_action_group_add_toggle_actions (action_group,
1224                                              modest_main_window_toggle_action_entries,
1225                                              G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1226                                              self);
1227
1228         gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1229         g_object_unref (action_group);
1230
1231         /* Load the UI definition */
1232         gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1233                                          MODEST_UIDIR "modest-main-window-ui.xml", &error);
1234         if (error != NULL) {
1235                 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1236                 g_error_free (error);
1237                 error = NULL;
1238         }
1239
1240         /* Add common dimming rules */
1241         modest_dimming_rules_group_add_rules (menu_rules_group, 
1242                                               modest_main_window_menu_dimming_entries,
1243                                               G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1244                                               MODEST_WINDOW (self));
1245         modest_dimming_rules_group_add_rules (toolbar_rules_group, 
1246                                               modest_main_window_toolbar_dimming_entries,
1247                                               G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1248                                               MODEST_WINDOW (self));
1249
1250         /* Insert dimming rules group for this window */
1251         modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1252         modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1253         g_object_unref (menu_rules_group);
1254         g_object_unref (toolbar_rules_group);
1255         
1256         /* Add accelerators */
1257         gtk_window_add_accel_group (GTK_WINDOW (self), 
1258                                     gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1259
1260         /* Menubar. Update the state of some toggles */
1261         parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1262         conf = modest_runtime_get_conf ();
1263         action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
1264                                             "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
1265         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1266                                       modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR, NULL));
1267         action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
1268                                             "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
1269         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1270                                       modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
1271         hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1272         gtk_widget_show (parent_priv->menubar);
1273
1274         /* Get device name */
1275         modest_maemo_utils_get_device_name ();
1276
1277         /* header view */
1278         priv->header_view =
1279                 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1280         g_object_ref (priv->header_view);
1281         if (!priv->header_view)
1282                 g_printerr ("modest: cannot instantiate header view\n");
1283         modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1284         modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1285                                       MODEST_CONF_HEADER_VIEW_KEY);
1286
1287         /* Other style properties of header view */
1288         g_object_set (G_OBJECT (priv->header_view), 
1289                       "rules-hint", FALSE,
1290                       NULL);
1291         /* gtk_widget_show (priv->header_view); */
1292
1293         /* Empty view */ 
1294         priv->empty_view = create_empty_view ();
1295         gtk_widget_show (priv->empty_view);
1296         g_object_ref (priv->empty_view);
1297                  
1298         /* Create scrolled windows */
1299         folder_win = gtk_scrolled_window_new (NULL, NULL);
1300         priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1301         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
1302                                         GTK_POLICY_NEVER,
1303                                         GTK_POLICY_AUTOMATIC);
1304         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1305                                         GTK_POLICY_NEVER,
1306                                         GTK_POLICY_AUTOMATIC);
1307         /* gtk_widget_show (priv->contents_widget); */
1308
1309         /* paned */
1310         priv->main_paned = gtk_hpaned_new ();
1311         gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
1312         gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
1313         gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
1314
1315         /* putting it all together... */
1316         priv->main_vbox = gtk_vbox_new (FALSE, 6);
1317         gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
1318         gtk_widget_show (priv->main_vbox);
1319         
1320         gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1321         
1322         app = hildon_program_get_instance ();
1323         hildon_program_add_window (app, HILDON_WINDOW (self));
1324         
1325         g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1326                 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1327
1328         /* Connect to "show" action. We delay the creation of some
1329            elements until that moment */
1330         helper = g_slice_new0 (ShowHelper);
1331         helper->folder_win = folder_win;
1332         helper->handler_id = g_signal_connect (G_OBJECT(self), "show",
1333                                                G_CALLBACK (modest_main_window_on_show), 
1334                                                helper);
1335         
1336         /* Set window icon */
1337         window_icon = modest_platform_get_icon (MODEST_APP_ICON, MODEST_ICON_SIZE_BIG);
1338         if (window_icon) {
1339                 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1340                 g_object_unref (window_icon);
1341         }
1342
1343         /* Listen for changes in the screen, we don't want to show a
1344            led pattern when the display is on for example */
1345         osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
1346                                       osso_display_event_cb,
1347                                       self); 
1348
1349         /* Dont't restore settings here, 
1350          * because it requires a gtk_widget_show(), 
1351          * and we don't want to do that until later,
1352          * so that the UI is not visible for non-menu D-Bus activation.
1353          */
1354
1355         return MODEST_WINDOW(self);
1356 }
1357
1358 void 
1359 modest_main_window_set_style (ModestMainWindow *self, 
1360                               ModestMainWindowStyle style)
1361 {
1362         ModestMainWindowPrivate *priv;
1363         ModestWindowPrivate *parent_priv;
1364         GtkAction *action;
1365         gboolean active;
1366         GtkTreeSelection *sel;
1367         GList *rows, *list;
1368         
1369         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1370
1371         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1372         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1373
1374         /* no change -> nothing to do */
1375         if (priv->style == style)
1376                 return;
1377
1378        /* Get toggle button and update the state if needed. This will
1379           happen only when the set_style is not invoked from the UI,
1380           for example when it's called from widget memory */
1381        action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1382        active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1383        if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1384            (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1385                g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1386                gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1387                g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1388        }
1389
1390        /* We need to store the selection because it's lost when the
1391           widget is reparented */
1392        sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->header_view));
1393        rows = gtk_tree_selection_get_selected_rows (sel, NULL);
1394
1395         priv->style = style;
1396         switch (style) {
1397         case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1398
1399                 if (!priv->wait_for_settings)
1400                         modest_widget_memory_save (modest_runtime_get_conf (), G_OBJECT (priv->main_paned),
1401                                                    MODEST_CONF_MAIN_PANED_KEY);
1402                 /* Remove main paned */
1403                 g_object_ref (priv->main_paned);
1404                 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1405
1406                 /* Reparent the contents widget to the main vbox */
1407                 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1408
1409                 break;
1410         case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1411                 /* Remove header view */
1412                 g_object_ref (priv->contents_widget);
1413                 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1414
1415                 /* Reparent the main paned */
1416                 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1417                 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1418
1419                 g_timeout_add (500, (GSourceFunc) restore_paned_timeout_handler, self);
1420
1421                 break;
1422         default:
1423                 g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL);
1424                 g_list_free (rows);
1425                 g_return_if_reached ();
1426         }
1427
1428         /* Reselect the previously selected folders. We disable the
1429            dimming rules execution during that time because there is
1430            no need to work out it again and it could take a lot of
1431            time if all the headers are selected */
1432         list = rows;
1433         modest_window_disable_dimming (MODEST_WINDOW (self));
1434         while (list) {
1435                 gtk_tree_selection_select_path (sel, (GtkTreePath *) list->data);
1436                 list = g_list_next (list);
1437         }
1438         modest_window_enable_dimming (MODEST_WINDOW (self));
1439
1440         /* Free */
1441         g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL);
1442         g_list_free (rows);
1443
1444         /* Let header view grab the focus if it's being shown */
1445         if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS) {
1446                 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1447         } else {
1448                 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SPLIT)
1449                         gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1450                 else
1451                         gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1452         }
1453
1454         /* Check dimming rules */
1455         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1456         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1457
1458         /* Show changes */
1459         gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1460 }
1461
1462 ModestMainWindowStyle
1463 modest_main_window_get_style (ModestMainWindow *self)
1464 {
1465         ModestMainWindowPrivate *priv;
1466
1467         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1468
1469         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1470         return priv->style;
1471 }
1472
1473 static void
1474 toolbar_resize (ModestMainWindow *self)
1475 {
1476         ModestMainWindowPrivate *priv = NULL;
1477         ModestWindowPrivate *parent_priv = NULL;
1478         GtkWidget *widget;
1479         gint static_button_size;
1480         ModestWindowMgr *mgr;
1481
1482         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1483         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1484         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1485
1486         mgr = modest_runtime_get_window_mgr ();
1487         static_button_size = modest_window_mgr_get_fullscreen_mode (mgr)?118:108;
1488
1489         if (parent_priv->toolbar) {
1490                 /* left size buttons */
1491                 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageNew");
1492                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1493                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1494                 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1495                 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReply");
1496                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1497                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1498                 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1499                 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarDeleteMessage");
1500                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1501                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1502                 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1503                 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1504                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1505                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1506                 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1507                 
1508                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1509                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1510                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1511                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1512                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1513                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1514                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1515                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1516         }
1517                 
1518 }
1519
1520
1521
1522 static gboolean
1523 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1524 {
1525         if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1526                 ModestWindowPrivate *parent_priv;
1527                 ModestWindowMgr *mgr;
1528                 gboolean is_fullscreen;
1529                 GtkAction *fs_toggle_action;
1530                 gboolean active;
1531                 
1532                 mgr = modest_runtime_get_window_mgr ();
1533                 
1534                 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1535
1536                 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1537                 
1538                 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1539                 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1540                 if (is_fullscreen != active) {
1541                         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1542                 }
1543
1544                 toolbar_resize (MODEST_MAIN_WINDOW (widget));
1545         }
1546
1547         return FALSE;
1548
1549 }
1550
1551 static void 
1552 modest_main_window_show_toolbar (ModestWindow *self,
1553                                  gboolean show_toolbar)
1554 {
1555         ModestMainWindowPrivate *priv = NULL;
1556         ModestWindowPrivate *parent_priv = NULL;        
1557         GtkWidget *reply_button = NULL, *menu = NULL;
1558         GtkWidget *placeholder = NULL;
1559         gint insert_index;
1560         const gchar *action_name;
1561         GtkAction *action;
1562
1563         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1564         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1565         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1566
1567         /* Set optimized view status */
1568         priv->optimized_view = !show_toolbar;
1569
1570         if (!parent_priv->toolbar) {
1571                 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, 
1572                                                                   "/ToolBar");
1573                 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1574
1575                 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1576                 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1577                 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1578                 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1579                 toolbar_resize (MODEST_MAIN_WINDOW (self));
1580                 
1581                 /* Add ProgressBar (Transfer toolbar) */ 
1582                 priv->progress_bar = modest_progress_bar_new ();
1583                 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1584                 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1585                 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1586                 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1587                 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1588                 
1589                 /* Connect cancel 'clicked' signal to abort progress mode */
1590                 g_signal_connect(priv->cancel_toolitem, "clicked",
1591                                  G_CALLBACK(cancel_progressbar),
1592                                  self);
1593                 
1594                 /* Add it to the observers list */
1595                 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1596
1597                 /* Add to window */
1598                 hildon_window_add_toolbar (HILDON_WINDOW (self), 
1599                                            GTK_TOOLBAR (parent_priv->toolbar));
1600
1601                 /* Set reply button tap and hold menu */
1602                 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager, 
1603                                                           "/ToolBar/ToolbarMessageReply");
1604                 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1605                                                   "/ToolbarReplyCSM");
1606                 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1607
1608                 /* Set send & receive button tap and hold menu */
1609                 update_menus (MODEST_MAIN_WINDOW (self));
1610         }
1611         
1612         if (show_toolbar) {
1613                 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */ 
1614                 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1615                 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1616
1617                 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1618                 if (modest_main_window_transfer_mode_enabled (MODEST_MAIN_WINDOW(self)))
1619                         set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_TRANSFER);
1620                 else
1621                         set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1622         } else {
1623                 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1624
1625         }
1626
1627         /* Update also the actions (to update the toggles in the
1628            menus), we have to do it manually because some other window
1629            of the same time could have changed it (remember that the
1630            toolbar fullscreen mode is shared by all the windows of the
1631            same type */
1632         if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
1633                 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu";
1634         else
1635                 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu";
1636
1637         action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
1638         modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1639                                                             show_toolbar);
1640 }
1641
1642 static void
1643 on_account_inserted (TnyAccountStore *accoust_store,
1644                      TnyAccount *account,
1645                      gpointer user_data)
1646 {
1647         /* Transport accounts and local ones (MMC and the Local
1648            folders account do now cause menu changes */
1649         if (TNY_IS_STORE_ACCOUNT (account) && 
1650             modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1651                 /* Update menus */
1652                 update_menus (MODEST_MAIN_WINDOW (user_data));
1653         }
1654 }
1655
1656 static void
1657 on_default_account_changed (ModestAccountMgr* mgr,
1658                             gpointer user_data)
1659 {
1660         update_menus (MODEST_MAIN_WINDOW (user_data));
1661 }
1662
1663 static void
1664 on_account_removed (TnyAccountStore *accoust_store,
1665                      TnyAccount *account,
1666                      gpointer user_data)
1667 {
1668         /* Transport accounts and local ones (MMC and the Local
1669            folders account do now cause menu changes */
1670         if (TNY_IS_STORE_ACCOUNT (account) && 
1671             modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1672                 update_menus (MODEST_MAIN_WINDOW (user_data));
1673 }
1674
1675 static void
1676 on_account_changed (TnyAccountStore *account_store,
1677                     TnyAccount *account,
1678                     gpointer user_data)
1679 {
1680         ModestMainWindow *win = MODEST_MAIN_WINDOW (user_data);
1681
1682         /* Transport accounts and local ones (MMC and the Local
1683            folders account do now cause menu changes */
1684         if (TNY_IS_STORE_ACCOUNT (account)) {
1685                 /* We need to refresh the details widget because it could have changed */
1686                 if (modest_main_window_get_contents_style(win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1687                         modest_main_window_set_contents_style (win, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1688
1689                 /* Update the menus as well, name could change */
1690                 if (modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1691                         update_menus (MODEST_MAIN_WINDOW (user_data));
1692         }
1693 }
1694
1695 /* 
1696  * This function manages the key events used to navigate between
1697  * header and folder views (when the window is in split view)
1698  *
1699  * FROM         KEY        ACTION
1700  * -------------------------------------------------
1701  * HeaderView   GDK_Left   Move focus to folder view
1702  * FolderView   GDK_Right  Move focus to header view
1703  *
1704  * There is no need to scroll to selected row, the widgets will be the
1705  * responsibles of doing that (probably managing the focus-in event
1706  */
1707 static gboolean 
1708 on_inner_widgets_key_pressed (GtkWidget *widget,
1709                               GdkEventKey *event,
1710                               gpointer user_data)
1711 {
1712         ModestMainWindowPrivate *priv;
1713
1714         if (event->type == GDK_KEY_RELEASE)
1715                 return FALSE;
1716
1717         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1718
1719         /* Do nothing if we're in SIMPLE style */
1720         if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1721                 return FALSE;
1722
1723         if (MODEST_IS_HEADER_VIEW (widget)) {
1724                 if (event->keyval == GDK_Left || event->keyval == GDK_KP_Left)
1725                         gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1726                 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1727                         guint selected_headers = modest_header_view_count_selected_headers (MODEST_HEADER_VIEW (widget));
1728                         if (selected_headers > 1) {
1729                                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1730                                 return TRUE;
1731                         } else {
1732                                 GtkTreePath * cursor_path;
1733                                 gtk_tree_view_get_cursor (GTK_TREE_VIEW (widget), &cursor_path, NULL);
1734                                 if (cursor_path == NULL) {
1735                                         GtkTreeSelection *selection;
1736                                         GList *list;
1737                                         selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
1738                                         list = gtk_tree_selection_get_selected_rows (selection, NULL);
1739
1740                                         if (list != NULL)
1741                                                 gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget), (GtkTreePath *) list->data, NULL, FALSE);
1742                                         g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
1743                                         g_list_free (list);
1744                                 }
1745                         }
1746                 }
1747         } else if (MODEST_IS_FOLDER_VIEW (widget) && 
1748                    (event->keyval == GDK_Right || event->keyval == GDK_KP_Right || event->keyval == GDK_Left || event->keyval == GDK_KP_Left)) {
1749 #if GTK_CHECK_VERSION(2, 8, 0) /* TODO: gtk_tree_view_get_visible_range() is only available in GTK+ 2.8 */
1750                 GtkTreePath *selected_path = NULL;
1751                 GtkTreePath *start_path = NULL;
1752                 GtkTreePath *end_path = NULL;
1753                 GList *selected;
1754                 GtkTreeSelection *selection;
1755
1756                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->header_view));
1757                 selected = gtk_tree_selection_get_selected_rows (selection, NULL);
1758                 if (selected != NULL) {
1759                         selected_path = (GtkTreePath *) selected->data;
1760                         if (gtk_tree_view_get_visible_range (GTK_TREE_VIEW (priv->header_view),
1761                                                              &start_path,
1762                                                              &end_path)) {
1763                                 
1764                                 if ((gtk_tree_path_compare (start_path, selected_path) != -1) ||
1765                                     (gtk_tree_path_compare (end_path, selected_path) != 1)) {
1766                                         
1767                                         /* Scroll to first path */
1768                                         gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (priv->header_view),
1769                                                                       selected_path,
1770                                                                       NULL,
1771                                                                       TRUE,
1772                                                                       0.5,
1773                                                                       0.0);
1774                                 }
1775                         }
1776                         if (start_path)
1777                                 gtk_tree_path_free (start_path);
1778                         if (end_path)
1779                                 gtk_tree_path_free (end_path);
1780                         g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL);
1781                         g_list_free (selected);
1782                 }
1783 #endif /* GTK_CHECK_VERSION */
1784                         /* fix scroll */
1785                 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1786         }
1787
1788         return FALSE;
1789 }
1790
1791 static void
1792 set_alignment (GtkWidget *widget,
1793                gpointer data)
1794 {
1795         gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1796         gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1797 }
1798
1799 static GtkWidget *
1800 create_empty_view (void)
1801 {
1802         GtkLabel *label = NULL;
1803         GtkWidget *align = NULL;
1804
1805         align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1806         label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1807         gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);      
1808         gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1809
1810         return GTK_WIDGET(align);
1811 }
1812
1813 /*
1814  * Free the returned string
1815  */
1816 static gchar *
1817 get_gray_color_markup (GtkWidget *styled_widget)
1818 {
1819         gchar *gray_color_markup = NULL;
1820 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1821         /* Obtain the secondary text color. We need a realized widget, that's why 
1822            we get styled_widget from outside */
1823         GdkColor color;
1824         if (gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color)) 
1825                 gray_color_markup = modest_text_utils_get_color_string (&color);
1826 #endif /*MODEST_HAVE_HILDON0_WIDGETS*/
1827         
1828         if (!gray_color_markup) 
1829                 gray_color_markup = g_strdup ("#BBBBBB");
1830
1831         return gray_color_markup;
1832 }
1833
1834 /*
1835  * Free the returned string
1836  */
1837 static gchar*
1838 create_device_name_visual_string (const gchar *device_name,
1839                                   const gchar *gray_color_markup)
1840 {
1841         gchar *tmp, *label;
1842
1843         /* We have to use "" to fill the %s of the translation. We can
1844            not just use the device name because the device name is
1845            shown in a different color, so it could not be included
1846            into the <span> tag */
1847         tmp = g_strdup_printf (_("mcen_fi_localroot_description"), "");
1848         label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s", 
1849                                          gray_color_markup, 
1850                                          tmp, 
1851                                          device_name);
1852         g_free (tmp);
1853
1854         return label;
1855 }
1856
1857 typedef struct
1858 {
1859         GtkWidget *count_label;
1860         GtkWidget *msg_count_label;
1861         GtkWidget *size_label;
1862         gchar *color_markup;
1863 } DetailsWidgets;
1864
1865 static gchar *
1866 create_uint_label (const gchar *markup,
1867                    const gchar *name,
1868                    guint count)
1869 {
1870         return g_markup_printf_escaped ("<span color='%s'>%s:</span> %d", markup, name, count);
1871 }
1872
1873 static gchar *
1874 create_gchar_label (const gchar *markup,
1875                     const gchar *name,
1876                     gchar *count)
1877 {
1878         return g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", markup, name, count);
1879 }
1880
1881 static void
1882 update_folder_stats_status_cb (ModestFolderStats stats,
1883                                gpointer user_data)
1884 {
1885         DetailsWidgets *widgets = (DetailsWidgets *) user_data;
1886         gchar *label, *tmp;
1887
1888         label = create_uint_label (widgets->color_markup, _("mcen_fi_rootfolder_folders"), stats.folders);
1889         gtk_label_set_markup (GTK_LABEL (widgets->count_label), label);
1890         g_free (label);
1891
1892         label = create_uint_label (widgets->color_markup, _("mcen_fi_rootfolder_messages"), stats.msg_count);
1893         gtk_label_set_markup (GTK_LABEL (widgets->msg_count_label), label);
1894         g_free (label);
1895
1896         if (widgets->size_label) {
1897                 tmp = modest_text_utils_get_display_size (stats.local_size);
1898                 label = create_gchar_label (widgets->color_markup, _("mcen_fi_rootfolder_size"), tmp);
1899                 gtk_label_set_markup (GTK_LABEL (widgets->size_label), label);
1900                 g_free (label);
1901                 g_free (tmp);
1902         }
1903 }
1904
1905 static void
1906 update_folder_stats_cb (ModestFolderStats stats,
1907                         gpointer user_data)
1908 {
1909         DetailsWidgets *widgets = (DetailsWidgets *) user_data;
1910
1911         /* refresh data */
1912         update_folder_stats_status_cb (stats, user_data);
1913
1914         /* frees. Note that the widgets could have been destroyed but
1915            we still keep a reference */
1916         g_free (widgets->color_markup);
1917         if (widgets->count_label)
1918                 g_object_unref (widgets->count_label);
1919         if (widgets->msg_count_label)
1920                 g_object_unref (widgets->msg_count_label);
1921         if (widgets->size_label)
1922         g_object_unref (widgets->size_label);
1923         g_slice_free (DetailsWidgets, widgets);
1924 }
1925
1926 static GtkWidget *
1927 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1928 {
1929         /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1930         
1931         GtkWidget *vbox;
1932         GtkWidget *label_w;
1933         gchar *label;
1934         gchar *gray_color_markup;
1935         DetailsWidgets *widgets;
1936
1937         vbox = gtk_vbox_new (FALSE, 0);
1938         widgets = g_slice_new0 (DetailsWidgets);
1939
1940         gray_color_markup = get_gray_color_markup (styled_widget);
1941         widgets->color_markup = g_strdup (gray_color_markup);
1942
1943         /* Account description: */
1944         if (modest_tny_account_is_virtual_local_folders (account)
1945                 || (modest_tny_account_is_memory_card_account (account))) {
1946         
1947                 /* Get device name */
1948                 gchar *device_name = NULL;
1949                 if (modest_tny_account_is_virtual_local_folders (account))
1950                         device_name = modest_conf_get_string (modest_runtime_get_conf(),
1951                                                       MODEST_CONF_DEVICE_NAME, NULL);
1952                 else
1953                         device_name = g_strdup (tny_account_get_name (account));
1954
1955                 label = create_device_name_visual_string ((const gchar *) device_name, 
1956                                                           (const gchar *) gray_color_markup);
1957                 label_w = gtk_label_new (NULL);
1958                 gtk_label_set_markup (GTK_LABEL (label_w), label);
1959                 gtk_label_set_ellipsize (GTK_LABEL (label_w),  PANGO_ELLIPSIZE_END);
1960                 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1961                 g_free (device_name);
1962                 g_free (label);
1963         } else {
1964                 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1965                         gtk_box_pack_start (GTK_BOX (vbox), 
1966                                 gtk_label_new (tny_account_get_name (account)), 
1967                                 FALSE, FALSE, 0);
1968                 } else {
1969                         /* Other accounts, such as IMAP and POP: */
1970                         
1971                         GString *proto;
1972                         gchar *tmp;
1973         
1974                         /* Put proto in uppercase */
1975                         proto = g_string_new (tny_account_get_proto (account));
1976                         proto = g_string_ascii_up (proto);
1977                         
1978                         /* note: mcen_fi_localroot_description is something like "%s account"
1979                          * however, we should display "%s account: %s"... therefore, ugly tmp */
1980                         tmp   = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1981                         label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", 
1982                                                          gray_color_markup, tmp, tny_account_get_name (account));
1983                         g_free (tmp);
1984
1985                         label_w = gtk_label_new (NULL);
1986                         gtk_label_set_markup (GTK_LABEL (label_w), label);
1987                         gtk_label_set_ellipsize (GTK_LABEL (label_w),  PANGO_ELLIPSIZE_END);
1988                         gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1989                         g_string_free (proto, TRUE);
1990                         g_free (label);
1991                 }
1992         }
1993
1994         /* Message count */
1995         TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1996         label = create_uint_label (gray_color_markup, _("mcen_fi_rootfolder_messages"), 0);
1997         label_w = gtk_label_new (NULL);
1998         gtk_label_set_markup (GTK_LABEL (label_w), label);
1999         gtk_label_set_ellipsize (GTK_LABEL (label_w),  PANGO_ELLIPSIZE_END);
2000         gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
2001         g_free (label);
2002
2003         widgets->msg_count_label = g_object_ref (label_w);
2004
2005         /* Folder count */
2006         label = create_uint_label (gray_color_markup, _("mcen_fi_rootfolder_folders"), 0);
2007         label_w = gtk_label_new (NULL);
2008         gtk_label_set_markup (GTK_LABEL (label_w), label);
2009         gtk_label_set_ellipsize (GTK_LABEL (label_w),  PANGO_ELLIPSIZE_END);
2010         gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
2011         g_free (label);
2012
2013         widgets->count_label = g_object_ref (label_w);
2014
2015         /* Size / Date */
2016         if (modest_tny_account_is_virtual_local_folders (account)
2017                 || modest_tny_account_is_memory_card_account (account)) {
2018
2019                 label = create_gchar_label (gray_color_markup, _("mcen_fi_rootfolder_size"), "0");
2020                 
2021                 label_w = gtk_label_new (NULL);
2022                 gtk_label_set_markup (GTK_LABEL (label_w), label);
2023                 gtk_label_set_ellipsize (GTK_LABEL (label_w),  PANGO_ELLIPSIZE_END);
2024                 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
2025                 g_free (label);
2026
2027                 widgets->size_label = g_object_ref (label_w);
2028
2029         } else if (TNY_IS_ACCOUNT(folder_store)) {
2030                 TnyAccount *account = TNY_ACCOUNT(folder_store);
2031                 
2032                 time_t last_updated;
2033                 const gchar *last_updated_string;
2034                 /* Get last updated from configuration */
2035                 last_updated = modest_account_mgr_get_last_updated (modest_runtime_get_account_mgr (), 
2036                                                                     tny_account_get_id (account));
2037
2038                 if (last_updated > 0) 
2039                         last_updated_string = modest_text_utils_get_display_date(last_updated);
2040                 else
2041                         last_updated_string = g_strdup (_("mcen_va_never"));
2042
2043                 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", 
2044                                                  gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
2045                 label_w = gtk_label_new (NULL);
2046                 gtk_label_set_markup (GTK_LABEL (label_w), label);
2047                 gtk_label_set_ellipsize (GTK_LABEL (label_w),  PANGO_ELLIPSIZE_END);
2048                 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
2049                 g_free (label);
2050         }
2051
2052         g_free (gray_color_markup);
2053
2054         /* Refresh folder stats asynchronously */
2055         modest_tny_folder_store_get_folder_stats (TNY_FOLDER_STORE (account),
2056                                                   update_folder_stats_cb,
2057                                                   update_folder_stats_status_cb,
2058                                                   widgets);
2059
2060         /* Set alignment */
2061         gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
2062
2063         return vbox;
2064 }
2065
2066 gboolean
2067 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
2068 {
2069         ModestMainWindowPrivate *priv = NULL;
2070         
2071         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2072
2073         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2074
2075         return priv->send_receive_in_progress;
2076 }
2077
2078 void 
2079 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
2080 {
2081         GtkAction *action = NULL;
2082         GtkWidget *widget = NULL;
2083         ModestMainWindowPrivate *priv = NULL;
2084                 
2085         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2086         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2087         
2088         priv->send_receive_in_progress  = TRUE;
2089
2090         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu"); 
2091         gtk_action_set_sensitive (action, FALSE);
2092 /*         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
2093 /*      gtk_action_set_sensitive (action, FALSE); */
2094         widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");       
2095         gtk_widget_set_sensitive (widget, FALSE);
2096
2097
2098 void 
2099 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
2100 {
2101         GtkAction *action = NULL;
2102         GtkWidget *widget = NULL;
2103         ModestMainWindowPrivate *priv = NULL;
2104                 
2105         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2106         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2107
2108         priv->send_receive_in_progress  = FALSE;
2109
2110         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu"); 
2111         gtk_action_set_sensitive (action, TRUE);
2112 /*         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu");     */
2113 /*      gtk_action_set_sensitive (action, TRUE); */
2114         widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");       
2115         gtk_widget_set_sensitive (widget, TRUE);
2116
2117
2118
2119 static void
2120 on_msg_count_changed (ModestHeaderView *header_view,
2121                       TnyFolder *folder,
2122                       TnyFolderChange *change,
2123                       ModestMainWindow *main_window)
2124 {
2125         gboolean refilter = FALSE;
2126         gboolean folder_empty = FALSE;
2127         gboolean all_marked_as_deleted = FALSE;
2128         ModestMainWindowPrivate *priv;
2129
2130         g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
2131         g_return_if_fail (TNY_IS_FOLDER(folder));
2132         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2133
2134         if (change != NULL) {
2135                 TnyFolderChangeChanged changed;
2136
2137                 changed = tny_folder_change_get_changed (change);
2138                 /* If something changes */
2139                 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
2140                         folder_empty = (((guint) tny_folder_change_get_new_all_count (change)) == 0);
2141                 else
2142                         folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
2143
2144                 /* Play a sound (if configured) and make the LED blink  */
2145                 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
2146                         modest_platform_push_email_notification ();
2147                 }
2148
2149                 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS)
2150                         refilter = TRUE;
2151         } else {
2152                 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
2153         }
2154
2155         /* Check if all messages are marked to be deleted */
2156         all_marked_as_deleted = modest_header_view_is_empty (header_view);
2157         folder_empty = folder_empty || all_marked_as_deleted;
2158
2159         /* Set contents style of headers view */
2160         if (folder_empty)  {
2161                 modest_main_window_set_contents_style (main_window,
2162                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2163                 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
2164         } else {
2165                 modest_main_window_set_contents_style (main_window,
2166                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2167         }
2168
2169         if (refilter)
2170                 modest_header_view_refilter (header_view);
2171 }
2172
2173
2174 void 
2175 modest_main_window_set_contents_style (ModestMainWindow *self, 
2176                                        ModestMainWindowContentsStyle style)
2177 {
2178         ModestMainWindowPrivate *priv;
2179
2180         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2181
2182         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2183
2184         /* We allow to set the same content style than the previously
2185            set if there are details, because it could happen when we're
2186            selecting different accounts consecutively */
2187         if ((priv->contents_style == style) &&
2188             (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
2189                 return;
2190
2191         /* Remove previous child. Delete it if it was an account
2192            details widget */
2193         GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
2194         if (content) {
2195                 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
2196                         gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
2197                 }
2198                 
2199                 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
2200         }
2201
2202         priv->contents_style = style;
2203
2204         switch (priv->contents_style) {
2205         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
2206                 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
2207                 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2208                                                       TRUE);
2209                 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
2210                         gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
2211                 break;
2212         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
2213         {
2214                 /* if we're started without main win, there may not be a folder
2215                  * view. this fixes a GLib-Critical */
2216                 if (priv->folder_view) {
2217                         TnyFolderStore *selected_folderstore = 
2218                                 modest_folder_view_get_selected (priv->folder_view);
2219                         if (TNY_IS_ACCOUNT (selected_folderstore)) {    
2220                                 priv->details_widget = create_details_widget (GTK_WIDGET (self),
2221                                                                 TNY_ACCOUNT (selected_folderstore));
2222                                 
2223                                 wrap_in_scrolled_window (priv->contents_widget, 
2224                                                          priv->details_widget);
2225                         }
2226                         if (selected_folderstore)
2227                                 g_object_unref (selected_folderstore);
2228                         modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2229                                                               FALSE);
2230                 }
2231                 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
2232                         gtk_widget_grab_focus (GTK_WIDGET (priv->details_widget));
2233                 break;
2234         }
2235         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
2236                 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
2237                 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2238                                                       FALSE);
2239                 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
2240                         gtk_widget_grab_focus (GTK_WIDGET (priv->empty_view));
2241                 break;
2242         default:
2243                 g_return_if_reached ();
2244         }
2245
2246         /* Show */
2247         gtk_widget_show_all (priv->contents_widget);
2248 }
2249
2250 ModestMainWindowContentsStyle
2251 modest_main_window_get_contents_style (ModestMainWindow *self)
2252 {
2253         ModestMainWindowPrivate *priv;
2254
2255         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
2256
2257         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2258         return priv->contents_style;
2259 }
2260
2261
2262 static void 
2263 on_configuration_key_changed (ModestConf* conf, 
2264                               const gchar *key, 
2265                               ModestConfEvent event,
2266                               ModestConfNotificationId id, 
2267                               ModestMainWindow *self)
2268 {
2269         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2270         TnyAccount *account = NULL;
2271
2272         if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
2273                 return;
2274
2275         if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
2276                 return;
2277
2278         if (priv->folder_view) 
2279                 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
2280
2281         if (account && TNY_IS_ACCOUNT (account) &&
2282             strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
2283                 GList *children;
2284                 GtkLabel *label;
2285                 const gchar *device_name;
2286                 gchar *new_text, *gray_color_markup;
2287                 
2288                 /* Get label */
2289                 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
2290                 label = GTK_LABEL (children->data);
2291                 
2292                 device_name = modest_conf_get_string (modest_runtime_get_conf(),
2293                                                       MODEST_CONF_DEVICE_NAME, NULL);
2294
2295                 gray_color_markup = get_gray_color_markup (GTK_WIDGET (self));          
2296                 new_text = create_device_name_visual_string (device_name, gray_color_markup);
2297                 
2298                 gtk_label_set_markup (label, new_text);
2299                 gtk_widget_show (GTK_WIDGET (label));
2300                 
2301                 g_free (gray_color_markup);
2302                 g_free (new_text);
2303                 g_list_free (children);
2304         }
2305         g_object_unref (account);
2306 }
2307
2308 static gboolean
2309 set_toolbar_transfer_mode (ModestMainWindow *self)
2310 {
2311         ModestMainWindowPrivate *priv = NULL;
2312         
2313         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2314
2315         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2316
2317         set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
2318         
2319         if (priv->progress_bar_timeout > 0) {
2320                 g_source_remove (priv->progress_bar_timeout);
2321                 priv->progress_bar_timeout = 0;
2322         }
2323
2324         return FALSE;
2325 }
2326
2327 static void 
2328 set_toolbar_mode (ModestMainWindow *self, 
2329                   ModestToolBarModes mode)
2330 {
2331         ModestWindowPrivate *parent_priv = NULL;
2332         ModestMainWindowPrivate *priv = NULL;
2333         GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
2334         
2335         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2336
2337         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2338         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2339
2340         /* In case this was called before the toolbar exists: */
2341         if (!(parent_priv->toolbar))
2342                 return;
2343
2344         g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar)); 
2345         
2346         sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
2347         refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
2348         cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
2349
2350         /* Sets current toolbar mode */
2351         priv->current_toolbar_mode = mode;
2352
2353         /* Checks the dimming rules */
2354         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2355         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2356
2357         /* Show and hide toolbar items */
2358         switch (mode) {
2359         case TOOLBAR_MODE_NORMAL:
2360                 if (sort_action)
2361                         gtk_action_set_visible (sort_action, TRUE);
2362                 if (refresh_action)
2363                         gtk_action_set_visible (refresh_action, TRUE);
2364                 if (priv->progress_toolitem) {
2365                         gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
2366                         gtk_widget_hide (priv->progress_toolitem);
2367                 }
2368                 if (priv->progress_bar)
2369                         gtk_widget_hide (priv->progress_bar);
2370                 
2371                 if (cancel_action)
2372                         gtk_action_set_visible (cancel_action, FALSE);
2373
2374                 /* Hide toolbar if optimized view is enabled */
2375                 if (priv->optimized_view)
2376                         gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
2377                 break;
2378         case TOOLBAR_MODE_TRANSFER:
2379                 if (sort_action)
2380                         gtk_action_set_visible (sort_action, FALSE);
2381                 if (refresh_action)
2382                         gtk_action_set_visible (refresh_action, FALSE);
2383                 if (cancel_action)
2384                         gtk_action_set_visible (cancel_action, TRUE);
2385                 if (priv->progress_bar)
2386                         gtk_widget_show (priv->progress_bar);
2387                 if (priv->progress_toolitem) {
2388                         gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
2389                         gtk_widget_show (priv->progress_toolitem);
2390                 }
2391
2392                 /* Show toolbar if it's hiden (optimized view ) */
2393                 if (priv->optimized_view)
2394                         gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2395                 break;
2396         default:
2397                 g_return_if_reached ();
2398         }
2399 }
2400
2401 gboolean
2402 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
2403 {
2404         ModestMainWindowPrivate *priv;
2405
2406         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2407         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2408
2409         return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
2410 }
2411
2412 static void
2413 cancel_progressbar (GtkToolButton *toolbutton,
2414                     ModestMainWindow *self)
2415 {
2416         GSList *tmp;
2417         ModestMainWindowPrivate *priv;
2418         
2419         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2420
2421         /* Get operation observers and cancel all the operations */
2422         tmp = priv->progress_widgets;
2423         while (tmp) {
2424                 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2425                 tmp=g_slist_next(tmp);
2426         }
2427 }
2428
2429 static gboolean
2430 observers_empty (ModestMainWindow *self)
2431 {
2432         GSList *tmp = NULL;
2433         ModestMainWindowPrivate *priv;
2434         gboolean is_empty = TRUE;
2435         guint pending_ops = 0;
2436  
2437         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2438         tmp = priv->progress_widgets;
2439
2440         /* Check all observers */
2441         while (tmp && is_empty)  {
2442                 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2443                 is_empty = pending_ops == 0;
2444                 
2445                 tmp = g_slist_next(tmp);
2446         }
2447         
2448         return is_empty;
2449 }
2450
2451
2452 /**
2453  * Gets the toolbar mode needed for each mail operation. It stores in
2454  * @mode_changed if the toolbar mode has changed or not
2455  */
2456 static ModestToolBarModes
2457 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
2458                                       ModestMailOperation *mail_op,
2459                                       gboolean *mode_changed)
2460 {
2461         ModestToolBarModes mode;
2462         ModestMainWindowPrivate *priv;
2463
2464         *mode_changed = FALSE;
2465         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2466
2467         /* Get toolbar mode from operation id*/
2468         switch (modest_mail_operation_get_type_operation (mail_op)) {
2469         case MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE:
2470         case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2471                 mode = TOOLBAR_MODE_TRANSFER;
2472                 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2473                         *mode_changed = TRUE;
2474                 break;
2475         default:
2476                 mode = TOOLBAR_MODE_NORMAL;             
2477         }
2478         return mode;
2479 }
2480
2481 static void 
2482 on_mail_operation_started (ModestMailOperation *mail_op,
2483                            gpointer user_data)
2484 {
2485         ModestMainWindow *self;
2486         ModestMailOperationTypeOperation op_type;
2487         ModestMainWindowPrivate *priv;
2488         ModestToolBarModes mode;
2489         GSList *tmp;
2490         gboolean mode_changed = FALSE;
2491         TnyAccount *account = NULL;
2492
2493         self = MODEST_MAIN_WINDOW (user_data);
2494         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2495
2496         /* Do not show progress for receiving operations if the
2497            account is the local account or the MMC one */
2498         op_type = modest_mail_operation_get_type_operation (mail_op);
2499         account = modest_mail_operation_get_account (mail_op);
2500         if (account && op_type == MODEST_MAIL_OPERATION_TYPE_OPEN) {
2501                 gboolean is_remote;
2502
2503                 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2504                               modest_tny_account_is_memory_card_account (account));
2505                 if (!is_remote) {
2506                         g_object_unref (account);
2507                         return;
2508                 }
2509
2510                 /* Show information banner. Remove old timeout */
2511                 if (priv->opening_banner_timeout > 0) {
2512                         g_source_remove (priv->opening_banner_timeout);
2513                         priv->opening_banner_timeout = 0;
2514                 }
2515                 /* Create a new timeout */
2516                 priv->opening_banner_timeout = 
2517                         g_timeout_add (2000, show_opening_banner, self);
2518         }
2519
2520         /* Not every mail operation has account, noop does not */
2521         if (account)
2522                 g_object_unref (account);
2523                
2524         /* Get toolbar mode from operation id*/
2525         mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2526
2527         /* Add operation observers and change toolbar if neccessary*/
2528         tmp = priv->progress_widgets;
2529         if (mode == TOOLBAR_MODE_TRANSFER) {
2530                 if (mode_changed) {
2531                         GObject *source = modest_mail_operation_get_source(mail_op);
2532                         if (G_OBJECT (self) == source) {
2533                                 set_toolbar_transfer_mode(self);
2534                         }
2535                         g_object_unref (source);
2536                 }
2537
2538                 while (tmp) {
2539                         modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2540                                                               mail_op);
2541                         tmp = g_slist_next (tmp);
2542                 }
2543         }
2544
2545         /* Update the main menu as well, we need to explicitely do
2546            this in order to enable/disable accelerators */
2547         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2548 }
2549
2550 static void 
2551 on_mail_operation_finished (ModestMailOperation *mail_op,
2552                             gpointer user_data)
2553 {
2554         ModestToolBarModes mode;
2555         ModestMailOperationTypeOperation op_type;
2556         GSList *tmp = NULL;
2557         ModestMainWindow *self;
2558         gboolean mode_changed;
2559         TnyAccount *account = NULL;
2560         ModestMainWindowPrivate *priv;
2561
2562         self = MODEST_MAIN_WINDOW (user_data);
2563         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2564
2565         /* The mail operation was not added to the progress objects if
2566            the account was the local account or the MMC one */
2567         op_type = modest_mail_operation_get_type_operation (mail_op);
2568         account = modest_mail_operation_get_account (mail_op);
2569         if (account && op_type == MODEST_MAIL_OPERATION_TYPE_OPEN) {
2570                 gboolean is_remote;
2571
2572                 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2573                               modest_tny_account_is_memory_card_account (account));
2574                 if (!is_remote) {
2575                         g_object_unref (account);
2576                         return;
2577                 }
2578
2579                 /* Remove old timeout */
2580                 if (priv->opening_banner_timeout > 0) {
2581                         g_source_remove (priv->opening_banner_timeout);
2582                         priv->opening_banner_timeout = 0;
2583                 }
2584
2585                 /* Remove the banner if exists */
2586                 if (priv->opening_banner) {
2587                         gtk_widget_destroy (priv->opening_banner);
2588                         priv->opening_banner = NULL;
2589                 }
2590         }
2591
2592         /* Not every mail operation has account, noop does not */
2593         if (account)
2594                 g_object_unref (account);
2595
2596         /* Get toolbar mode from operation id*/
2597         mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2598
2599         /* Change toolbar mode */
2600         tmp = priv->progress_widgets;
2601         if (mode == TOOLBAR_MODE_TRANSFER) {                    
2602                 while (tmp) {
2603                         modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2604                                                                  mail_op);
2605                         tmp = g_slist_next (tmp);
2606                 }
2607                 
2608                 /* If no more operations are being observed, NORMAL mode is enabled again */
2609                 if (observers_empty (self)) {
2610                         set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);                           
2611                 }
2612         }
2613 }
2614
2615 static void
2616 on_queue_changed (ModestMailOperationQueue *queue,
2617                   ModestMailOperation *mail_op,
2618                   ModestMailOperationQueueNotification type,
2619                   ModestMainWindow *self)
2620 {
2621         ModestMainWindowPrivate *priv;
2622
2623         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2624
2625         if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2626                 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2627                                                                G_OBJECT (mail_op),
2628                                                                "operation-started",
2629                                                                G_CALLBACK (on_mail_operation_started),
2630                                                                self);
2631                 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2632                                                                G_OBJECT (mail_op),
2633                                                                "operation-finished",
2634                                                                G_CALLBACK (on_mail_operation_finished),
2635                                                                self);
2636         } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2637                 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2638                                                                   G_OBJECT (mail_op),
2639                                                                   "operation-started");
2640                 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2641                                                                   G_OBJECT (mail_op),
2642                                                                   "operation-finished");
2643         }
2644 }
2645
2646 static void
2647 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2648 {
2649         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2650         GtkAction *action;
2651         ModestAccountMgr *mgr;
2652         ModestAccountSettings *settings;
2653         ModestServerAccountSettings *store_settings = NULL;
2654
2655         /* Get account data */
2656         mgr = modest_runtime_get_account_mgr ();
2657         settings = modest_account_mgr_load_account_settings (mgr, acc_name);
2658         if (settings)
2659                 store_settings = modest_account_settings_get_store_settings (settings);
2660
2661         /* Set the new visible & active account */
2662         if (settings && (modest_server_account_settings_get_account_name (store_settings)!= NULL)) { 
2663                 const gchar *account_name;
2664
2665                 account_name = modest_account_settings_get_account_name (settings);
2666
2667                 modest_folder_view_set_account_id_of_visible_server_account 
2668                         (priv->folder_view,
2669                          modest_server_account_settings_get_account_name (store_settings));
2670                 modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2671                 modest_window_set_active_account (MODEST_WINDOW (self), account_name);
2672
2673                 action = gtk_action_group_get_action (priv->view_additions_group, account_name);
2674                 if (action != NULL) {
2675                         if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2676                                 modest_utils_toggle_action_set_active_block_notify (
2677                                         GTK_TOGGLE_ACTION (action),
2678                                         TRUE);
2679                         }
2680                 }
2681         }
2682         
2683         /* Free */
2684         if (settings) {
2685                 g_object_unref (store_settings);
2686                 g_object_unref (settings);
2687         }
2688 }
2689
2690 /* Make sure that at least one account is "viewed": */
2691 static void
2692 set_at_least_one_account_visible(ModestMainWindow *self)
2693 {
2694         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2695         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2696
2697         if (!(priv->folder_view)) {
2698                 /* It is too early to do this. */
2699                 return; 
2700         }
2701         
2702         const gchar *active_server_account_name = 
2703                 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2704         
2705         if (!active_server_account_name ||
2706                 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2707         {
2708                 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2709                 gchar* default_modest_name = modest_account_mgr_get_default_account (account_mgr);
2710                 if (default_modest_name) {
2711                         set_account_visible (self, default_modest_name);
2712                 } else if (first_modest_name) {
2713                         set_account_visible (self, first_modest_name);
2714                 }
2715                 g_free (first_modest_name);
2716                 g_free (default_modest_name);
2717         }
2718 }
2719
2720 static void 
2721 on_show_account_action_toggled  (GtkToggleAction *action,
2722                                    gpointer user_data)
2723 {
2724         ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2725
2726         const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2727         if (gtk_toggle_action_get_active (action))
2728                 set_account_visible (self, acc_name);
2729 }
2730
2731 static void
2732 refresh_account (const gchar *account_name)
2733 {
2734         ModestWindow *win;
2735         
2736         /* win must already exists here, obviously */ 
2737         win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
2738                                                  FALSE);
2739         if (!win) {
2740                 g_warning ("%s: BUG: no main window!", __FUNCTION__);
2741                 return;
2742         }
2743         
2744         /* If account_name == NULL, we must update all (option All) */
2745         if (!account_name)
2746                 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2747         else
2748                 modest_ui_actions_do_send_receive (account_name, TRUE, TRUE, TRUE, win);
2749         
2750 }
2751
2752 static void 
2753 on_refresh_account_action_activated  (GtkAction *action,
2754                                       gpointer user_data)
2755 {
2756         refresh_account ((const gchar*) user_data);
2757 }
2758
2759 static void
2760 on_send_receive_csm_activated (GtkMenuItem *item,
2761                                gpointer user_data)
2762 {
2763         refresh_account ((const gchar*) user_data);
2764 }
2765
2766 static gboolean
2767 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2768 {
2769         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2770
2771         hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2772         return FALSE;
2773
2774 }
2775
2776 static gboolean
2777 on_folder_view_focus_in (GtkWidget *widget, GdkEventFocus *event, gpointer userdata)
2778 {
2779         ModestMainWindow *main_window = NULL;
2780         
2781         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2782         main_window = MODEST_MAIN_WINDOW (userdata);
2783         
2784         /* Update toolbar dimming state */
2785         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2786         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2787
2788         return FALSE;
2789 }
2790
2791 static gboolean
2792 on_header_view_focus_in (GtkWidget *widget,
2793                          GdkEventFocus *event,
2794                          gpointer userdata)
2795 {
2796         ModestMainWindow *main_window = NULL;
2797
2798         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2799
2800         main_window = MODEST_MAIN_WINDOW (userdata);
2801
2802         /* Update toolbar dimming state */
2803         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2804         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2805
2806         return FALSE;
2807 }
2808
2809 static void 
2810 on_folder_selection_changed (ModestFolderView *folder_view,
2811                              TnyFolderStore *folder_store, 
2812                              gboolean selected,
2813                              ModestMainWindow *main_window)
2814 {
2815         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2816         GtkAction *action = NULL;
2817         gboolean show_reply = TRUE;
2818         gboolean show_forward = TRUE;
2819         gboolean show_cancel_send = FALSE;
2820         gboolean show_clipboard = TRUE;
2821         gboolean show_delete = TRUE;
2822
2823         if (selected) {
2824                 if (TNY_IS_ACCOUNT (folder_store)) {
2825                         show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2826                 } else if (TNY_IS_FOLDER (folder_store)) {
2827                         if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2828                                 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2829                                         TNY_FOLDER (folder_store));
2830                                 switch (folder_type) {
2831                                 case TNY_FOLDER_TYPE_DRAFTS:
2832                                         show_clipboard = show_delete = TRUE;
2833                                         show_reply = show_forward = show_cancel_send = FALSE;
2834                                         break;
2835                                 case TNY_FOLDER_TYPE_SENT:
2836                                         show_forward = show_clipboard = show_delete = TRUE;
2837                                         show_reply = show_cancel_send = FALSE;
2838                                         break;
2839                                 case TNY_FOLDER_TYPE_OUTBOX:
2840                                         show_clipboard = show_delete = show_cancel_send = TRUE;
2841                                         show_reply = show_forward = FALSE;
2842                                         break;
2843                                 case TNY_FOLDER_TYPE_INVALID:
2844                                         g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
2845                                         break;
2846                                 default:
2847                                         show_reply = show_forward = show_clipboard = show_delete = TRUE;
2848                                         show_cancel_send = FALSE;
2849                                 }
2850                         } else {
2851                                 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2852                                 show_cancel_send = FALSE;
2853                         }
2854                 }
2855         }
2856
2857         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2858         gtk_action_set_visible (action, show_reply);
2859         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2860         gtk_action_set_visible (action, show_reply);
2861         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2862         gtk_action_set_visible (action, show_forward);
2863         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2864         gtk_action_set_visible (action, show_cancel_send);
2865         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2866         gtk_action_set_visible (action, show_delete);
2867
2868         /* We finally call to the ui actions handler, after updating properly
2869          * the header view CSM */
2870         modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2871 }
2872
2873 gboolean 
2874 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2875                                                    GtkTreeModel *model,
2876                                                    GtkTreeRowReference *row_reference,
2877                                                    ModestMainWindow *self)
2878 {
2879         ModestMainWindowPrivate *priv = NULL;
2880         GtkTreeModel *header_model = NULL;
2881         GtkTreePath *path = NULL;
2882
2883         g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2884         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2885         g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2886
2887         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2888         header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2889
2890         /* Do nothing if we changed the folder in the main view */
2891         if (header_model != model)
2892                 return FALSE;
2893
2894         /* Select the message in the header view */
2895         path = gtk_tree_row_reference_get_path (row_reference);
2896         gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2897                                   path, NULL, FALSE);
2898         gtk_tree_path_free (path);
2899
2900         return TRUE;
2901 }
2902
2903 static void
2904 updating_banner_destroyed (gpointer data,
2905                            GObject *where_the_object_was)
2906 {
2907         ModestMainWindowPrivate *priv = NULL;
2908
2909         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
2910
2911         priv->updating_banner = NULL;
2912 }
2913
2914 static gboolean
2915 show_updating_banner (gpointer user_data)
2916 {
2917         ModestMainWindowPrivate *priv = NULL;
2918
2919         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2920
2921         if (priv->updating_banner == NULL) {
2922
2923                 /* We're outside the main lock */
2924                 gdk_threads_enter ();
2925                 priv->updating_banner = 
2926                         modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2927                                                           _CS ("ckdg_pb_updating"));
2928
2929                 /* We need this because banners in Maemo could be
2930                    destroyed by dialogs so we need to properly update
2931                    our reference to it */
2932                 g_object_weak_ref (G_OBJECT (priv->updating_banner),
2933                                    updating_banner_destroyed,
2934                                    user_data);
2935                 gdk_threads_leave ();
2936         }
2937
2938         /* Remove timeout */
2939         priv->updating_banner_timeout = 0;
2940         return FALSE;
2941 }
2942
2943 /**
2944  * We use this function to show/hide a progress banner showing
2945  * "Updating" while the header view is being filled. We're not showing
2946  * it unless the update takes more than 2 seconds
2947  *
2948  * If starting = TRUE then the refresh is starting, otherwise it means
2949  * that is has just finished
2950  */
2951 static void 
2952 on_updating_msg_list (ModestHeaderView *header_view,
2953                       gboolean starting,
2954                       gpointer user_data)
2955 {
2956         ModestMainWindowPrivate *priv = NULL;
2957
2958         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2959         
2960         /* Remove old timeout */
2961         if (priv->updating_banner_timeout > 0) {
2962                 g_source_remove (priv->updating_banner_timeout);
2963                 priv->updating_banner_timeout = 0;
2964         }
2965
2966         /* Create a new timeout */
2967         if (starting) {
2968                 priv->updating_banner_timeout = 
2969                         g_timeout_add (2000, show_updating_banner, user_data);
2970         } else {
2971                 /* Remove the banner if exists */
2972                 if (priv->updating_banner) {
2973                         gtk_widget_destroy (priv->updating_banner);
2974                         priv->updating_banner = NULL;
2975                 }
2976         }
2977 }
2978
2979 gboolean
2980 modest_main_window_screen_is_on (ModestMainWindow *self)
2981 {
2982         ModestMainWindowPrivate *priv = NULL;
2983
2984         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(self), FALSE);
2985
2986         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2987         
2988         return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE;
2989 }
2990
2991 static void
2992 remove_banners (ModestMainWindow *window)
2993 {
2994         ModestMainWindowPrivate *priv;
2995
2996         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (window);
2997
2998         if (priv->opening_banner_timeout > 0) {
2999                 g_source_remove (priv->opening_banner_timeout);
3000                 priv->opening_banner_timeout = 0;
3001         }
3002
3003         if (priv->opening_banner != NULL) {
3004                 gtk_widget_destroy (priv->opening_banner);
3005                 priv->opening_banner = NULL;
3006         }
3007         
3008         if (priv->updating_banner_timeout > 0) {
3009                 g_source_remove (priv->updating_banner_timeout);
3010                 priv->updating_banner_timeout = 0;
3011         }
3012
3013         if (priv->updating_banner != NULL) {
3014                 gtk_widget_destroy (priv->updating_banner);
3015                 priv->updating_banner = NULL;
3016         }       
3017 }
3018
3019
3020 static void
3021 on_window_hide (GObject    *gobject,
3022                 GParamSpec *arg1,
3023                 gpointer    user_data)
3024 {
3025         g_return_if_fail (MODEST_IS_MAIN_WINDOW (gobject));
3026
3027         if (!GTK_WIDGET_VISIBLE (gobject)) {
3028                 TnyFolderStore *folder_store;
3029                 ModestMainWindowPrivate *priv;
3030                 
3031                 /* Remove the currently shown banners */
3032                 remove_banners (MODEST_MAIN_WINDOW (gobject));
3033
3034                 /* Force the folder view to sync the currently selected folder
3035                    to save the read/unread status and to expunge messages */
3036                 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (gobject);
3037                 folder_store = modest_folder_view_get_selected (priv->folder_view);
3038                 if (TNY_IS_FOLDER (folder_store)) {
3039                         ModestMailOperation *mail_op;
3040                         
3041                         mail_op = modest_mail_operation_new (NULL);
3042                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3043                                                          mail_op);
3044                         modest_mail_operation_sync_folder (mail_op, TNY_FOLDER (folder_store), FALSE);
3045                         g_object_unref (mail_op);
3046                         g_object_unref (folder_store);
3047                 }
3048         }
3049 }
3050
3051 static void
3052 on_window_destroy (GtkObject *widget, 
3053                    gpointer user_data)
3054 {
3055         g_return_if_fail (MODEST_IS_MAIN_WINDOW (widget));
3056
3057         remove_banners (MODEST_MAIN_WINDOW (widget));
3058 }
3059
3060 static void
3061 opening_banner_destroyed (gpointer data,
3062                            GObject *where_the_object_was)
3063 {
3064         ModestMainWindowPrivate *priv = NULL;
3065
3066         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
3067
3068         priv->opening_banner = NULL;
3069 }
3070
3071 static gboolean
3072 show_opening_banner (gpointer user_data)
3073 {
3074         ModestMainWindowPrivate *priv = NULL;
3075
3076         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
3077
3078         if (priv->opening_banner == NULL) {
3079
3080                 /* We're outside the main lock */
3081                 gdk_threads_enter ();
3082                 priv->opening_banner = 
3083                         modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
3084                                                           _("mail_me_opening"));
3085
3086                 /* We need this because banners in Maemo could be
3087                    destroyed by dialogs so we need to properly update
3088                    our reference to it */
3089                 g_object_weak_ref (G_OBJECT (priv->opening_banner),
3090                                    opening_banner_destroyed,
3091                                    user_data);
3092
3093                 /* We need this because banners in Maemo could be
3094                    destroyed by dialogs so we need to properly update
3095                    our reference to it */
3096                 g_object_weak_ref (G_OBJECT (priv->updating_banner),
3097                                    updating_banner_destroyed,
3098                                    user_data);
3099                 gdk_threads_leave ();
3100         }
3101
3102         /* Remove timeout */
3103         priv->opening_banner_timeout = 0;
3104         return FALSE;
3105 }