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