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