* Fixes NB#84725, retrieve messages when the option "messages and attchaments" is...
[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
1056 static void 
1057 on_hildon_program_is_topmost_notify(GObject *self,
1058                                     GParamSpec *propert_param, 
1059                                     gpointer user_data)
1060 {
1061         HildonProgram *app = HILDON_PROGRAM (self);
1062         
1063         /* Note that use of hildon_program_set_can_hibernate() 
1064          * is generally referred to as "setting the killable flag", 
1065          * though hibernation does not seem equal to death.
1066          * murrayc */
1067                  
1068         if (hildon_program_get_is_topmost (app)) {
1069                 /* Prevent hibernation when the progam comes to the foreground,
1070                  * because hibernation should only happen when the application 
1071                  * is in the background: */
1072                 hildon_program_set_can_hibernate (app, FALSE);
1073
1074                 /* Remove new mail visual notifications */
1075                 modest_platform_remove_new_mail_notifications (TRUE);
1076         } else {
1077                 /* Allow hibernation if the program has gone to the background: */
1078                 
1079                 /* However, prevent hibernation while the settings are being changed: */
1080                 const gboolean hibernation_prevented = 
1081                         modest_window_mgr_get_hibernation_is_prevented (
1082                                                                         modest_runtime_get_window_mgr ()); 
1083         
1084                 if (hibernation_prevented)
1085                         hildon_program_set_can_hibernate (app, FALSE);
1086                 else {
1087                         /* Allow hibernation, after saving the state: */
1088                         modest_osso_save_state();
1089                         hildon_program_set_can_hibernate (app, TRUE);
1090                 }
1091         }       
1092 }
1093
1094 typedef struct
1095 {
1096         GtkWidget *folder_win;
1097         gulong handler_id;
1098 } ShowHelper;
1099
1100 static void
1101 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
1102 {
1103         ShowHelper *helper = (ShowHelper *) user_data;
1104         GtkWidget *folder_win = helper->folder_win;
1105         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1106         
1107         priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
1108         wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
1109
1110         gtk_widget_show (GTK_WIDGET (priv->folder_view));
1111
1112         /* Connect signals */
1113         connect_signals (MODEST_MAIN_WINDOW (self));
1114
1115         /* Set account store */
1116         tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
1117                                                   TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
1118
1119         /* Load previous osso state, for instance if we are being restored from 
1120          * hibernation:  */
1121         modest_osso_load_state ();
1122
1123         /* Restore window & widget settings */  
1124         priv->wait_for_settings = TRUE;
1125         restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
1126         priv->wait_for_settings = FALSE;
1127
1128         /* Check if accounts exist and show the account wizard if not */
1129         gboolean accounts_exist = 
1130                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1131
1132         if (!accounts_exist) {
1133                 /* This is necessary to have the main window shown behind the dialog 
1134                 It's an ugly hack... jschmid */
1135                 gtk_widget_show_all(GTK_WIDGET(self));
1136                 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
1137         } else {
1138                 GSList *accounts;
1139                 GtkAction *send_receive_all;
1140                 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1141                 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
1142                 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager, 
1143                                                               "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1144                 gtk_action_set_visible (send_receive_all, g_slist_length (accounts) > 0);
1145                 modest_account_mgr_free_account_names (accounts);
1146                 update_menus (MODEST_MAIN_WINDOW (self));
1147         }
1148
1149         /* Never call this function again (NOTE that it could happen
1150            as we hide the main window instead of closing it while
1151            there are operations ongoing) and free the helper */
1152         g_signal_handler_disconnect (self, helper->handler_id);
1153         g_slice_free (ShowHelper, helper);
1154 }
1155
1156 static void 
1157 osso_display_event_cb (osso_display_state_t state, 
1158                        gpointer data)
1159 {
1160         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data);
1161
1162         priv->display_state = state;
1163
1164         /* Stop blinking if the screen becomes on */
1165         if (priv->display_state == OSSO_DISPLAY_ON)
1166                 modest_platform_remove_new_mail_notifications (TRUE);
1167 }
1168
1169 ModestWindow *
1170 modest_main_window_new (void)
1171 {
1172         ModestMainWindow *self = NULL;  
1173         ModestMainWindowPrivate *priv = NULL;
1174         ModestWindowPrivate *parent_priv = NULL;
1175         GtkWidget *folder_win = NULL;
1176         ModestDimmingRulesGroup *menu_rules_group = NULL;
1177         ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1178         GtkActionGroup *action_group = NULL;
1179         GError *error = NULL;
1180         HildonProgram *app;
1181         ModestConf *conf = NULL;
1182         GtkAction *action = NULL;
1183         GdkPixbuf *window_icon;
1184         ShowHelper *helper;
1185         
1186         self  = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1187         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1188         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1189
1190         parent_priv->ui_manager = gtk_ui_manager_new();
1191         parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1192
1193         action_group = gtk_action_group_new ("ModestMainWindowActions");
1194         gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1195
1196         menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1197         toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1198
1199         /* Add common actions */
1200         gtk_action_group_add_actions (action_group,
1201                                       modest_action_entries,
1202                                       G_N_ELEMENTS (modest_action_entries),
1203                                       self);
1204
1205         gtk_action_group_add_actions (action_group,
1206                                       modest_folder_view_action_entries,
1207                                       G_N_ELEMENTS (modest_folder_view_action_entries),
1208                                       self);
1209
1210         gtk_action_group_add_actions (action_group,
1211                                       modest_header_view_action_entries,
1212                                       G_N_ELEMENTS (modest_header_view_action_entries),
1213                                       self);
1214
1215         gtk_action_group_add_toggle_actions (action_group,
1216                                              modest_toggle_action_entries,
1217                                              G_N_ELEMENTS (modest_toggle_action_entries),
1218                                              self);
1219
1220         gtk_action_group_add_toggle_actions (action_group,
1221                                              modest_main_window_toggle_action_entries,
1222                                              G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1223                                              self);
1224
1225         gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1226         g_object_unref (action_group);
1227
1228         /* Load the UI definition */
1229         gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1230                                          MODEST_UIDIR "modest-main-window-ui.xml", &error);
1231         if (error != NULL) {
1232                 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1233                 g_error_free (error);
1234                 error = NULL;
1235         }
1236
1237         /* Add common dimming rules */
1238         modest_dimming_rules_group_add_rules (menu_rules_group, 
1239                                               modest_main_window_menu_dimming_entries,
1240                                               G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1241                                               MODEST_WINDOW (self));
1242         modest_dimming_rules_group_add_rules (toolbar_rules_group, 
1243                                               modest_main_window_toolbar_dimming_entries,
1244                                               G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1245                                               MODEST_WINDOW (self));
1246
1247         /* Insert dimming rules group for this window */
1248         modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1249         modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1250         g_object_unref (menu_rules_group);
1251         g_object_unref (toolbar_rules_group);
1252         
1253         /* Add accelerators */
1254         gtk_window_add_accel_group (GTK_WINDOW (self), 
1255                                     gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1256
1257         /* Menubar. Update the state of some toggles */
1258         parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1259         conf = modest_runtime_get_conf ();
1260         action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
1261                                             "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
1262         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1263                                       modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR, NULL));
1264         action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
1265                                             "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
1266         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1267                                       modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
1268         hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1269         gtk_widget_show (parent_priv->menubar);
1270
1271         /* Get device name */
1272         modest_maemo_utils_get_device_name ();
1273
1274         /* header view */
1275         priv->header_view =
1276                 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1277         if (!priv->header_view)
1278                 g_printerr ("modest: cannot instantiate header view\n");
1279         modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1280         modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1281                                       MODEST_CONF_HEADER_VIEW_KEY);
1282
1283         /* Other style properties of header view */
1284         g_object_set (G_OBJECT (priv->header_view), 
1285                       "rules-hint", FALSE,
1286                       NULL);
1287         /* gtk_widget_show (priv->header_view); */
1288
1289         /* Empty view */ 
1290         priv->empty_view = create_empty_view ();
1291         gtk_widget_show (priv->empty_view);
1292                  
1293         /* Create scrolled windows */
1294         folder_win = gtk_scrolled_window_new (NULL, NULL);
1295         priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1296         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
1297                                         GTK_POLICY_NEVER,
1298                                         GTK_POLICY_AUTOMATIC);
1299         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1300                                         GTK_POLICY_NEVER,
1301                                         GTK_POLICY_AUTOMATIC);
1302         /* gtk_widget_show (priv->contents_widget); */
1303
1304         /* paned */
1305         priv->main_paned = gtk_hpaned_new ();
1306         gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
1307         gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
1308         gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
1309
1310         /* putting it all together... */
1311         priv->main_vbox = gtk_vbox_new (FALSE, 6);
1312         gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
1313         gtk_widget_show (priv->main_vbox);
1314         
1315         gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1316         
1317         app = hildon_program_get_instance ();
1318         hildon_program_add_window (app, HILDON_WINDOW (self));
1319         
1320         g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1321                 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1322
1323         /* Connect to "show" action. We delay the creation of some
1324            elements until that moment */
1325         helper = g_slice_new0 (ShowHelper);
1326         helper->folder_win = folder_win;
1327         helper->handler_id = g_signal_connect (G_OBJECT(self), "show",
1328                                                G_CALLBACK (modest_main_window_on_show), 
1329                                                helper);
1330         
1331         /* Set window icon */
1332         window_icon = modest_platform_get_icon (MODEST_APP_ICON, MODEST_ICON_SIZE_BIG);
1333         if (window_icon) {
1334                 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1335                 g_object_unref (window_icon);
1336         }
1337
1338         /* Listen for changes in the screen, we don't want to show a
1339            led pattern when the display is on for example */
1340         osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
1341                                       osso_display_event_cb,
1342                                       self); 
1343
1344         /* Dont't restore settings here, 
1345          * because it requires a gtk_widget_show(), 
1346          * and we don't want to do that until later,
1347          * so that the UI is not visible for non-menu D-Bus activation.
1348          */
1349
1350         return MODEST_WINDOW(self);
1351 }
1352
1353 void 
1354 modest_main_window_set_style (ModestMainWindow *self, 
1355                               ModestMainWindowStyle style)
1356 {
1357         ModestMainWindowPrivate *priv;
1358         ModestWindowPrivate *parent_priv;
1359         GtkAction *action;
1360         gboolean active;
1361
1362         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1363
1364         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1365         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1366
1367         /* no change -> nothing to do */
1368         if (priv->style == style)
1369                 return;
1370
1371        /* Get toggle button and update the state if needed. This will
1372           happen only when the set_style is not invoked from the UI,
1373           for example when it's called from widget memory */
1374        action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1375        active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1376        if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1377            (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1378                g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1379                gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1380                g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1381        }
1382
1383         priv->style = style;
1384         switch (style) {
1385         case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1386
1387                 if (!priv->wait_for_settings)
1388                         modest_widget_memory_save (modest_runtime_get_conf (), G_OBJECT (priv->main_paned),
1389                                                    MODEST_CONF_MAIN_PANED_KEY);
1390                 /* Remove main paned */
1391                 g_object_ref (priv->main_paned);
1392                 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1393
1394                 /* Reparent the contents widget to the main vbox */
1395                 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1396
1397                 break;
1398         case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1399                 /* Remove header view */
1400                 g_object_ref (priv->contents_widget);
1401                 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1402
1403                 /* Reparent the main paned */
1404                 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1405                 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1406
1407                 g_timeout_add (500, (GSourceFunc) restore_paned_timeout_handler, self);
1408
1409                 break;
1410         default:
1411                 g_return_if_reached ();
1412         }
1413
1414         /* Let header view grab the focus if it's being shown */
1415         if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1416                 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1417         else 
1418                 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1419
1420         /* Show changes */
1421         gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1422 }
1423
1424 ModestMainWindowStyle
1425 modest_main_window_get_style (ModestMainWindow *self)
1426 {
1427         ModestMainWindowPrivate *priv;
1428
1429         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1430
1431         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1432         return priv->style;
1433 }
1434
1435 static void
1436 toolbar_resize (ModestMainWindow *self)
1437 {
1438         ModestMainWindowPrivate *priv = NULL;
1439         ModestWindowPrivate *parent_priv = NULL;
1440         GtkWidget *widget;
1441         gint static_button_size;
1442         ModestWindowMgr *mgr;
1443
1444         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1445         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1446         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1447
1448         mgr = modest_runtime_get_window_mgr ();
1449         static_button_size = modest_window_mgr_get_fullscreen_mode (mgr)?118:108;
1450
1451         if (parent_priv->toolbar) {
1452                 /* left size buttons */
1453                 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageNew");
1454                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1455                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1456                 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1457                 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReply");
1458                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1459                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1460                 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1461                 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarDeleteMessage");
1462                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1463                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1464                 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1465                 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1466                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
1467                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
1468                 gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
1469                 
1470                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1471                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1472                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1473                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1474                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1475                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->refresh_toolitem), TRUE);
1476                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1477                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->sort_toolitem), TRUE);
1478         }
1479                 
1480 }
1481
1482
1483
1484 static gboolean
1485 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1486 {
1487         if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1488                 ModestWindowPrivate *parent_priv;
1489                 ModestWindowMgr *mgr;
1490                 gboolean is_fullscreen;
1491                 GtkAction *fs_toggle_action;
1492                 gboolean active;
1493                 
1494                 mgr = modest_runtime_get_window_mgr ();
1495                 
1496                 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1497
1498                 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1499                 
1500                 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1501                 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1502                 if (is_fullscreen != active) {
1503                         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1504                 }
1505
1506                 toolbar_resize (MODEST_MAIN_WINDOW (widget));
1507         }
1508
1509         return FALSE;
1510
1511 }
1512
1513 static void 
1514 modest_main_window_show_toolbar (ModestWindow *self,
1515                                  gboolean show_toolbar)
1516 {
1517         ModestMainWindowPrivate *priv = NULL;
1518         ModestWindowPrivate *parent_priv = NULL;        
1519         GtkWidget *reply_button = NULL, *menu = NULL;
1520         GtkWidget *placeholder = NULL;
1521         gint insert_index;
1522         const gchar *action_name;
1523         GtkAction *action;
1524
1525         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1526         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1527         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1528
1529         /* Set optimized view status */
1530         priv->optimized_view = !show_toolbar;
1531
1532         if (!parent_priv->toolbar) {
1533                 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, 
1534                                                                   "/ToolBar");
1535                 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1536
1537                 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1538                 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1539                 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1540                 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1541                 toolbar_resize (MODEST_MAIN_WINDOW (self));
1542                 
1543                 /* Add ProgressBar (Transfer toolbar) */ 
1544                 priv->progress_bar = modest_progress_bar_new ();
1545                 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1546                 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1547                 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1548                 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1549                 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1550                 
1551                 /* Connect cancel 'clicked' signal to abort progress mode */
1552                 g_signal_connect(priv->cancel_toolitem, "clicked",
1553                                  G_CALLBACK(cancel_progressbar),
1554                                  self);
1555                 
1556                 /* Add it to the observers list */
1557                 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1558
1559                 /* Add to window */
1560                 hildon_window_add_toolbar (HILDON_WINDOW (self), 
1561                                            GTK_TOOLBAR (parent_priv->toolbar));
1562
1563                 /* Set reply button tap and hold menu */
1564                 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager, 
1565                                                           "/ToolBar/ToolbarMessageReply");
1566                 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1567                                                   "/ToolbarReplyCSM");
1568                 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1569
1570                 /* Set send & receive button tap and hold menu */
1571                 update_menus (MODEST_MAIN_WINDOW (self));
1572         }
1573         
1574         if (show_toolbar) {
1575                 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */ 
1576                 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1577                 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1578
1579                 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1580                 if (modest_main_window_transfer_mode_enabled (MODEST_MAIN_WINDOW(self)))
1581                         set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_TRANSFER);
1582                 else
1583                         set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1584         } else {
1585                 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1586
1587         }
1588
1589         /* Update also the actions (to update the toggles in the
1590            menus), we have to do it manually because some other window
1591            of the same time could have changed it (remember that the
1592            toolbar fullscreen mode is shared by all the windows of the
1593            same type */
1594         if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
1595                 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu";
1596         else
1597                 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu";
1598
1599         action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
1600         modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1601                                                             show_toolbar);
1602 }
1603
1604 static void
1605 on_account_inserted (TnyAccountStore *accoust_store,
1606                      TnyAccount *account,
1607                      gpointer user_data)
1608 {
1609         /* Transport accounts and local ones (MMC and the Local
1610            folders account do now cause menu changes */
1611         if (TNY_IS_STORE_ACCOUNT (account) && 
1612             modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) {
1613                 /* Update menus */
1614                 update_menus (MODEST_MAIN_WINDOW (user_data));
1615         }
1616 }
1617
1618 static void
1619 on_default_account_changed (ModestAccountMgr* mgr,
1620                             gpointer user_data)
1621 {
1622         update_menus (MODEST_MAIN_WINDOW (user_data));
1623 }
1624
1625 static void
1626 on_account_removed (TnyAccountStore *accoust_store,
1627                      TnyAccount *account,
1628                      gpointer user_data)
1629 {
1630         /* Transport accounts and local ones (MMC and the Local
1631            folders account do now cause menu changes */
1632         if (TNY_IS_STORE_ACCOUNT (account) && 
1633             modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1634                 update_menus (MODEST_MAIN_WINDOW (user_data));
1635 }
1636
1637 static void
1638 on_account_changed (TnyAccountStore *account_store,
1639                     TnyAccount *account,
1640                     gpointer user_data)
1641 {
1642         ModestMainWindow *win = MODEST_MAIN_WINDOW (user_data);
1643
1644         /* Transport accounts and local ones (MMC and the Local
1645            folders account do now cause menu changes */
1646         if (TNY_IS_STORE_ACCOUNT (account)) {
1647                 /* We need to refresh the details widget because it could have changed */
1648                 if (modest_main_window_get_contents_style(win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1649                         modest_main_window_set_contents_style (win, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1650
1651                 /* Update the menus as well, name could change */
1652                 if (modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account)))
1653                         update_menus (MODEST_MAIN_WINDOW (user_data));
1654         }
1655 }
1656
1657 /* 
1658  * This function manages the key events used to navigate between
1659  * header and folder views (when the window is in split view)
1660  *
1661  * FROM         KEY        ACTION
1662  * -------------------------------------------------
1663  * HeaderView   GDK_Left   Move focus to folder view
1664  * FolderView   GDK_Right  Move focus to header view
1665  *
1666  * There is no need to scroll to selected row, the widgets will be the
1667  * responsibles of doing that (probably managing the focus-in event
1668  */
1669 static gboolean 
1670 on_inner_widgets_key_pressed (GtkWidget *widget,
1671                               GdkEventKey *event,
1672                               gpointer user_data)
1673 {
1674         ModestMainWindowPrivate *priv;
1675
1676         if (event->type == GDK_KEY_RELEASE)
1677                 return FALSE;
1678
1679         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1680
1681         /* Do nothing if we're in SIMPLE style */
1682         if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1683                 return FALSE;
1684
1685         if (MODEST_IS_HEADER_VIEW (widget)) {
1686                 if (event->keyval == GDK_Left)
1687                         gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1688                 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1689                         guint selected_headers = modest_header_view_count_selected_headers (MODEST_HEADER_VIEW (widget));
1690                         if (selected_headers > 1) {
1691                                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1692                                 return TRUE;
1693                         } else {
1694                                 GtkTreePath * cursor_path;
1695                                 gtk_tree_view_get_cursor (GTK_TREE_VIEW (widget), &cursor_path, NULL);
1696                                 if (cursor_path == NULL) {
1697                                         GtkTreeSelection *selection;
1698                                         GList *list;
1699                                         selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
1700                                         list = gtk_tree_selection_get_selected_rows (selection, NULL);
1701
1702                                         if (list != NULL)
1703                                                 gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget), (GtkTreePath *) list->data, NULL, FALSE);
1704                                         g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
1705                                         g_list_free (list);
1706                                 }
1707                         }
1708                 }
1709         } else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1710                 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1711
1712         return FALSE;
1713 }
1714
1715 static void
1716 set_alignment (GtkWidget *widget,
1717                gpointer data)
1718 {
1719         gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1720         gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1721 }
1722
1723 static GtkWidget *
1724 create_empty_view (void)
1725 {
1726         GtkLabel *label = NULL;
1727         GtkWidget *align = NULL;
1728
1729         align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1730         label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1731         gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);      
1732         gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1733
1734         return GTK_WIDGET(align);
1735 }
1736
1737 /*
1738  * Free the returned string
1739  */
1740 static gchar *
1741 get_gray_color_markup (GtkWidget *styled_widget)
1742 {
1743         gchar *gray_color_markup = NULL;
1744 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1745         /* Obtain the secondary text color. We need a realized widget, that's why 
1746            we get styled_widget from outside */
1747         GdkColor color;
1748         if (gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color)) 
1749                 gray_color_markup = modest_text_utils_get_color_string (&color);
1750 #endif /*MODEST_HAVE_HILDON0_WIDGETS*/
1751         
1752         if (!gray_color_markup) 
1753                 gray_color_markup = g_strdup ("#BBBBBB");
1754
1755         return gray_color_markup;
1756 }
1757
1758 /*
1759  * Free the returned string
1760  */
1761 static gchar*
1762 create_device_name_visual_string (const gchar *device_name,
1763                                   const gchar *gray_color_markup)
1764 {
1765         gchar *tmp, *label;
1766
1767         /* We have to use "" to fill the %s of the translation. We can
1768            not just use the device name because the device name is
1769            shown in a different color, so it could not be included
1770            into the <span> tag */
1771         tmp = g_strdup_printf (_("mcen_fi_localroot_description"), "");
1772         label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s", 
1773                                          gray_color_markup, 
1774                                          tmp, 
1775                                          device_name);
1776         g_free (tmp);
1777
1778         return label;
1779 }
1780
1781 static GtkWidget *
1782 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1783 {
1784         /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1785         
1786         GtkWidget *vbox;
1787         GtkWidget *label_w;
1788         gchar *label;
1789         gchar *gray_color_markup;
1790
1791         vbox = gtk_vbox_new (FALSE, 0);
1792
1793         gray_color_markup = get_gray_color_markup (styled_widget);
1794
1795         /* Account description: */
1796         if (modest_tny_account_is_virtual_local_folders (account)
1797                 || (modest_tny_account_is_memory_card_account (account))) {
1798         
1799                 /* Get device name */
1800                 gchar *device_name = NULL;
1801                 if (modest_tny_account_is_virtual_local_folders (account))
1802                         device_name = modest_conf_get_string (modest_runtime_get_conf(),
1803                                                       MODEST_CONF_DEVICE_NAME, NULL);
1804                 else
1805                         device_name = g_strdup (tny_account_get_name (account));
1806
1807                 label = create_device_name_visual_string ((const gchar *) device_name, 
1808                                                           (const gchar *) gray_color_markup);
1809                 label_w = gtk_label_new (NULL);
1810                 gtk_label_set_markup (GTK_LABEL (label_w), label);
1811                 gtk_label_set_ellipsize (GTK_LABEL (label_w),  PANGO_ELLIPSIZE_END);
1812                 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1813                 g_free (device_name);
1814                 g_free (label);
1815         } else {
1816                 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1817                         gtk_box_pack_start (GTK_BOX (vbox), 
1818                                 gtk_label_new (tny_account_get_name (account)), 
1819                                 FALSE, FALSE, 0);
1820                 } else {
1821                         /* Other accounts, such as IMAP and POP: */
1822                         
1823                         GString *proto;
1824                         gchar *tmp;
1825         
1826                         /* Put proto in uppercase */
1827                         proto = g_string_new (tny_account_get_proto (account));
1828                         proto = g_string_ascii_up (proto);
1829                         
1830                         /* note: mcen_fi_localroot_description is something like "%s account"
1831                          * however, we should display "%s account: %s"... therefore, ugly tmp */
1832                         tmp   = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1833                         label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", 
1834                                                          gray_color_markup, tmp, tny_account_get_name (account));
1835                         g_free (tmp);
1836
1837                         label_w = gtk_label_new (NULL);
1838                         gtk_label_set_markup (GTK_LABEL (label_w), label);
1839                         gtk_label_set_ellipsize (GTK_LABEL (label_w),  PANGO_ELLIPSIZE_END);
1840                         gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1841                         g_string_free (proto, TRUE);
1842                         g_free (label);
1843                 }
1844         }
1845
1846         /* Message count */
1847         TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1848         label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d", 
1849                                          gray_color_markup, _("mcen_fi_rootfolder_messages"), 
1850                                          modest_tny_folder_store_get_message_count (folder_store));
1851         label_w = gtk_label_new (NULL);
1852         gtk_label_set_markup (GTK_LABEL (label_w), label);
1853         gtk_label_set_ellipsize (GTK_LABEL (label_w),  PANGO_ELLIPSIZE_END);
1854         gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1855         g_free (label);
1856
1857         /* Folder count */
1858         label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d", 
1859                                          gray_color_markup, 
1860                                          _("mcen_fi_rootfolder_folders"), 
1861                                          modest_tny_folder_store_get_folder_count (folder_store));
1862         label_w = gtk_label_new (NULL);
1863         gtk_label_set_markup (GTK_LABEL (label_w), label);
1864         gtk_label_set_ellipsize (GTK_LABEL (label_w),  PANGO_ELLIPSIZE_END);
1865         gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1866         g_free (label);
1867
1868         /* Size / Date */
1869         if (modest_tny_account_is_virtual_local_folders (account)
1870                 || modest_tny_account_is_memory_card_account (account)) {
1871
1872                 gchar *size = modest_text_utils_get_display_size (
1873                         modest_tny_folder_store_get_local_size (folder_store));
1874                 
1875                 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", 
1876                                                  gray_color_markup, _("mcen_fi_rootfolder_size"),
1877                                                  size);
1878                 g_free (size);
1879                 
1880                 label_w = gtk_label_new (NULL);
1881                 gtk_label_set_markup (GTK_LABEL (label_w), label);
1882                 gtk_label_set_ellipsize (GTK_LABEL (label_w),  PANGO_ELLIPSIZE_END);
1883                 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1884                 g_free (label);
1885         } else if (TNY_IS_ACCOUNT(folder_store)) {
1886                 TnyAccount *account = TNY_ACCOUNT(folder_store);
1887                 
1888                 time_t last_updated;
1889                 const gchar *last_updated_string;
1890                 /* Get last updated from configuration */
1891                 last_updated = modest_account_mgr_get_last_updated (modest_runtime_get_account_mgr (), 
1892                                                                     tny_account_get_id (account));
1893
1894                 if (last_updated > 0) 
1895                         last_updated_string = modest_text_utils_get_display_date(last_updated);
1896                 else
1897                         last_updated_string = g_strdup (_("mcen_va_never"));
1898
1899                 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", 
1900                                                  gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1901                 label_w = gtk_label_new (NULL);
1902                 gtk_label_set_markup (GTK_LABEL (label_w), label);
1903                 gtk_label_set_ellipsize (GTK_LABEL (label_w),  PANGO_ELLIPSIZE_END);
1904                 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1905                 g_free (label);
1906         }
1907
1908         g_free (gray_color_markup);
1909
1910         /* Set alignment */
1911         gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1912
1913         return vbox;
1914 }
1915
1916 gboolean
1917 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1918 {
1919         ModestMainWindowPrivate *priv = NULL;
1920         
1921         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1922
1923         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1924
1925         return priv->send_receive_in_progress;
1926 }
1927
1928 void 
1929 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1930 {
1931         GtkAction *action = NULL;
1932         GtkWidget *widget = NULL;
1933         ModestMainWindowPrivate *priv = NULL;
1934                 
1935         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1936         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1937         
1938         priv->send_receive_in_progress  = TRUE;
1939
1940         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu"); 
1941         gtk_action_set_sensitive (action, FALSE);
1942 /*         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1943 /*      gtk_action_set_sensitive (action, FALSE); */
1944         widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");       
1945         gtk_widget_set_sensitive (widget, FALSE);
1946
1947
1948 void 
1949 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1950 {
1951         GtkAction *action = NULL;
1952         GtkWidget *widget = NULL;
1953         ModestMainWindowPrivate *priv = NULL;
1954                 
1955         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1956         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1957
1958         priv->send_receive_in_progress  = FALSE;
1959
1960         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu"); 
1961         gtk_action_set_sensitive (action, TRUE);
1962 /*         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu");     */
1963 /*      gtk_action_set_sensitive (action, TRUE); */
1964         widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");       
1965         gtk_widget_set_sensitive (widget, TRUE);
1966
1967
1968
1969 static void
1970 on_msg_count_changed (ModestHeaderView *header_view,
1971                       TnyFolder *folder,
1972                       TnyFolderChange *change,
1973                       ModestMainWindow *main_window)
1974 {
1975         gboolean refilter = FALSE;
1976         gboolean folder_empty = FALSE;
1977         gboolean all_marked_as_deleted = FALSE;
1978         ModestMainWindowPrivate *priv;
1979
1980         g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1981         g_return_if_fail (TNY_IS_FOLDER(folder));
1982         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
1983
1984         if (change != NULL) {
1985                 TnyFolderChangeChanged changed;
1986
1987                 changed = tny_folder_change_get_changed (change);
1988                 /* If something changes */
1989                 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1990                         folder_empty = (((guint) tny_folder_change_get_new_all_count (change)) == 0);
1991                 else
1992                         folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
1993
1994                 /* Play a sound (if configured) and make the LED blink  */
1995                 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
1996                         modest_platform_push_email_notification ();
1997                 }
1998
1999                 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS)
2000                         refilter = TRUE;
2001         } else {
2002                 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
2003         }
2004
2005         /* Check if all messages are marked to be deleted */
2006         all_marked_as_deleted = modest_header_view_is_empty (header_view);
2007         folder_empty = folder_empty || all_marked_as_deleted;
2008
2009         /* Set contents style of headers view */
2010         if (folder_empty)  {
2011                 modest_main_window_set_contents_style (main_window,
2012                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2013                 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
2014         } else {
2015                 modest_main_window_set_contents_style (main_window,
2016                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2017         }
2018
2019         if (refilter)
2020                 modest_header_view_refilter (header_view);
2021 }
2022
2023
2024 void 
2025 modest_main_window_set_contents_style (ModestMainWindow *self, 
2026                                        ModestMainWindowContentsStyle style)
2027 {
2028         ModestMainWindowPrivate *priv;
2029
2030         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2031
2032         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2033
2034         /* We allow to set the same content style than the previously
2035            set if there are details, because it could happen when we're
2036            selecting different accounts consecutively */
2037         if ((priv->contents_style == style) &&
2038             (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
2039                 return;
2040
2041         /* Remove previous child. Delete it if it was an account
2042            details widget */
2043         GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
2044         if (content) {
2045                 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2046                         g_object_ref (content);
2047                 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
2048                         g_object_ref (priv->empty_view);
2049                         gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
2050                 }
2051                 
2052                 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
2053         }
2054
2055         priv->contents_style = style;
2056
2057         switch (priv->contents_style) {
2058         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
2059                 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
2060                 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2061                                                       TRUE);
2062                 break;
2063         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
2064         {
2065                 /* if we're started without main win, there may not be a folder
2066                  * view. this fixes a GLib-Critical */
2067                 if (priv->folder_view) {
2068                         TnyFolderStore *selected_folderstore = 
2069                                 modest_folder_view_get_selected (priv->folder_view);
2070                         if (TNY_IS_ACCOUNT (selected_folderstore)) {    
2071                                 priv->details_widget = create_details_widget (GTK_WIDGET (self),
2072                                                                 TNY_ACCOUNT (selected_folderstore));
2073                                 
2074                                 wrap_in_scrolled_window (priv->contents_widget, 
2075                                                          priv->details_widget);
2076                         }
2077                         g_object_unref (selected_folderstore);
2078                         modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2079                                                               FALSE);
2080                 }
2081                 break;
2082         }
2083         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
2084                 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
2085                 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2086                                                       FALSE);
2087                 break;
2088         default:
2089                 g_return_if_reached ();
2090         }
2091
2092         /* Show */
2093         gtk_widget_show_all (priv->contents_widget);
2094 }
2095
2096 ModestMainWindowContentsStyle
2097 modest_main_window_get_contents_style (ModestMainWindow *self)
2098 {
2099         ModestMainWindowPrivate *priv;
2100
2101         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
2102
2103         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2104         return priv->contents_style;
2105 }
2106
2107
2108 static void 
2109 on_configuration_key_changed (ModestConf* conf, 
2110                               const gchar *key, 
2111                               ModestConfEvent event,
2112                               ModestConfNotificationId id, 
2113                               ModestMainWindow *self)
2114 {
2115         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2116         TnyAccount *account = NULL;
2117
2118         if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
2119                 return;
2120
2121         if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
2122                 return;
2123
2124         if (priv->folder_view) 
2125                 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
2126
2127         if (account && TNY_IS_ACCOUNT (account) &&
2128             strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
2129                 GList *children;
2130                 GtkLabel *label;
2131                 const gchar *device_name;
2132                 gchar *new_text, *gray_color_markup;
2133                 
2134                 /* Get label */
2135                 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
2136                 label = GTK_LABEL (children->data);
2137                 
2138                 device_name = modest_conf_get_string (modest_runtime_get_conf(),
2139                                                       MODEST_CONF_DEVICE_NAME, NULL);
2140
2141                 gray_color_markup = get_gray_color_markup (GTK_WIDGET (self));          
2142                 new_text = create_device_name_visual_string (device_name, gray_color_markup);
2143                 
2144                 gtk_label_set_markup (label, new_text);
2145                 gtk_widget_show (GTK_WIDGET (label));
2146                 
2147                 g_free (gray_color_markup);
2148                 g_free (new_text);
2149                 g_list_free (children);
2150         }
2151         g_object_unref (account);
2152 }
2153
2154 static gboolean
2155 set_toolbar_transfer_mode (ModestMainWindow *self)
2156 {
2157         ModestMainWindowPrivate *priv = NULL;
2158         
2159         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2160
2161         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2162
2163         set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
2164         
2165         if (priv->progress_bar_timeout > 0) {
2166                 g_source_remove (priv->progress_bar_timeout);
2167                 priv->progress_bar_timeout = 0;
2168         }
2169
2170         return FALSE;
2171 }
2172
2173 static void 
2174 set_toolbar_mode (ModestMainWindow *self, 
2175                   ModestToolBarModes mode)
2176 {
2177         ModestWindowPrivate *parent_priv = NULL;
2178         ModestMainWindowPrivate *priv = NULL;
2179         GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
2180         
2181         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2182
2183         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2184         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2185
2186         /* In case this was called before the toolbar exists: */
2187         if (!(parent_priv->toolbar))
2188                 return;
2189
2190         g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar)); 
2191         
2192         sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
2193         refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
2194         cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
2195
2196         /* Sets current toolbar mode */
2197         priv->current_toolbar_mode = mode;
2198
2199         /* Checks the dimming rules */
2200         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2201         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2202
2203         /* Show and hide toolbar items */
2204         switch (mode) {
2205         case TOOLBAR_MODE_NORMAL:
2206                 if (sort_action)
2207                         gtk_action_set_visible (sort_action, TRUE);
2208                 if (refresh_action)
2209                         gtk_action_set_visible (refresh_action, TRUE);
2210                 if (priv->progress_toolitem) {
2211                         gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
2212                         gtk_widget_hide (priv->progress_toolitem);
2213                 }
2214                 if (priv->progress_bar)
2215                         gtk_widget_hide (priv->progress_bar);
2216                 
2217                 if (cancel_action)
2218                         gtk_action_set_visible (cancel_action, FALSE);
2219
2220                 /* Hide toolbar if optimized view is enabled */
2221                 if (priv->optimized_view)
2222                         gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
2223                 break;
2224         case TOOLBAR_MODE_TRANSFER:
2225                 if (sort_action)
2226                         gtk_action_set_visible (sort_action, FALSE);
2227                 if (refresh_action)
2228                         gtk_action_set_visible (refresh_action, FALSE);
2229                 if (cancel_action)
2230                         gtk_action_set_visible (cancel_action, TRUE);
2231                 if (priv->progress_bar)
2232                         gtk_widget_show (priv->progress_bar);
2233                 if (priv->progress_toolitem) {
2234                         gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
2235                         gtk_widget_show (priv->progress_toolitem);
2236                 }
2237
2238                 /* Show toolbar if it's hiden (optimized view ) */
2239                 if (priv->optimized_view)
2240                         gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2241                 break;
2242         default:
2243                 g_return_if_reached ();
2244         }
2245 }
2246
2247 gboolean
2248 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
2249 {
2250         ModestMainWindowPrivate *priv;
2251
2252         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2253         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2254
2255         return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
2256 }
2257
2258 static void
2259 cancel_progressbar (GtkToolButton *toolbutton,
2260                     ModestMainWindow *self)
2261 {
2262         GSList *tmp;
2263         ModestMainWindowPrivate *priv;
2264         
2265         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2266
2267         /* Get operation observers and cancel all the operations */
2268         tmp = priv->progress_widgets;
2269         while (tmp) {
2270                 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2271                 tmp=g_slist_next(tmp);
2272         }
2273 }
2274
2275 static gboolean
2276 observers_empty (ModestMainWindow *self)
2277 {
2278         GSList *tmp = NULL;
2279         ModestMainWindowPrivate *priv;
2280         gboolean is_empty = TRUE;
2281         guint pending_ops = 0;
2282  
2283         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2284         tmp = priv->progress_widgets;
2285
2286         /* Check all observers */
2287         while (tmp && is_empty)  {
2288                 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2289                 is_empty = pending_ops == 0;
2290                 
2291                 tmp = g_slist_next(tmp);
2292         }
2293         
2294         return is_empty;
2295 }
2296
2297
2298 /**
2299  * Gets the toolbar mode needed for each mail operation. It stores in
2300  * @mode_changed if the toolbar mode has changed or not
2301  */
2302 static ModestToolBarModes
2303 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
2304                                       ModestMailOperation *mail_op,
2305                                       gboolean *mode_changed)
2306 {
2307         ModestToolBarModes mode;
2308         ModestMainWindowPrivate *priv;
2309
2310         *mode_changed = FALSE;
2311         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2312
2313         /* Get toolbar mode from operation id*/
2314         switch (modest_mail_operation_get_type_operation (mail_op)) {
2315         case MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE:
2316         case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2317         case MODEST_MAIL_OPERATION_TYPE_OPEN:
2318                 mode = TOOLBAR_MODE_TRANSFER;
2319                 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2320                         *mode_changed = TRUE;
2321                 break;
2322         default:
2323                 mode = TOOLBAR_MODE_NORMAL;             
2324         }
2325         return mode;
2326 }
2327
2328 static void 
2329 on_mail_operation_started (ModestMailOperation *mail_op,
2330                            gpointer user_data)
2331 {
2332         ModestMainWindow *self;
2333         ModestMailOperationTypeOperation op_type;
2334         ModestMainWindowPrivate *priv;
2335         ModestToolBarModes mode;
2336         GSList *tmp;
2337         gboolean mode_changed = FALSE;
2338         TnyAccount *account = NULL;
2339
2340         self = MODEST_MAIN_WINDOW (user_data);
2341         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2342
2343         /* Do not show progress for receiving operations if the
2344            account is the local account or the MMC one */
2345         op_type = modest_mail_operation_get_type_operation (mail_op);
2346         account = modest_mail_operation_get_account (mail_op);
2347         if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2348                 gboolean is_remote;
2349
2350                 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2351                               modest_tny_account_is_memory_card_account (account));
2352                 if (!is_remote) {
2353                         g_object_unref (account);
2354                         return;
2355                 }
2356
2357                 /* Show information banner. Remove old timeout */
2358                 if (priv->retrieving_banner_timeout > 0) {
2359                         g_source_remove (priv->retrieving_banner_timeout);
2360                         priv->retrieving_banner_timeout = 0;
2361                 }
2362                 /* Create a new timeout */
2363                 priv->retrieving_banner_timeout = 
2364                         g_timeout_add (2000, show_retrieving_banner, self);
2365         }
2366
2367         /* Not every mail operation has account, noop does not */
2368         if (account)
2369                 g_object_unref (account);
2370                
2371         /* Get toolbar mode from operation id*/
2372         mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2373
2374         /* Add operation observers and change toolbar if neccessary*/
2375         tmp = priv->progress_widgets;
2376         if (mode == TOOLBAR_MODE_TRANSFER) {
2377                 if (mode_changed) {
2378                         GObject *source = modest_mail_operation_get_source(mail_op);
2379                         if (G_OBJECT (self) == source) {
2380                                 set_toolbar_transfer_mode(self);
2381                         }
2382                         g_object_unref (source);
2383                 }
2384
2385                 while (tmp) {
2386                         modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2387                                                               mail_op);
2388                         tmp = g_slist_next (tmp);
2389                 }
2390         }
2391
2392         /* Update the main menu as well, we need to explicitely do
2393            this in order to enable/disable accelerators */
2394         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2395 }
2396
2397 static void 
2398 on_mail_operation_finished (ModestMailOperation *mail_op,
2399                             gpointer user_data)
2400 {
2401         ModestToolBarModes mode;
2402         ModestMailOperationTypeOperation op_type;
2403         GSList *tmp = NULL;
2404         ModestMainWindow *self;
2405         gboolean mode_changed;
2406         TnyAccount *account = NULL;
2407         ModestMainWindowPrivate *priv;
2408
2409         self = MODEST_MAIN_WINDOW (user_data);
2410         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2411
2412         /* The mail operation was not added to the progress objects if
2413            the account was the local account or the MMC one */
2414         op_type = modest_mail_operation_get_type_operation (mail_op);
2415         account = modest_mail_operation_get_account (mail_op);
2416         if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2417                 gboolean is_remote;
2418
2419                 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2420                               modest_tny_account_is_memory_card_account (account));
2421                 if (!is_remote) {
2422                         g_object_unref (account);
2423                         return;
2424                 }
2425
2426                 /* Remove old timeout */
2427                 if (priv->retrieving_banner_timeout > 0) {
2428                         g_source_remove (priv->retrieving_banner_timeout);
2429                         priv->retrieving_banner_timeout = 0;
2430                 }
2431
2432                 /* Remove the banner if exists */
2433                 if (priv->retrieving_banner) {
2434                         gtk_widget_destroy (priv->retrieving_banner);
2435                         priv->retrieving_banner = NULL;
2436                 }
2437         }
2438
2439         /* Not every mail operation has account, noop does not */
2440         if (account)
2441                 g_object_unref (account);
2442
2443         /* Get toolbar mode from operation id*/
2444         mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2445
2446         /* Change toolbar mode */
2447         tmp = priv->progress_widgets;
2448         if (mode == TOOLBAR_MODE_TRANSFER) {                    
2449                 while (tmp) {
2450                         modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2451                                                                  mail_op);
2452                         tmp = g_slist_next (tmp);
2453                 }
2454                 
2455                 /* If no more operations are being observed, NORMAL mode is enabled again */
2456                 if (observers_empty (self)) {
2457                         set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);                           
2458                 }
2459         }
2460 }
2461
2462 static void
2463 on_queue_changed (ModestMailOperationQueue *queue,
2464                   ModestMailOperation *mail_op,
2465                   ModestMailOperationQueueNotification type,
2466                   ModestMainWindow *self)
2467 {
2468         ModestMainWindowPrivate *priv;
2469
2470         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2471
2472         if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2473                 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2474                                                                G_OBJECT (mail_op),
2475                                                                "operation-started",
2476                                                                G_CALLBACK (on_mail_operation_started),
2477                                                                self);
2478                 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2479                                                                G_OBJECT (mail_op),
2480                                                                "operation-finished",
2481                                                                G_CALLBACK (on_mail_operation_finished),
2482                                                                self);
2483         } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2484                 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2485                                                                   G_OBJECT (mail_op),
2486                                                                   "operation-started");
2487                 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2488                                                                   G_OBJECT (mail_op),
2489                                                                   "operation-finished");
2490         }
2491 }
2492
2493 static void
2494 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2495 {
2496         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2497         GtkAction *action;
2498         ModestAccountMgr *mgr;
2499         ModestAccountSettings *settings;
2500         ModestServerAccountSettings *store_settings = NULL;
2501
2502         /* Get account data */
2503         mgr = modest_runtime_get_account_mgr ();
2504         settings = modest_account_mgr_load_account_settings (mgr, acc_name);
2505         if (settings)
2506                 store_settings = modest_account_settings_get_store_settings (settings);
2507
2508         /* Set the new visible & active account */
2509         if (settings && (modest_server_account_settings_get_account_name (store_settings)!= NULL)) { 
2510                 const gchar *account_name;
2511
2512                 account_name = modest_account_settings_get_account_name (settings);
2513
2514                 modest_folder_view_set_account_id_of_visible_server_account 
2515                         (priv->folder_view,
2516                          modest_server_account_settings_get_account_name (store_settings));
2517                 modest_window_set_active_account (MODEST_WINDOW (self), account_name);
2518                 action = gtk_action_group_get_action (priv->view_additions_group, account_name);
2519                 if (action != NULL) {
2520                         if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2521                                 modest_utils_toggle_action_set_active_block_notify (
2522                                         GTK_TOGGLE_ACTION (action),
2523                                         TRUE);
2524                         }
2525                 }
2526         }
2527         
2528         /* Free */
2529         if (settings) {
2530                 g_object_unref (store_settings);
2531                 g_object_unref (settings);
2532         }
2533 }
2534
2535 /* Make sure that at least one account is "viewed": */
2536 static void
2537 set_at_least_one_account_visible(ModestMainWindow *self)
2538 {
2539         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2540         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2541
2542         if (!(priv->folder_view)) {
2543                 /* It is too early to do this. */
2544                 return; 
2545         }
2546         
2547         const gchar *active_server_account_name = 
2548                 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2549         
2550         if (!active_server_account_name ||
2551                 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2552         {
2553                 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2554                 gchar* default_modest_name = modest_account_mgr_get_default_account (account_mgr);
2555                 if (default_modest_name) {
2556                         set_account_visible (self, default_modest_name);
2557                 } else if (first_modest_name) {
2558                         set_account_visible (self, first_modest_name);
2559                 }
2560                 g_free (first_modest_name);
2561                 g_free (default_modest_name);
2562         }
2563 }
2564
2565 static void 
2566 on_show_account_action_toggled  (GtkToggleAction *action,
2567                                    gpointer user_data)
2568 {
2569         ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2570
2571         const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2572         if (gtk_toggle_action_get_active (action))
2573                 set_account_visible (self, acc_name);
2574 }
2575
2576 static void
2577 refresh_account (const gchar *account_name)
2578 {
2579         ModestWindow *win;
2580         
2581         /* win must already exists here, obviously */ 
2582         win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
2583                                                  FALSE);
2584         if (!win) {
2585                 g_warning ("%s: BUG: no main window!", __FUNCTION__);
2586                 return;
2587         }
2588         
2589         /* If account_name == NULL, we must update all (option All) */
2590         if (!account_name)
2591                 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2592         else
2593                 modest_ui_actions_do_send_receive (account_name, TRUE, TRUE, TRUE, win);
2594         
2595 }
2596
2597 static void 
2598 on_refresh_account_action_activated  (GtkAction *action,
2599                                       gpointer user_data)
2600 {
2601         refresh_account ((const gchar*) user_data);
2602 }
2603
2604 static void
2605 on_send_receive_csm_activated (GtkMenuItem *item,
2606                                gpointer user_data)
2607 {
2608         refresh_account ((const gchar*) user_data);
2609 }
2610
2611 static gboolean
2612 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2613 {
2614         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2615
2616         hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2617         return FALSE;
2618
2619 }
2620
2621 static gboolean
2622 on_folder_view_focus_in (GtkWidget *widget, GdkEventFocus *event, gpointer userdata)
2623 {
2624         ModestMainWindow *main_window = NULL;
2625         
2626         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2627         main_window = MODEST_MAIN_WINDOW (userdata);
2628         
2629         /* Update toolbar dimming state */
2630         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2631         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2632
2633         return FALSE;
2634 }
2635
2636 static gboolean
2637 on_header_view_focus_in (GtkWidget *widget,
2638                          GdkEventFocus *event,
2639                          gpointer userdata)
2640 {
2641         ModestMainWindow *main_window = NULL;
2642
2643         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2644
2645         main_window = MODEST_MAIN_WINDOW (userdata);
2646
2647         /* Update toolbar dimming state */
2648         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2649         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2650
2651         return FALSE;
2652 }
2653
2654 static void 
2655 on_folder_selection_changed (ModestFolderView *folder_view,
2656                              TnyFolderStore *folder_store, 
2657                              gboolean selected,
2658                              ModestMainWindow *main_window)
2659 {
2660         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2661         GtkAction *action = NULL;
2662         gboolean show_reply = TRUE;
2663         gboolean show_forward = TRUE;
2664         gboolean show_cancel_send = FALSE;
2665         gboolean show_clipboard = TRUE;
2666         gboolean show_delete = TRUE;
2667
2668         if (selected) {
2669                 if (TNY_IS_ACCOUNT (folder_store)) {
2670                         show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2671                 } else if (TNY_IS_FOLDER (folder_store)) {
2672                         if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2673                                 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2674                                         TNY_FOLDER (folder_store));
2675                                 switch (folder_type) {
2676                                 case TNY_FOLDER_TYPE_DRAFTS:
2677                                         show_clipboard = show_delete = TRUE;
2678                                         show_reply = show_forward = show_cancel_send = FALSE;
2679                                         break;
2680                                 case TNY_FOLDER_TYPE_SENT:
2681                                         show_forward = show_clipboard = show_delete = TRUE;
2682                                         show_reply = show_cancel_send = FALSE;
2683                                         break;
2684                                 case TNY_FOLDER_TYPE_OUTBOX:
2685                                         show_clipboard = show_delete = show_cancel_send = TRUE;
2686                                         show_reply = show_forward = FALSE;
2687                                         break;
2688                                 case TNY_FOLDER_TYPE_INVALID:
2689                                         g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
2690                                         break;
2691                                 default:
2692                                         show_reply = show_forward = show_clipboard = show_delete = TRUE;
2693                                         show_cancel_send = FALSE;
2694                                 }
2695                         } else {
2696                                 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2697                                 show_cancel_send = FALSE;
2698                         }
2699                 }
2700         }
2701
2702         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2703         gtk_action_set_visible (action, show_reply);
2704         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2705         gtk_action_set_visible (action, show_reply);
2706         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2707         gtk_action_set_visible (action, show_forward);
2708         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2709         gtk_action_set_visible (action, show_cancel_send);
2710         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2711         gtk_action_set_visible (action, show_delete);
2712
2713         /* We finally call to the ui actions handler, after updating properly
2714          * the header view CSM */
2715         modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2716 }
2717
2718 gboolean 
2719 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2720                                                    GtkTreeModel *model,
2721                                                    GtkTreeRowReference *row_reference,
2722                                                    ModestMainWindow *self)
2723 {
2724         ModestMainWindowPrivate *priv = NULL;
2725         GtkTreeModel *header_model = NULL;
2726         GtkTreePath *path = NULL;
2727
2728         g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2729         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2730         g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2731
2732         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2733         header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2734
2735         /* Do nothing if we changed the folder in the main view */
2736         if (header_model != model)
2737                 return FALSE;
2738
2739         /* Select the message in the header view */
2740         path = gtk_tree_row_reference_get_path (row_reference);
2741         gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2742                                   path, NULL, FALSE);
2743         gtk_tree_path_free (path);
2744
2745         return TRUE;
2746 }
2747
2748 static gboolean
2749 show_updating_banner (gpointer user_data)
2750 {
2751         ModestMainWindowPrivate *priv = NULL;
2752
2753         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2754
2755         if (priv->updating_banner == NULL) {
2756
2757                 /* We're outside the main lock */
2758                 gdk_threads_enter ();
2759                 priv->updating_banner = 
2760                         modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2761                                                           _CS ("ckdg_pb_updating"));
2762                 gdk_threads_leave ();
2763         }
2764
2765         /* Remove timeout */
2766         priv->updating_banner_timeout = 0;
2767         return FALSE;
2768 }
2769
2770 /**
2771  * We use this function to show/hide a progress banner showing
2772  * "Updating" while the header view is being filled. We're not showing
2773  * it unless the update takes more than 2 seconds
2774  *
2775  * If starting = TRUE then the refresh is starting, otherwise it means
2776  * that is has just finished
2777  */
2778 static void 
2779 on_updating_msg_list (ModestHeaderView *header_view,
2780                       gboolean starting,
2781                       gpointer user_data)
2782 {
2783         ModestMainWindowPrivate *priv = NULL;
2784
2785         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2786         
2787         /* Remove old timeout */
2788         if (priv->updating_banner_timeout > 0) {
2789                 g_source_remove (priv->updating_banner_timeout);
2790                 priv->updating_banner_timeout = 0;
2791         }
2792
2793         /* Create a new timeout */
2794         if (starting) {
2795                 priv->updating_banner_timeout = 
2796                         g_timeout_add (2000, show_updating_banner, user_data);
2797         } else {
2798                 /* Remove the banner if exists */
2799                 if (priv->updating_banner) {
2800                         gtk_widget_destroy (priv->updating_banner);
2801                         priv->updating_banner = NULL;
2802                 }
2803         }
2804 }
2805
2806 gboolean
2807 modest_main_window_screen_is_on (ModestMainWindow *self)
2808 {
2809         ModestMainWindowPrivate *priv = NULL;
2810
2811         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(self), FALSE);
2812
2813         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2814         
2815         return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE;
2816 }
2817
2818 static void
2819 remove_banners (ModestMainWindow *window)
2820 {
2821         ModestMainWindowPrivate *priv;
2822
2823         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (window);
2824
2825         if (priv->retrieving_banner_timeout > 0) {
2826                 g_source_remove (priv->retrieving_banner_timeout);
2827                 priv->retrieving_banner_timeout = 0;
2828         }
2829
2830         if (priv->retrieving_banner != NULL) {
2831                 gtk_widget_destroy (priv->retrieving_banner);
2832                 priv->retrieving_banner = NULL;
2833         }
2834         
2835         if (priv->updating_banner_timeout > 0) {
2836                 g_source_remove (priv->updating_banner_timeout);
2837                 priv->updating_banner_timeout = 0;
2838         }
2839
2840         if (priv->updating_banner != NULL) {
2841                 gtk_widget_destroy (priv->updating_banner);
2842                 priv->updating_banner = NULL;
2843         }       
2844 }
2845
2846
2847 static void
2848 on_window_hide (GObject    *gobject,
2849                 GParamSpec *arg1,
2850                 gpointer    user_data)
2851 {
2852         g_return_if_fail (MODEST_IS_MAIN_WINDOW (gobject));
2853
2854         if (!GTK_WIDGET_VISIBLE (gobject)) {
2855                 TnyFolderStore *folder_store;
2856                 ModestMainWindowPrivate *priv;
2857                 
2858                 /* Remove the currently shown banners */
2859                 remove_banners (MODEST_MAIN_WINDOW (gobject));
2860
2861                 /* Force the folder view to sync the currently selected folder
2862                    to save the read/unread status and to expunge messages */
2863                 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (gobject);
2864                 folder_store = modest_folder_view_get_selected (priv->folder_view);
2865                 if (TNY_IS_FOLDER (folder_store)) {
2866                         ModestMailOperation *mail_op;
2867                         
2868                         mail_op = modest_mail_operation_new (NULL);
2869                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2870                                                          mail_op);
2871                         modest_mail_operation_sync_folder (mail_op, TNY_FOLDER (folder_store), FALSE);
2872                         g_object_unref (mail_op);
2873                 }
2874         }
2875 }
2876
2877 static void
2878 on_window_destroy (GtkObject *widget, 
2879                    gpointer user_data)
2880 {
2881         g_return_if_fail (MODEST_IS_MAIN_WINDOW (widget));
2882
2883         remove_banners (MODEST_MAIN_WINDOW (widget));
2884 }
2885
2886 static gboolean
2887 show_retrieving_banner (gpointer user_data)
2888 {
2889         ModestMainWindowPrivate *priv = NULL;
2890
2891         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2892
2893         if (priv->retrieving_banner == NULL) {
2894
2895                 /* We're outside the main lock */
2896                 gdk_threads_enter ();
2897                 priv->retrieving_banner = 
2898                         modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2899                                                           _("mcen_ib_getting_items"));
2900                 gdk_threads_leave ();
2901         }
2902
2903         /* Remove timeout */
2904         priv->retrieving_banner_timeout = 0;
2905         return FALSE;
2906 }