* Fixes NB#84117, fixes "hangs" when reopening Modest while there are ongoing operations
[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                         }
1682                 }
1683         } else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1684                 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1685
1686         return FALSE;
1687 }
1688
1689 static void
1690 set_alignment (GtkWidget *widget,
1691                gpointer data)
1692 {
1693         gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1694         gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1695 }
1696
1697 static GtkWidget *
1698 create_empty_view (void)
1699 {
1700         GtkLabel *label = NULL;
1701         GtkWidget *align = NULL;
1702
1703         align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1704         label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1705         gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);      
1706         gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1707
1708         return GTK_WIDGET(align);
1709 }
1710
1711 /*
1712  * Free the returned string
1713  */
1714 static gchar *
1715 get_gray_color_markup (GtkWidget *styled_widget)
1716 {
1717         gchar *gray_color_markup = NULL;
1718 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1719         /* Obtain the secondary text color. We need a realized widget, that's why 
1720            we get styled_widget from outside */
1721         GdkColor color;
1722         if (gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color)) 
1723                 gray_color_markup = modest_text_utils_get_color_string (&color);
1724 #endif /*MODEST_HAVE_HILDON0_WIDGETS*/
1725         
1726         if (!gray_color_markup) 
1727                 gray_color_markup = g_strdup ("#BBBBBB");
1728
1729         return gray_color_markup;
1730 }
1731
1732 /*
1733  * Free the returned string
1734  */
1735 static gchar*
1736 create_device_name_visual_string (const gchar *device_name,
1737                                   const gchar *gray_color_markup)
1738 {
1739         gchar *tmp, *label;
1740
1741         /* We have to use "" to fill the %s of the translation. We can
1742            not just use the device name because the device name is
1743            shown in a different color, so it could not be included
1744            into the <span> tag */
1745         tmp = g_strdup_printf (_("mcen_fi_localroot_description"), "");
1746         label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s", 
1747                                          gray_color_markup, 
1748                                          tmp, 
1749                                          device_name);
1750         g_free (tmp);
1751
1752         return label;
1753 }
1754
1755 static GtkWidget *
1756 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1757 {
1758         /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1759         
1760         GtkWidget *vbox;
1761         GtkWidget *label_w;
1762         gchar *label;
1763         gchar *gray_color_markup;
1764
1765         vbox = gtk_vbox_new (FALSE, 0);
1766
1767         gray_color_markup = get_gray_color_markup (styled_widget);
1768
1769         /* Account description: */
1770         if (modest_tny_account_is_virtual_local_folders (account)
1771                 || (modest_tny_account_is_memory_card_account (account))) {
1772         
1773                 /* Get device name */
1774                 gchar *device_name = NULL;
1775                 if (modest_tny_account_is_virtual_local_folders (account))
1776                         device_name = modest_conf_get_string (modest_runtime_get_conf(),
1777                                                       MODEST_CONF_DEVICE_NAME, NULL);
1778                 else
1779                         device_name = g_strdup (tny_account_get_name (account));
1780
1781                 label = create_device_name_visual_string ((const gchar *) device_name, 
1782                                                           (const gchar *) gray_color_markup);
1783                 label_w = gtk_label_new (NULL);
1784                 gtk_label_set_markup (GTK_LABEL (label_w), label);
1785                 gtk_label_set_ellipsize (GTK_LABEL (label_w),  PANGO_ELLIPSIZE_END);
1786                 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1787                 g_free (device_name);
1788                 g_free (label);
1789         } else {
1790                 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1791                         gtk_box_pack_start (GTK_BOX (vbox), 
1792                                 gtk_label_new (tny_account_get_name (account)), 
1793                                 FALSE, FALSE, 0);
1794                 } else {
1795                         /* Other accounts, such as IMAP and POP: */
1796                         
1797                         GString *proto;
1798                         gchar *tmp;
1799         
1800                         /* Put proto in uppercase */
1801                         proto = g_string_new (tny_account_get_proto (account));
1802                         proto = g_string_ascii_up (proto);
1803                         
1804                         /* note: mcen_fi_localroot_description is something like "%s account"
1805                          * however, we should display "%s account: %s"... therefore, ugly tmp */
1806                         tmp   = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1807                         label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", 
1808                                                          gray_color_markup, tmp, tny_account_get_name (account));
1809                         g_free (tmp);
1810
1811                         label_w = gtk_label_new (NULL);
1812                         gtk_label_set_markup (GTK_LABEL (label_w), label);
1813                         gtk_label_set_ellipsize (GTK_LABEL (label_w),  PANGO_ELLIPSIZE_END);
1814                         gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1815                         g_string_free (proto, TRUE);
1816                         g_free (label);
1817                 }
1818         }
1819
1820         /* Message count */
1821         TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1822         label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d", 
1823                                          gray_color_markup, _("mcen_fi_rootfolder_messages"), 
1824                                          modest_tny_folder_store_get_message_count (folder_store));
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_free (label);
1830
1831         /* Folder count */
1832         label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d", 
1833                                          gray_color_markup, 
1834                                          _("mcen_fi_rootfolder_folders"), 
1835                                          modest_tny_folder_store_get_folder_count (folder_store));
1836         label_w = gtk_label_new (NULL);
1837         gtk_label_set_markup (GTK_LABEL (label_w), label);
1838         gtk_label_set_ellipsize (GTK_LABEL (label_w),  PANGO_ELLIPSIZE_END);
1839         gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1840         g_free (label);
1841
1842         /* Size / Date */
1843         if (modest_tny_account_is_virtual_local_folders (account)
1844                 || modest_tny_account_is_memory_card_account (account)) {
1845
1846                 gchar *size = modest_text_utils_get_display_size (
1847                         modest_tny_folder_store_get_local_size (folder_store));
1848                 
1849                 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", 
1850                                                  gray_color_markup, _("mcen_fi_rootfolder_size"),
1851                                                  size);
1852                 g_free (size);
1853                 
1854                 label_w = gtk_label_new (NULL);
1855                 gtk_label_set_markup (GTK_LABEL (label_w), label);
1856                 gtk_label_set_ellipsize (GTK_LABEL (label_w),  PANGO_ELLIPSIZE_END);
1857                 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1858                 g_free (label);
1859         } else if (TNY_IS_ACCOUNT(folder_store)) {
1860                 TnyAccount *account = TNY_ACCOUNT(folder_store);
1861                 
1862                 time_t last_updated;
1863                 const gchar *last_updated_string;
1864                 /* Get last updated from configuration */
1865                 last_updated = modest_account_mgr_get_last_updated (modest_runtime_get_account_mgr (), 
1866                                                                     tny_account_get_id (account));
1867
1868                 if (last_updated > 0) 
1869                         last_updated_string = modest_text_utils_get_display_date(last_updated);
1870                 else
1871                         last_updated_string = g_strdup (_("mcen_va_never"));
1872
1873                 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", 
1874                                                  gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1875                 label_w = gtk_label_new (NULL);
1876                 gtk_label_set_markup (GTK_LABEL (label_w), label);
1877                 gtk_label_set_ellipsize (GTK_LABEL (label_w),  PANGO_ELLIPSIZE_END);
1878                 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1879                 g_free (label);
1880         }
1881
1882         g_free (gray_color_markup);
1883
1884         /* Set alignment */
1885         gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1886
1887         return vbox;
1888 }
1889
1890 gboolean
1891 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1892 {
1893         ModestMainWindowPrivate *priv = NULL;
1894         
1895         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1896
1897         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1898
1899         return priv->send_receive_in_progress;
1900 }
1901
1902 void 
1903 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1904 {
1905         GtkAction *action = NULL;
1906         GtkWidget *widget = NULL;
1907         ModestMainWindowPrivate *priv = NULL;
1908                 
1909         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1910         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1911         
1912         priv->send_receive_in_progress  = TRUE;
1913
1914         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu"); 
1915         gtk_action_set_sensitive (action, FALSE);
1916 /*         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1917 /*      gtk_action_set_sensitive (action, FALSE); */
1918         widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");       
1919         gtk_widget_set_sensitive (widget, FALSE);
1920
1921
1922 void 
1923 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1924 {
1925         GtkAction *action = NULL;
1926         GtkWidget *widget = NULL;
1927         ModestMainWindowPrivate *priv = NULL;
1928                 
1929         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1930         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1931
1932         priv->send_receive_in_progress  = FALSE;
1933
1934         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu"); 
1935         gtk_action_set_sensitive (action, TRUE);
1936 /*         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu");     */
1937 /*      gtk_action_set_sensitive (action, TRUE); */
1938         widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");       
1939         gtk_widget_set_sensitive (widget, TRUE);
1940
1941
1942
1943 static void
1944 on_msg_count_changed (ModestHeaderView *header_view,
1945                       TnyFolder *folder,
1946                       TnyFolderChange *change,
1947                       ModestMainWindow *main_window)
1948 {
1949         gboolean refilter = FALSE;
1950         gboolean folder_empty = FALSE;
1951         gboolean all_marked_as_deleted = FALSE;
1952         ModestMainWindowPrivate *priv;
1953
1954         g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1955         g_return_if_fail (TNY_IS_FOLDER(folder));
1956         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
1957
1958         if (change != NULL) {
1959                 TnyFolderChangeChanged changed;
1960
1961                 changed = tny_folder_change_get_changed (change);
1962                 /* If something changes */
1963                 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1964                         folder_empty = (((guint) tny_folder_change_get_new_all_count (change)) == 0);
1965                 else
1966                         folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
1967
1968                 /* Play a sound (if configured) and make the LED blink  */
1969                 if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
1970                         modest_platform_push_email_notification ();
1971                 }
1972
1973                 if ((changed) & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS)
1974                         refilter = TRUE;
1975         } else {
1976                 folder_empty = (((guint) tny_folder_get_all_count (TNY_FOLDER (folder))) == 0);
1977         }
1978
1979         /* Check if all messages are marked to be deleted */
1980         all_marked_as_deleted = modest_header_view_is_empty (header_view);
1981         folder_empty = folder_empty || all_marked_as_deleted;
1982
1983         /* Set contents style of headers view */
1984         if (folder_empty)  {
1985                 modest_main_window_set_contents_style (main_window,
1986                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1987                 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1988         } else {
1989                 modest_main_window_set_contents_style (main_window,
1990                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1991         }
1992
1993         if (refilter)
1994                 modest_header_view_refilter (header_view);
1995 }
1996
1997
1998 void 
1999 modest_main_window_set_contents_style (ModestMainWindow *self, 
2000                                        ModestMainWindowContentsStyle style)
2001 {
2002         ModestMainWindowPrivate *priv;
2003
2004         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2005
2006         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2007
2008         /* We allow to set the same content style than the previously
2009            set if there are details, because it could happen when we're
2010            selecting different accounts consecutively */
2011         if ((priv->contents_style == style) &&
2012             (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
2013                 return;
2014
2015         /* Remove previous child. Delete it if it was an account
2016            details widget */
2017         GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
2018         if (content) {
2019                 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2020                         g_object_ref (content);
2021                 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
2022                         g_object_ref (priv->empty_view);
2023                         gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
2024                 }
2025                 
2026                 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
2027         }
2028
2029         priv->contents_style = style;
2030
2031         switch (priv->contents_style) {
2032         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
2033                 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
2034                 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2035                                                       TRUE);
2036                 break;
2037         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
2038         {
2039                 /* if we're started without main win, there may not be a folder
2040                  * view. this fixes a GLib-Critical */
2041                 if (priv->folder_view) {
2042                         TnyFolderStore *selected_folderstore = 
2043                                 modest_folder_view_get_selected (priv->folder_view);
2044                         if (TNY_IS_ACCOUNT (selected_folderstore)) {    
2045                                 priv->details_widget = create_details_widget (GTK_WIDGET (self),
2046                                                                 TNY_ACCOUNT (selected_folderstore));
2047                                 
2048                                 wrap_in_scrolled_window (priv->contents_widget, 
2049                                                          priv->details_widget);
2050                         }
2051                         g_object_unref (selected_folderstore);
2052                         modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2053                                                               FALSE);
2054                 }
2055                 break;
2056         }
2057         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
2058                 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
2059                 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
2060                                                       FALSE);
2061                 break;
2062         default:
2063                 g_return_if_reached ();
2064         }
2065
2066         /* Show */
2067         gtk_widget_show_all (priv->contents_widget);
2068 }
2069
2070 ModestMainWindowContentsStyle
2071 modest_main_window_get_contents_style (ModestMainWindow *self)
2072 {
2073         ModestMainWindowPrivate *priv;
2074
2075         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
2076
2077         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2078         return priv->contents_style;
2079 }
2080
2081
2082 static void 
2083 on_configuration_key_changed (ModestConf* conf, 
2084                               const gchar *key, 
2085                               ModestConfEvent event,
2086                               ModestConfNotificationId id, 
2087                               ModestMainWindow *self)
2088 {
2089         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2090         TnyAccount *account = NULL;
2091
2092         if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
2093                 return;
2094
2095         if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
2096                 return;
2097
2098         if (priv->folder_view) 
2099                 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
2100
2101         if (account && TNY_IS_ACCOUNT (account) &&
2102             strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
2103                 GList *children;
2104                 GtkLabel *label;
2105                 const gchar *device_name;
2106                 gchar *new_text, *gray_color_markup;
2107                 
2108                 /* Get label */
2109                 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
2110                 label = GTK_LABEL (children->data);
2111                 
2112                 device_name = modest_conf_get_string (modest_runtime_get_conf(),
2113                                                       MODEST_CONF_DEVICE_NAME, NULL);
2114
2115                 gray_color_markup = get_gray_color_markup (GTK_WIDGET (self));          
2116                 new_text = create_device_name_visual_string (device_name, gray_color_markup);
2117                 
2118                 gtk_label_set_markup (label, new_text);
2119                 gtk_widget_show (GTK_WIDGET (label));
2120                 
2121                 g_free (gray_color_markup);
2122                 g_free (new_text);
2123                 g_list_free (children);
2124         }
2125         g_object_unref (account);
2126 }
2127
2128 static gboolean
2129 set_toolbar_transfer_mode (ModestMainWindow *self)
2130 {
2131         ModestMainWindowPrivate *priv = NULL;
2132         
2133         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2134
2135         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2136
2137         set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
2138         
2139         if (priv->progress_bar_timeout > 0) {
2140                 g_source_remove (priv->progress_bar_timeout);
2141                 priv->progress_bar_timeout = 0;
2142         }
2143
2144         return FALSE;
2145 }
2146
2147 static void 
2148 set_toolbar_mode (ModestMainWindow *self, 
2149                   ModestToolBarModes mode)
2150 {
2151         ModestWindowPrivate *parent_priv = NULL;
2152         ModestMainWindowPrivate *priv = NULL;
2153         GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
2154         
2155         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2156
2157         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2158         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2159
2160         /* In case this was called before the toolbar exists: */
2161         if (!(parent_priv->toolbar))
2162                 return;
2163
2164         g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar)); 
2165         
2166         sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
2167         refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
2168         cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
2169
2170         /* Sets current toolbar mode */
2171         priv->current_toolbar_mode = mode;
2172
2173         /* Checks the dimming rules */
2174         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2175         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2176
2177         /* Show and hide toolbar items */
2178         switch (mode) {
2179         case TOOLBAR_MODE_NORMAL:
2180                 if (sort_action)
2181                         gtk_action_set_visible (sort_action, TRUE);
2182                 if (refresh_action)
2183                         gtk_action_set_visible (refresh_action, TRUE);
2184                 if (priv->progress_toolitem) {
2185                         gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
2186                         gtk_widget_hide (priv->progress_toolitem);
2187                 }
2188                 if (priv->progress_bar)
2189                         gtk_widget_hide (priv->progress_bar);
2190                 
2191                 if (cancel_action)
2192                         gtk_action_set_visible (cancel_action, FALSE);
2193
2194                 /* Hide toolbar if optimized view is enabled */
2195                 if (priv->optimized_view)
2196                         gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
2197                 break;
2198         case TOOLBAR_MODE_TRANSFER:
2199                 if (sort_action)
2200                         gtk_action_set_visible (sort_action, FALSE);
2201                 if (refresh_action)
2202                         gtk_action_set_visible (refresh_action, FALSE);
2203                 if (cancel_action)
2204                         gtk_action_set_visible (cancel_action, TRUE);
2205                 if (priv->progress_bar)
2206                         gtk_widget_show (priv->progress_bar);
2207                 if (priv->progress_toolitem) {
2208                         gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
2209                         gtk_widget_show (priv->progress_toolitem);
2210                 }
2211
2212                 /* Show toolbar if it's hiden (optimized view ) */
2213                 if (priv->optimized_view)
2214                         gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2215                 break;
2216         default:
2217                 g_return_if_reached ();
2218         }
2219 }
2220
2221 gboolean
2222 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
2223 {
2224         ModestMainWindowPrivate *priv;
2225
2226         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2227         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2228
2229         return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
2230 }
2231
2232 static void
2233 cancel_progressbar (GtkToolButton *toolbutton,
2234                     ModestMainWindow *self)
2235 {
2236         GSList *tmp;
2237         ModestMainWindowPrivate *priv;
2238         
2239         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2240
2241         /* Get operation observers and cancel all the operations */
2242         tmp = priv->progress_widgets;
2243         while (tmp) {
2244                 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2245                 tmp=g_slist_next(tmp);
2246         }
2247 }
2248
2249 static gboolean
2250 observers_empty (ModestMainWindow *self)
2251 {
2252         GSList *tmp = NULL;
2253         ModestMainWindowPrivate *priv;
2254         gboolean is_empty = TRUE;
2255         guint pending_ops = 0;
2256  
2257         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2258         tmp = priv->progress_widgets;
2259
2260         /* Check all observers */
2261         while (tmp && is_empty)  {
2262                 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2263                 is_empty = pending_ops == 0;
2264                 
2265                 tmp = g_slist_next(tmp);
2266         }
2267         
2268         return is_empty;
2269 }
2270
2271
2272 /**
2273  * Gets the toolbar mode needed for each mail operation. It stores in
2274  * @mode_changed if the toolbar mode has changed or not
2275  */
2276 static ModestToolBarModes
2277 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
2278                                       ModestMailOperation *mail_op,
2279                                       gboolean *mode_changed)
2280 {
2281         ModestToolBarModes mode;
2282         ModestMainWindowPrivate *priv;
2283
2284         *mode_changed = FALSE;
2285         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2286
2287         /* Get toolbar mode from operation id*/
2288         switch (modest_mail_operation_get_type_operation (mail_op)) {
2289         case MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE:
2290         case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2291         case MODEST_MAIL_OPERATION_TYPE_OPEN:
2292                 mode = TOOLBAR_MODE_TRANSFER;
2293                 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2294                         *mode_changed = TRUE;
2295                 break;
2296         default:
2297                 mode = TOOLBAR_MODE_NORMAL;             
2298         }
2299         return mode;
2300 }
2301
2302 static void 
2303 on_mail_operation_started (ModestMailOperation *mail_op,
2304                            gpointer user_data)
2305 {
2306         ModestMainWindow *self;
2307         ModestMailOperationTypeOperation op_type;
2308         ModestMainWindowPrivate *priv;
2309         ModestToolBarModes mode;
2310         GSList *tmp;
2311         gboolean mode_changed = FALSE;
2312         TnyAccount *account = NULL;
2313
2314         self = MODEST_MAIN_WINDOW (user_data);
2315         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2316
2317         /* Do not show progress for receiving operations if the
2318            account is the local account or the MMC one */
2319         op_type = modest_mail_operation_get_type_operation (mail_op);
2320         account = modest_mail_operation_get_account (mail_op);
2321         if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2322                 gboolean is_remote;
2323
2324                 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2325                               modest_tny_account_is_memory_card_account (account));
2326                 if (!is_remote) {
2327                         g_object_unref (account);
2328                         return;
2329                 }
2330
2331                 /* Show information banner. Remove old timeout */
2332                 if (priv->retrieving_banner_timeout > 0) {
2333                         g_source_remove (priv->retrieving_banner_timeout);
2334                         priv->retrieving_banner_timeout = 0;
2335                 }
2336                 /* Create a new timeout */
2337                 priv->retrieving_banner_timeout = 
2338                         g_timeout_add (2000, show_retrieving_banner, self);
2339         }
2340
2341         /* Not every mail operation has account, noop does not */
2342         if (account)
2343                 g_object_unref (account);
2344                
2345         /* Get toolbar mode from operation id*/
2346         mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2347
2348         /* Add operation observers and change toolbar if neccessary*/
2349         tmp = priv->progress_widgets;
2350         if (mode == TOOLBAR_MODE_TRANSFER) {
2351                 if (mode_changed) {
2352                         GObject *source = modest_mail_operation_get_source(mail_op);
2353                         if (G_OBJECT (self) == source) {
2354                                 set_toolbar_transfer_mode(self);
2355                         }
2356                         g_object_unref (source);
2357                 }
2358
2359                 while (tmp) {
2360                         modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2361                                                               mail_op);
2362                         tmp = g_slist_next (tmp);
2363                 }
2364         }
2365
2366         /* Update the main menu as well, we need to explicitely do
2367            this in order to enable/disable accelerators */
2368         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2369 }
2370
2371 static void 
2372 on_mail_operation_finished (ModestMailOperation *mail_op,
2373                             gpointer user_data)
2374 {
2375         ModestToolBarModes mode;
2376         ModestMailOperationTypeOperation op_type;
2377         GSList *tmp = NULL;
2378         ModestMainWindow *self;
2379         gboolean mode_changed;
2380         TnyAccount *account = NULL;
2381         ModestMainWindowPrivate *priv;
2382
2383         self = MODEST_MAIN_WINDOW (user_data);
2384         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2385
2386         /* The mail operation was not added to the progress objects if
2387            the account was the local account or the MMC one */
2388         op_type = modest_mail_operation_get_type_operation (mail_op);
2389         account = modest_mail_operation_get_account (mail_op);
2390         if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2391                 gboolean is_remote;
2392
2393                 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2394                               modest_tny_account_is_memory_card_account (account));
2395                 if (!is_remote) {
2396                         g_object_unref (account);
2397                         return;
2398                 }
2399
2400                 /* Remove old timeout */
2401                 if (priv->retrieving_banner_timeout > 0) {
2402                         g_source_remove (priv->retrieving_banner_timeout);
2403                         priv->retrieving_banner_timeout = 0;
2404                 }
2405
2406                 /* Remove the banner if exists */
2407                 if (priv->retrieving_banner) {
2408                         gtk_widget_destroy (priv->retrieving_banner);
2409                         priv->retrieving_banner = NULL;
2410                 }
2411         }
2412
2413         /* Not every mail operation has account, noop does not */
2414         if (account)
2415                 g_object_unref (account);
2416
2417         /* Get toolbar mode from operation id*/
2418         mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2419
2420         /* Change toolbar mode */
2421         tmp = priv->progress_widgets;
2422         if (mode == TOOLBAR_MODE_TRANSFER) {                    
2423                 while (tmp) {
2424                         modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2425                                                                  mail_op);
2426                         tmp = g_slist_next (tmp);
2427                 }
2428                 
2429                 /* If no more operations are being observed, NORMAL mode is enabled again */
2430                 if (observers_empty (self)) {
2431                         set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);                           
2432                 }
2433         }
2434 }
2435
2436 static void
2437 on_queue_changed (ModestMailOperationQueue *queue,
2438                   ModestMailOperation *mail_op,
2439                   ModestMailOperationQueueNotification type,
2440                   ModestMainWindow *self)
2441 {
2442         ModestMainWindowPrivate *priv;
2443
2444         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2445
2446         if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2447                 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2448                                                                G_OBJECT (mail_op),
2449                                                                "operation-started",
2450                                                                G_CALLBACK (on_mail_operation_started),
2451                                                                self);
2452                 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2453                                                                G_OBJECT (mail_op),
2454                                                                "operation-finished",
2455                                                                G_CALLBACK (on_mail_operation_finished),
2456                                                                self);
2457         } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2458                 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2459                                                                   G_OBJECT (mail_op),
2460                                                                   "operation-started");
2461                 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2462                                                                   G_OBJECT (mail_op),
2463                                                                   "operation-finished");
2464         }
2465 }
2466
2467 static void
2468 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2469 {
2470         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2471         GtkAction *action;
2472         ModestAccountMgr *mgr;
2473         ModestAccountSettings *settings;
2474         ModestServerAccountSettings *store_settings = NULL;
2475
2476         /* Get account data */
2477         mgr = modest_runtime_get_account_mgr ();
2478         settings = modest_account_mgr_load_account_settings (mgr, acc_name);
2479         if (settings)
2480                 store_settings = modest_account_settings_get_store_settings (settings);
2481
2482         /* Set the new visible & active account */
2483         if (settings && (modest_server_account_settings_get_account_name (store_settings)!= NULL)) { 
2484                 const gchar *account_name;
2485
2486                 account_name = modest_account_settings_get_account_name (settings);
2487
2488                 modest_folder_view_set_account_id_of_visible_server_account 
2489                         (priv->folder_view,
2490                          modest_server_account_settings_get_account_name (store_settings));
2491                 modest_window_set_active_account (MODEST_WINDOW (self), account_name);
2492                 action = gtk_action_group_get_action (priv->view_additions_group, account_name);
2493                 if (action != NULL) {
2494                         if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2495                                 modest_utils_toggle_action_set_active_block_notify (
2496                                         GTK_TOGGLE_ACTION (action),
2497                                         TRUE);
2498                         }
2499                 }
2500         }
2501         
2502         modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2503
2504
2505         /* Free */
2506         if (settings) {
2507                 g_object_unref (store_settings);
2508                 g_object_unref (settings);
2509         }
2510 }
2511
2512 /* Make sure that at least one account is "viewed": */
2513 static void
2514 set_at_least_one_account_visible(ModestMainWindow *self)
2515 {
2516         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2517         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2518
2519         if (!(priv->folder_view)) {
2520                 /* It is too early to do this. */
2521                 return; 
2522         }
2523         
2524         const gchar *active_server_account_name = 
2525                 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);
2526         
2527         if (!active_server_account_name ||
2528                 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2529         {
2530                 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2531                 gchar* default_modest_name = modest_account_mgr_get_default_account (account_mgr);
2532                 if (default_modest_name) {
2533                         set_account_visible (self, default_modest_name);
2534                 } else if (first_modest_name) {
2535                         set_account_visible (self, first_modest_name);
2536                 }
2537                 g_free (first_modest_name);
2538                 g_free (default_modest_name);
2539         }
2540 }
2541
2542 static void 
2543 on_show_account_action_toggled  (GtkToggleAction *action,
2544                                    gpointer user_data)
2545 {
2546         ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2547
2548         const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2549         if (gtk_toggle_action_get_active (action))
2550                 set_account_visible (self, acc_name);
2551 }
2552
2553 static void
2554 refresh_account (const gchar *account_name)
2555 {
2556         ModestWindow *win;
2557         
2558         /* win must already exists here, obviously */ 
2559         win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
2560                                                  FALSE);
2561         if (!win) {
2562                 g_warning ("%s: BUG: no main window!", __FUNCTION__);
2563                 return;
2564         }
2565         
2566         /* If account_name == NULL, we must update all (option All) */
2567         if (!account_name)
2568                 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2569         else
2570                 modest_ui_actions_do_send_receive (account_name, TRUE, TRUE, TRUE, win);
2571         
2572 }
2573
2574 static void 
2575 on_refresh_account_action_activated  (GtkAction *action,
2576                                       gpointer user_data)
2577 {
2578         refresh_account ((const gchar*) user_data);
2579 }
2580
2581 static void
2582 on_send_receive_csm_activated (GtkMenuItem *item,
2583                                gpointer user_data)
2584 {
2585         refresh_account ((const gchar*) user_data);
2586 }
2587
2588 static gboolean
2589 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2590 {
2591         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2592
2593         hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2594         return FALSE;
2595
2596 }
2597
2598 static gboolean
2599 on_folder_view_focus_in (GtkWidget *widget, GdkEventFocus *event, gpointer userdata)
2600 {
2601         ModestMainWindow *main_window = NULL;
2602         
2603         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2604         main_window = MODEST_MAIN_WINDOW (userdata);
2605         
2606         /* Update toolbar dimming state */
2607         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2608         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2609
2610         return FALSE;
2611 }
2612
2613 static gboolean
2614 on_header_view_focus_in (GtkWidget *widget,
2615                          GdkEventFocus *event,
2616                          gpointer userdata)
2617 {
2618         ModestMainWindow *main_window = NULL;
2619
2620         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2621
2622         main_window = MODEST_MAIN_WINDOW (userdata);
2623
2624         /* Update toolbar dimming state */
2625         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2626         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2627
2628         return FALSE;
2629 }
2630
2631 static void 
2632 on_folder_selection_changed (ModestFolderView *folder_view,
2633                              TnyFolderStore *folder_store, 
2634                              gboolean selected,
2635                              ModestMainWindow *main_window)
2636 {
2637         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2638         GtkAction *action = NULL;
2639         gboolean show_reply = TRUE;
2640         gboolean show_forward = TRUE;
2641         gboolean show_cancel_send = FALSE;
2642         gboolean show_clipboard = TRUE;
2643         gboolean show_delete = TRUE;
2644
2645         if (selected) {
2646                 if (TNY_IS_ACCOUNT (folder_store)) {
2647                         show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2648                 } else if (TNY_IS_FOLDER (folder_store)) {
2649                         if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2650                                 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2651                                         TNY_FOLDER (folder_store));
2652                                 switch (folder_type) {
2653                                 case TNY_FOLDER_TYPE_DRAFTS:
2654                                         show_clipboard = show_delete = TRUE;
2655                                         show_reply = show_forward = show_cancel_send = FALSE;
2656                                         break;
2657                                 case TNY_FOLDER_TYPE_SENT:
2658                                         show_forward = show_clipboard = show_delete = TRUE;
2659                                         show_reply = show_cancel_send = FALSE;
2660                                         break;
2661                                 case TNY_FOLDER_TYPE_OUTBOX:
2662                                         show_clipboard = show_delete = show_cancel_send = TRUE;
2663                                         show_reply = show_forward = FALSE;
2664                                         break;
2665                                 case TNY_FOLDER_TYPE_INVALID:
2666                                         g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
2667                                         break;
2668                                 default:
2669                                         show_reply = show_forward = show_clipboard = show_delete = TRUE;
2670                                         show_cancel_send = FALSE;
2671                                 }
2672                         } else {
2673                                 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2674                                 show_cancel_send = FALSE;
2675                         }
2676                 }
2677         }
2678
2679         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2680         gtk_action_set_visible (action, show_reply);
2681         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2682         gtk_action_set_visible (action, show_reply);
2683         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2684         gtk_action_set_visible (action, show_forward);
2685         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2686         gtk_action_set_visible (action, show_cancel_send);
2687         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2688         gtk_action_set_visible (action, show_delete);
2689
2690         /* We finally call to the ui actions handler, after updating properly
2691          * the header view CSM */
2692         modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2693 }
2694
2695 gboolean 
2696 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2697                                                    GtkTreeModel *model,
2698                                                    GtkTreeRowReference *row_reference,
2699                                                    ModestMainWindow *self)
2700 {
2701         ModestMainWindowPrivate *priv = NULL;
2702         GtkTreeModel *header_model = NULL;
2703         GtkTreePath *path = NULL;
2704
2705         g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2706         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2707         g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2708
2709         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2710         header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2711
2712         /* Do nothing if we changed the folder in the main view */
2713         if (header_model != model)
2714                 return FALSE;
2715
2716         /* Select the message in the header view */
2717         path = gtk_tree_row_reference_get_path (row_reference);
2718         gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2719                                   path, NULL, FALSE);
2720         gtk_tree_path_free (path);
2721
2722         return TRUE;
2723 }
2724
2725 static gboolean
2726 show_updating_banner (gpointer user_data)
2727 {
2728         ModestMainWindowPrivate *priv = NULL;
2729
2730         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2731
2732         if (priv->updating_banner == NULL) {
2733
2734                 /* We're outside the main lock */
2735                 gdk_threads_enter ();
2736                 priv->updating_banner = 
2737                         modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2738                                                           _CS ("ckdg_pb_updating"));
2739                 gdk_threads_leave ();
2740         }
2741
2742         /* Remove timeout */
2743         priv->updating_banner_timeout = 0;
2744         return FALSE;
2745 }
2746
2747 /**
2748  * We use this function to show/hide a progress banner showing
2749  * "Updating" while the header view is being filled. We're not showing
2750  * it unless the update takes more than 2 seconds
2751  *
2752  * If starting = TRUE then the refresh is starting, otherwise it means
2753  * that is has just finished
2754  */
2755 static void 
2756 on_updating_msg_list (ModestHeaderView *header_view,
2757                       gboolean starting,
2758                       gpointer user_data)
2759 {
2760         ModestMainWindowPrivate *priv = NULL;
2761
2762         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2763         
2764         /* Remove old timeout */
2765         if (priv->updating_banner_timeout > 0) {
2766                 g_source_remove (priv->updating_banner_timeout);
2767                 priv->updating_banner_timeout = 0;
2768         }
2769
2770         /* Create a new timeout */
2771         if (starting) {
2772                 priv->updating_banner_timeout = 
2773                         g_timeout_add (2000, show_updating_banner, user_data);
2774         } else {
2775                 /* Remove the banner if exists */
2776                 if (priv->updating_banner) {
2777                         gtk_widget_destroy (priv->updating_banner);
2778                         priv->updating_banner = NULL;
2779                 }
2780         }
2781 }
2782
2783 gboolean
2784 modest_main_window_screen_is_on (ModestMainWindow *self)
2785 {
2786         ModestMainWindowPrivate *priv = NULL;
2787
2788         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW(self), FALSE);
2789
2790         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2791         
2792         return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE;
2793 }
2794
2795 static void
2796 remove_banners (ModestMainWindow *window)
2797 {
2798         ModestMainWindowPrivate *priv;
2799
2800         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (window);
2801
2802         if (priv->retrieving_banner_timeout > 0) {
2803                 g_source_remove (priv->retrieving_banner_timeout);
2804                 priv->retrieving_banner_timeout = 0;
2805         }
2806
2807         if (priv->retrieving_banner != NULL) {
2808                 gtk_widget_destroy (priv->retrieving_banner);
2809                 priv->retrieving_banner = NULL;
2810         }
2811         
2812         if (priv->updating_banner_timeout > 0) {
2813                 g_source_remove (priv->updating_banner_timeout);
2814                 priv->updating_banner_timeout = 0;
2815         }
2816
2817         if (priv->updating_banner != NULL) {
2818                 gtk_widget_destroy (priv->updating_banner);
2819                 priv->updating_banner = NULL;
2820         }       
2821 }
2822
2823
2824 static void
2825 on_window_hide (GObject    *gobject,
2826                 GParamSpec *arg1,
2827                 gpointer    user_data)
2828 {
2829         g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
2830
2831         if (!GTK_WIDGET_VISIBLE (user_data))
2832                 remove_banners (MODEST_MAIN_WINDOW (user_data));
2833 }
2834
2835 static void
2836 on_window_destroy (GtkObject *widget, 
2837                    gpointer user_data)
2838 {
2839         g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
2840
2841         remove_banners (MODEST_MAIN_WINDOW (user_data));
2842 }
2843
2844 static gboolean
2845 show_retrieving_banner (gpointer user_data)
2846 {
2847         ModestMainWindowPrivate *priv = NULL;
2848
2849         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2850
2851         if (priv->retrieving_banner == NULL) {
2852
2853                 /* We're outside the main lock */
2854                 gdk_threads_enter ();
2855                 priv->retrieving_banner = 
2856                         modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2857                                                           _("mcen_ib_getting_items"));
2858                 gdk_threads_leave ();
2859         }
2860
2861         /* Remove timeout */
2862         priv->retrieving_banner_timeout = 0;
2863         return FALSE;
2864 }