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