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