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