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