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