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