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