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