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