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