* src/modest-marshal.list:
[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 = 
865                 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "tap-and-hold",
866                                            G_CALLBACK(_header_view_csm_menu_activated),
867                                            self);
868         
869         /* window */
870         priv->sighandlers = 
871                 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (self), "window-state-event",
872                                            G_CALLBACK (modest_main_window_window_state_event),
873                                            NULL);
874         
875         /* Mail Operation Queue */
876         priv->sighandlers = 
877                 modest_signal_mgr_connect (priv->sighandlers,
878                                            G_OBJECT (modest_runtime_get_mail_operation_queue ()),
879                                            "queue-changed", 
880                                            G_CALLBACK (on_queue_changed), self);
881         
882         /* Track changes in the device name */
883         priv->sighandlers = 
884                 modest_signal_mgr_connect (priv->sighandlers,
885                                            G_OBJECT(modest_runtime_get_conf ()),
886                                            "key_changed", 
887                                            G_CALLBACK (on_configuration_key_changed), 
888                                            self);
889         
890         /* Track account changes. We need to refresh the toolbar */
891         priv->sighandlers = 
892                 modest_signal_mgr_connect (priv->sighandlers,
893                                            G_OBJECT (modest_runtime_get_account_store ()),
894                                            "account_inserted", 
895                                            G_CALLBACK (on_account_inserted),
896                                            self);
897         priv->sighandlers = 
898                 modest_signal_mgr_connect (priv->sighandlers,
899                                            G_OBJECT (modest_runtime_get_account_store ()),
900                                            "account_removed", 
901                                            G_CALLBACK (on_account_removed),
902                                            self);
903
904         /* We need to refresh the send & receive menu to change the bold
905          * account when the default account changes. */
906         priv->sighandlers = 
907                 modest_signal_mgr_connect (priv->sighandlers,
908                                            G_OBJECT (modest_runtime_get_account_mgr ()),
909                                            "default_account_changed", 
910                                            G_CALLBACK (on_default_account_changed),
911                                            self);
912
913         /* Account store */
914         priv->sighandlers = 
915                 modest_signal_mgr_connect (priv->sighandlers,
916                                            G_OBJECT (modest_runtime_get_account_store()), 
917                                            "password_requested",
918                                            G_CALLBACK (modest_ui_actions_on_password_requested), 
919                                            self);
920 }
921
922 #if 0
923 /** Idle handler, to send/receive at startup .*/
924 gboolean
925 sync_accounts_cb (ModestMainWindow *win)
926 {
927         modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (win));
928         return FALSE; /* Do not call this idle handler again. */
929 }
930 #endif
931
932 static void 
933 on_hildon_program_is_topmost_notify(GObject *self,
934                                     GParamSpec *propert_param, gpointer user_data)
935 {
936         HildonProgram *app = HILDON_PROGRAM (self);
937         
938         /*
939         ModestWindow* self = MODEST_WINDOW(user_data);
940         */
941         
942         /* Note that use of hildon_program_set_can_hibernate() 
943          * is generally referred to as "setting the killable flag", 
944          * though hibernation does not seem equal to death.
945          * murrayc */
946                  
947         if (hildon_program_get_is_topmost (app)) {
948                 /* Prevent hibernation when the progam comes to the foreground,
949                  * because hibernation should only happen when the application 
950                  * is in the background: */
951                 hildon_program_set_can_hibernate (app, FALSE);
952         } else {
953                 /* Allow hibernation if the program has gone to the background: */
954                 
955                 /* However, prevent hibernation while the settings are being changed: */
956                 const gboolean hibernation_prevented = 
957                         modest_window_mgr_get_hibernation_is_prevented (
958         modest_runtime_get_window_mgr ()); 
959         
960                 if (hibernation_prevented)
961                         hildon_program_set_can_hibernate (app, FALSE);
962                 else {
963                         /* Allow hibernation, after saving the state: */
964                         modest_osso_save_state();
965                         hildon_program_set_can_hibernate (app, TRUE);
966                 }
967         }
968         
969 }
970
971 static void
972 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
973 {
974         GtkWidget *folder_win = (GtkWidget *) user_data;
975         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
976         
977         priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL));
978         wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
979 /*      wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET(priv->header_view)); */
980
981         gtk_widget_show (GTK_WIDGET (priv->folder_view));
982
983         /* Connect signals */
984         connect_signals (MODEST_MAIN_WINDOW (self));
985
986         /* Set account store */
987         tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
988                                                   TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
989
990         /* Load previous osso state, for instance if we are being restored from 
991          * hibernation:  */
992         modest_osso_load_state ();
993
994         /* Restore window & widget settings */  
995         restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
996
997 /*      /\* The UI spec wants us to show a connection dialog when the application is  */
998 /*       * started by the user, if there is no connection. */
999 /*       * Do this before showing the account wizard,  */
1000 /*       * because wizard needs a connection to discover capabilities. *\/ */
1001 /*       modest_platform_connect_and_wait (GTK_WINDOW (self), NULL); */
1002          
1003         /* Check if accounts exist and show the account wizard if not */
1004         gboolean accounts_exist = 
1005                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1006
1007         if (!accounts_exist) {
1008                 /* This is necessary to have the main window shown behind the dialog 
1009                 It's an ugly hack... jschmid */
1010                 gtk_widget_show_all(GTK_WIDGET(self));
1011                 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
1012         } else {
1013                 GSList *accounts;
1014                 GtkAction *send_receive_all;
1015                 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1016                 accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE);
1017                 send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager, 
1018                                                               "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1019                 gtk_action_set_visible (send_receive_all, g_slist_length (accounts) > 1);
1020                 modest_account_mgr_free_account_names (accounts);
1021         }
1022 }
1023
1024 ModestWindow *
1025 modest_main_window_new (void)
1026 {
1027         ModestMainWindow *self = NULL;  
1028         ModestMainWindowPrivate *priv = NULL;
1029         ModestWindowPrivate *parent_priv = NULL;
1030         GtkWidget *folder_win = NULL;
1031         ModestDimmingRulesGroup *menu_rules_group = NULL;
1032         ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1033         GtkActionGroup *action_group = NULL;
1034         GError *error = NULL;
1035         ModestConf *conf = NULL;
1036         GtkAction *action = NULL;
1037         GdkPixbuf *window_icon;
1038         
1039         self  = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
1040         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1041         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1042
1043         parent_priv->ui_manager = gtk_ui_manager_new();
1044         parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
1045
1046         action_group = gtk_action_group_new ("ModestMainWindowActions");
1047         gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1048
1049         menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules", FALSE);
1050         toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules", TRUE);
1051
1052         /* Add common actions */
1053         gtk_action_group_add_actions (action_group,
1054                                       modest_action_entries,
1055                                       G_N_ELEMENTS (modest_action_entries),
1056                                       self);
1057
1058         gtk_action_group_add_actions (action_group,
1059                                       modest_folder_view_action_entries,
1060                                       G_N_ELEMENTS (modest_folder_view_action_entries),
1061                                       self);
1062
1063         gtk_action_group_add_actions (action_group,
1064                                       modest_header_view_action_entries,
1065                                       G_N_ELEMENTS (modest_header_view_action_entries),
1066                                       self);
1067
1068         gtk_action_group_add_toggle_actions (action_group,
1069                                              modest_toggle_action_entries,
1070                                              G_N_ELEMENTS (modest_toggle_action_entries),
1071                                              self);
1072
1073         gtk_action_group_add_toggle_actions (action_group,
1074                                              modest_main_window_toggle_action_entries,
1075                                              G_N_ELEMENTS (modest_main_window_toggle_action_entries),
1076                                              self);
1077
1078         gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1079         g_object_unref (action_group);
1080
1081         /* Load the UI definition */
1082         gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
1083                                          MODEST_UIDIR "modest-main-window-ui.xml", &error);
1084         if (error != NULL) {
1085                 g_warning ("Could not merge modest-ui.xml: %s", error->message);
1086                 g_error_free (error);
1087                 error = NULL;
1088         }
1089
1090         /* Add common dimming rules */
1091         modest_dimming_rules_group_add_rules (menu_rules_group, 
1092                                               modest_main_window_menu_dimming_entries,
1093                                               G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
1094                                               MODEST_WINDOW (self));
1095         modest_dimming_rules_group_add_rules (toolbar_rules_group, 
1096                                               modest_main_window_toolbar_dimming_entries,
1097                                               G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
1098                                               MODEST_WINDOW (self));
1099
1100         /* Insert dimming rules group for this window */
1101         modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1102         modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1103         g_object_unref (menu_rules_group);
1104         g_object_unref (toolbar_rules_group);
1105         
1106         /* Add accelerators */
1107         gtk_window_add_accel_group (GTK_WINDOW (self), 
1108                                     gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1109
1110         /* Menubar. Update the state of some toggles */
1111         parent_priv->menubar = modest_maemo_utils_menubar_to_menu (parent_priv->ui_manager);
1112         conf = modest_runtime_get_conf ();
1113         action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
1114                                             "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
1115         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1116                                       modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR, NULL));
1117         action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
1118                                             "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
1119         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1120                                       modest_conf_get_bool (conf, MODEST_CONF_MAIN_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
1121         hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
1122         gtk_widget_show (parent_priv->menubar);
1123
1124         /* Get device name */
1125         modest_maemo_utils_get_device_name ();
1126
1127         /* header view */
1128         priv->header_view =
1129                 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
1130         if (!priv->header_view)
1131                 g_printerr ("modest: cannot instantiate header view\n");
1132         modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
1133         modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
1134                                       MODEST_CONF_HEADER_VIEW_KEY);
1135
1136         /* Other style properties of header view */
1137         g_object_set (G_OBJECT (priv->header_view), 
1138                       "rules-hint", FALSE,
1139                       NULL);
1140         /* gtk_widget_show (priv->header_view); */
1141
1142         /* Empty view */ 
1143         priv->empty_view = create_empty_view ();
1144         gtk_widget_show (priv->empty_view);
1145                  
1146         /* Create scrolled windows */
1147         folder_win = gtk_scrolled_window_new (NULL, NULL);
1148         priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
1149         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
1150                                         GTK_POLICY_NEVER,
1151                                         GTK_POLICY_AUTOMATIC);
1152         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
1153                                         GTK_POLICY_NEVER,
1154                                         GTK_POLICY_AUTOMATIC);
1155         /* gtk_widget_show (priv->contents_widget); */
1156
1157         /* paned */
1158         priv->main_paned = gtk_hpaned_new ();
1159         gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
1160         gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
1161         gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
1162
1163         /* putting it all together... */
1164         priv->main_vbox = gtk_vbox_new (FALSE, 6);
1165         gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
1166         gtk_widget_show (priv->main_vbox);
1167         
1168         gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
1169         
1170         HildonProgram *app = hildon_program_get_instance ();
1171         hildon_program_add_window (app, HILDON_WINDOW (self));
1172         
1173         g_signal_connect (G_OBJECT(app), "notify::is-topmost",
1174                 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
1175
1176         g_signal_connect (G_OBJECT(self), "show",
1177                           G_CALLBACK (modest_main_window_on_show), folder_win);
1178                 
1179         /* Set window icon */
1180         window_icon = modest_platform_get_icon (MODEST_APP_ICON);
1181         if (window_icon) {
1182                 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
1183                 g_object_unref (window_icon);
1184         }
1185
1186         /* Dont't restore settings here, 
1187          * because it requires a gtk_widget_show(), 
1188          * and we don't want to do that until later,
1189          * so that the UI is not visible for non-menu D-Bus activation.
1190          */
1191         /* restore_settings (MODEST_MAIN_WINDOW(self), FALSE); */
1192
1193         return MODEST_WINDOW(self);
1194 }
1195
1196 gboolean 
1197 modest_main_window_close_all (ModestMainWindow *self)
1198 {
1199         GtkWidget *note;
1200         GtkResponseType response;
1201
1202         /* Create the confirmation dialog MSG-NOT308 */
1203         note = hildon_note_new_confirmation_add_buttons (GTK_WINDOW (self),
1204                                                          _("emev_nc_close_windows"),
1205                                                          _("mcen_bd_yes"), GTK_RESPONSE_YES,
1206                                                          _("mcen_bd_no"), GTK_RESPONSE_NO,
1207                                                          NULL);
1208
1209         response = gtk_dialog_run (GTK_DIALOG (note));
1210         gtk_widget_destroy (GTK_WIDGET (note));
1211
1212         if (response == GTK_RESPONSE_YES)
1213                 return TRUE;
1214         else
1215                 return FALSE;
1216 }
1217
1218
1219 void 
1220 modest_main_window_set_style (ModestMainWindow *self, 
1221                               ModestMainWindowStyle style)
1222 {
1223         ModestMainWindowPrivate *priv;
1224         ModestWindowPrivate *parent_priv;
1225         GtkAction *action;
1226         gboolean active;
1227
1228         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1229
1230         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1231         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1232
1233         /* no change -> nothing to do */
1234         if (priv->style == style)
1235                 return;
1236
1237        /* Get toggle button and update the state if needed. This will
1238           happen only when the set_style is not invoked from the UI,
1239           for example when it's called from widget memory */
1240        action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToggleFolders");
1241        active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1242        if ((active && style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) ||
1243            (!active && style == MODEST_MAIN_WINDOW_STYLE_SPLIT)) {
1244                g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
1245                gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !active);
1246                g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
1247        }
1248
1249         priv->style = style;
1250         switch (style) {
1251         case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
1252                 /* Remove main paned */
1253                 g_object_ref (priv->main_paned);
1254                 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1255
1256                 /* Reparent the contents widget to the main vbox */
1257                 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
1258
1259                 break;
1260         case MODEST_MAIN_WINDOW_STYLE_SPLIT:
1261                 /* Remove header view */
1262                 g_object_ref (priv->contents_widget);
1263                 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
1264
1265                 /* Reparent the main paned */
1266                 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
1267                 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
1268
1269                 break;
1270         default:
1271                 g_return_if_reached ();
1272         }
1273
1274         /* Let header view grab the focus if it's being shown */
1275         if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1276                 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1277         else 
1278                 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
1279
1280         /* Show changes */
1281         gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
1282 }
1283
1284 ModestMainWindowStyle
1285 modest_main_window_get_style (ModestMainWindow *self)
1286 {
1287         ModestMainWindowPrivate *priv;
1288
1289         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1290
1291         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1292         return priv->style;
1293 }
1294
1295
1296
1297 static gboolean
1298 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1299 {
1300         if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1301                 ModestWindowPrivate *parent_priv;
1302                 ModestWindowMgr *mgr;
1303                 gboolean is_fullscreen;
1304                 GtkAction *fs_toggle_action;
1305                 gboolean active;
1306                 
1307                 mgr = modest_runtime_get_window_mgr ();
1308                 
1309                 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1310
1311                 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1312                 
1313                 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1314                 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1315                 if (is_fullscreen != active) {
1316                         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1317                 }
1318         }
1319
1320         return FALSE;
1321
1322 }
1323
1324 static void
1325 set_homogeneous (GtkWidget *widget,
1326                  gpointer data)
1327 {
1328         gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
1329         gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
1330 }
1331
1332 static void 
1333 modest_main_window_show_toolbar (ModestWindow *self,
1334                                  gboolean show_toolbar)
1335 {
1336         ModestMainWindowPrivate *priv = NULL;
1337         ModestWindowPrivate *parent_priv = NULL;        
1338         GtkWidget *reply_button = NULL, *menu = NULL;
1339         GtkWidget *placeholder = NULL;
1340         gint insert_index;
1341         const gchar *action_name;
1342         GtkAction *action;
1343
1344         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1345         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1346         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1347
1348         /* Set optimized view status */
1349         priv->optimized_view = !show_toolbar;
1350
1351         if (!parent_priv->toolbar) {
1352                 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, 
1353                                                                   "/ToolBar");
1354                 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1355
1356                 /* Set homogeneous toolbar */
1357                 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar), 
1358                                        set_homogeneous, NULL);
1359         
1360                 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1361                 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1362                 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1363                 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1364                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1365                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1366                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1367                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1368
1369                 /* Add ProgressBar (Transfer toolbar) */ 
1370                 priv->progress_bar = modest_progress_bar_widget_new ();
1371                 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1372                 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1373                 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1374                 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1375                 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1376                 
1377                 /* Connect cancel 'clicked' signal to abort progress mode */
1378                 g_signal_connect(priv->cancel_toolitem, "clicked",
1379                                  G_CALLBACK(cancel_progressbar),
1380                                  self);
1381                 
1382                 /* Add it to the observers list */
1383                 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1384
1385                 /* Add to window */
1386                 hildon_window_add_toolbar (HILDON_WINDOW (self), 
1387                                            GTK_TOOLBAR (parent_priv->toolbar));
1388
1389                 /* Set reply button tap and hold menu */
1390                 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager, 
1391                                                           "/ToolBar/ToolbarMessageReply");
1392                 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1393                                                   "/ToolbarReplyCSM");
1394                 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1395
1396                 /* Set send & receive button tap and hold menu */
1397                 update_menus (MODEST_MAIN_WINDOW (self));
1398         }
1399         
1400         if (show_toolbar) {
1401                 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */ 
1402                 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1403                 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1404
1405                 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1406                 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1407         } else {
1408                 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1409
1410         }
1411
1412         /* Update also the actions (to update the toggles in the
1413            menus), we have to do it manually because some other window
1414            of the same time could have changed it (remember that the
1415            toolbar fullscreen mode is shared by all the windows of the
1416            same type */
1417         if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
1418                 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu";
1419         else
1420                 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu";
1421
1422         action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
1423         modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1424                                                             show_toolbar);
1425 }
1426
1427 static void
1428 on_account_inserted (TnyAccountStore *accoust_store,
1429                      TnyAccount *account,
1430                      gpointer user_data)
1431 {
1432         update_menus (MODEST_MAIN_WINDOW (user_data));
1433 }
1434
1435 static void
1436 on_default_account_changed (ModestAccountMgr* mgr,
1437                             gpointer user_data)
1438 {
1439         update_menus (MODEST_MAIN_WINDOW (user_data));
1440 }
1441
1442 static void
1443 on_account_removed (TnyAccountStore *accoust_store,
1444                      TnyAccount *account,
1445                      gpointer user_data)
1446 {
1447         update_menus (MODEST_MAIN_WINDOW (user_data));
1448 }
1449
1450 /* 
1451  * This function manages the key events used to navigate between
1452  * header and folder views (when the window is in split view)
1453  *
1454  * FROM         KEY        ACTION
1455  * -------------------------------------------------
1456  * HeaderView   GDK_Left   Move focus to folder view
1457  * FolderView   GDK_Right  Move focus to header view
1458  *
1459  * There is no need to scroll to selected row, the widgets will be the
1460  * responsibles of doing that (probably managing the focus-in event
1461  */
1462 static gboolean 
1463 on_inner_widgets_key_pressed (GtkWidget *widget,
1464                               GdkEventKey *event,
1465                               gpointer user_data)
1466 {
1467         ModestMainWindowPrivate *priv;
1468
1469         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1470
1471         /* Do nothing if we're in SIMPLE style */
1472         if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1473                 return FALSE;
1474
1475         if (MODEST_IS_HEADER_VIEW (widget)) {
1476                 if (event->keyval == GDK_Left)
1477                         gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1478                 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1479                         hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1480                         return TRUE;
1481                 }
1482         } else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1483                 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1484
1485         return FALSE;
1486 }
1487
1488 static void
1489 set_alignment (GtkWidget *widget,
1490                gpointer data)
1491 {
1492         gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1493         gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1494 }
1495
1496 static GtkWidget *
1497 create_empty_view (void)
1498 {
1499         GtkLabel *label = NULL;
1500         GtkWidget *align = NULL;
1501
1502         align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1503         label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1504         gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);      
1505         gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1506
1507         return GTK_WIDGET(align);
1508 }
1509
1510 /*
1511  * Free the returned string
1512  */
1513 static gchar *
1514 get_gray_color_markup (GtkWidget *styled_widget)
1515 {
1516         gchar *gray_color_markup;
1517
1518         /* Obtain the secondary text color. We need a realized widget, that's why 
1519            we get styled_widget from outside */
1520 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1521         GdkColor color;
1522         gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color);
1523         gray_color_markup = modest_text_utils_get_color_string (&color);
1524 #else
1525         gray_color_markup = g_strdup ("#BBBBBB");
1526 #endif  
1527         return gray_color_markup;
1528 }
1529
1530 /*
1531  * Free the returned string
1532  */
1533 static gchar*
1534 create_device_name_visual_string (const gchar *device_name,
1535                                   const gchar *gray_color_markup)
1536 {
1537         gchar *tmp, *label;
1538
1539         /* We have to use "" to fill the %s of the translation. We can
1540            not just use the device name because the device name is
1541            shown in a different color, so it could not be included
1542            into the <span> tag */
1543         tmp = g_strdup_printf (_("mcen_fi_localroot_description"), "");
1544         label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s", 
1545                                          gray_color_markup, 
1546                                          tmp, 
1547                                          device_name);
1548         g_free (tmp);
1549
1550         return label;
1551 }
1552
1553 static GtkWidget *
1554 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1555 {
1556         /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1557         
1558         GtkWidget *vbox;
1559         GtkWidget *label_w;
1560         gchar *label;
1561         gchar *gray_color_markup;
1562
1563         vbox = gtk_vbox_new (FALSE, 0);
1564
1565         gray_color_markup = get_gray_color_markup (styled_widget);
1566
1567         /* Account description: */
1568         if (modest_tny_account_is_virtual_local_folders (account)
1569                 || (modest_tny_account_is_memory_card_account (account))) {
1570         
1571                 /* Get device name */
1572                 gchar *device_name = NULL;
1573                 if (modest_tny_account_is_virtual_local_folders (account))
1574                         device_name = modest_conf_get_string (modest_runtime_get_conf(),
1575                                                       MODEST_CONF_DEVICE_NAME, NULL);
1576                 else
1577                         device_name = g_strdup (tny_account_get_name (account));
1578
1579                 label = create_device_name_visual_string ((const gchar *) device_name, 
1580                                                           (const gchar *) gray_color_markup);
1581                 label_w = gtk_label_new (NULL);
1582                 gtk_label_set_markup (GTK_LABEL (label_w), label);
1583                 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1584                 g_free (device_name);
1585                 g_free (label);
1586         } else {
1587                 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1588                         gtk_box_pack_start (GTK_BOX (vbox), 
1589                                 gtk_label_new (tny_account_get_name (account)), 
1590                                 FALSE, FALSE, 0);
1591                 } else {
1592                         /* Other accounts, such as IMAP and POP: */
1593                         
1594                         GString *proto;
1595                         gchar *tmp;
1596         
1597                         /* Put proto in uppercase */
1598                         proto = g_string_new (tny_account_get_proto (account));
1599                         proto = g_string_ascii_up (proto);
1600                         
1601                         /* note: mcen_fi_localroot_description is something like "%s account"
1602                          * however, we should display "%s account: %s"... therefore, ugly tmp */
1603                         tmp   = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1604                         label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", 
1605                                                          gray_color_markup, tmp, tny_account_get_name (account));
1606                         g_free (tmp);
1607
1608                         label_w = gtk_label_new (NULL);
1609                         gtk_label_set_markup (GTK_LABEL (label_w), label);
1610                         gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1611                         g_string_free (proto, TRUE);
1612                         g_free (label);
1613                 }
1614         }
1615
1616         /* Message count */
1617         TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1618         label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d", 
1619                                          gray_color_markup, _("mcen_fi_rootfolder_messages"), 
1620                                          modest_tny_folder_store_get_message_count (folder_store));
1621         label_w = gtk_label_new (NULL);
1622         gtk_label_set_markup (GTK_LABEL (label_w), label);
1623         gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1624         g_free (label);
1625
1626         /* Folder count */
1627         label = g_markup_printf_escaped ("<span color='%s'>%s</span>: %d", 
1628                                          gray_color_markup, 
1629                                          _("mcen_fi_rootfolder_folders"), 
1630                                          modest_tny_folder_store_get_folder_count (folder_store));
1631         label_w = gtk_label_new (NULL);
1632         gtk_label_set_markup (GTK_LABEL (label_w), label);
1633         gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1634         g_free (label);
1635
1636         /* Size / Date */
1637         if (modest_tny_account_is_virtual_local_folders (account)
1638                 || modest_tny_account_is_memory_card_account (account)) {
1639
1640                 gchar *size = modest_text_utils_get_display_size (
1641                         modest_tny_folder_store_get_local_size (folder_store));
1642                 
1643                 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", 
1644                                                  gray_color_markup, _("mcen_fi_rootfolder_size"),
1645                                                  size);
1646                 g_free (size);
1647                 
1648                 label_w = gtk_label_new (NULL);
1649                 gtk_label_set_markup (GTK_LABEL (label_w), label);
1650                 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1651                 g_free (label);
1652         } else if (TNY_IS_ACCOUNT(folder_store)) {
1653                 TnyAccount *account = TNY_ACCOUNT(folder_store);
1654                 
1655                 time_t last_updated;
1656                 gchar *last_updated_string;
1657                 /* Get last updated from configuration */
1658                 last_updated = modest_account_mgr_get_last_updated (modest_runtime_get_account_mgr (), 
1659                                                                     tny_account_get_id (account));
1660
1661                 if (last_updated > 0) 
1662                         last_updated_string = modest_text_utils_get_display_date(last_updated);
1663                 else
1664                         last_updated_string = g_strdup (_("mcen_va_never"));
1665
1666                 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", 
1667                                                  gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1668                 label_w = gtk_label_new (NULL);
1669                 gtk_label_set_markup (GTK_LABEL (label_w), label);
1670                 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1671                 g_free (last_updated_string);
1672                 g_free (label);
1673         }
1674
1675         g_free (gray_color_markup);
1676
1677         /* Set alignment */
1678         gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1679
1680         return vbox;
1681 }
1682
1683 gboolean
1684 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1685 {
1686         ModestMainWindowPrivate *priv = NULL;
1687         
1688         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1689
1690         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1691
1692         return priv->send_receive_in_progress;
1693 }
1694
1695 void 
1696 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1697 {
1698         GtkAction *action = NULL;
1699         GtkWidget *widget = NULL;
1700         ModestMainWindowPrivate *priv = NULL;
1701                 
1702         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1703         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1704         
1705         priv->send_receive_in_progress  = TRUE;
1706
1707         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu"); 
1708         gtk_action_set_sensitive (action, FALSE);
1709 /*         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1710 /*      gtk_action_set_sensitive (action, FALSE); */
1711         widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");       
1712         gtk_widget_set_sensitive (widget, FALSE);
1713
1714
1715 void 
1716 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1717 {
1718         GtkAction *action = NULL;
1719         GtkWidget *widget = NULL;
1720         ModestMainWindowPrivate *priv = NULL;
1721                 
1722         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1723         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1724
1725         priv->send_receive_in_progress  = FALSE;
1726
1727         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu"); 
1728         gtk_action_set_sensitive (action, TRUE);
1729 /*         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu");     */
1730 /*      gtk_action_set_sensitive (action, TRUE); */
1731         widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");       
1732         gtk_widget_set_sensitive (widget, TRUE);
1733
1734
1735
1736 static void
1737 on_msg_count_changed (ModestHeaderView *header_view,
1738                       TnyFolder *folder,
1739                       TnyFolderChange *change,
1740                       ModestMainWindow *main_window)
1741 {
1742         gboolean folder_empty = FALSE;
1743         gboolean all_marked_as_deleted = FALSE;
1744         TnyFolderChangeChanged changed; 
1745         ModestMainWindowPrivate *priv;
1746         
1747         g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1748         g_return_if_fail (TNY_IS_FOLDER(folder));
1749         g_return_if_fail (TNY_IS_FOLDER_CHANGE(change));
1750         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
1751         
1752         changed = tny_folder_change_get_changed (change);
1753         
1754         /* If something changes */
1755         if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1756                 folder_empty = (tny_folder_change_get_new_all_count (change) == 0);
1757         else
1758                 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1759         
1760 /*      Check header removed  (hide marked as DELETED headers) */
1761         if (changed & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS) {
1762                 modest_header_view_refilter (MODEST_HEADER_VIEW(priv->header_view));
1763         }
1764
1765         /* Check if all messages are marked to be deleted */
1766         all_marked_as_deleted = modest_header_view_is_empty (header_view);
1767         folder_empty = folder_empty || all_marked_as_deleted ;
1768         
1769         /* Set contents style of headers view */
1770         if (folder_empty)  {
1771                 modest_main_window_set_contents_style (main_window,
1772                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1773                 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1774         }
1775         else {
1776                 modest_main_window_set_contents_style (main_window,
1777                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1778         }       
1779 }
1780
1781
1782 void 
1783 modest_main_window_set_contents_style (ModestMainWindow *self, 
1784                                        ModestMainWindowContentsStyle style)
1785 {
1786         ModestMainWindowPrivate *priv;
1787
1788         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1789
1790         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1791
1792         /* We allow to set the same content style than the previously
1793            set if there are details, because it could happen when we're
1794            selecting different accounts consecutively */
1795         if ((priv->contents_style == style) &&
1796             (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1797                 return;
1798
1799         /* Remove previous child. Delete it if it was an account
1800            details widget */
1801         GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1802         if (content) {
1803                 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1804                         g_object_ref (content);
1805                 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1806                         g_object_ref (priv->empty_view);
1807                         gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1808                 }
1809                 
1810                 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1811         }
1812
1813         priv->contents_style = style;
1814
1815         switch (priv->contents_style) {
1816         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1817                 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1818                 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1819                                                       TRUE);
1820                 break;
1821         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1822         {
1823                 /* if we're started without main win, there may not be a folder
1824                  * view. this fixes a GLib-Critical */
1825                 if (priv->folder_view) {
1826                         TnyFolderStore *selected_folderstore = 
1827                                 modest_folder_view_get_selected (priv->folder_view);
1828                         if (TNY_IS_ACCOUNT (selected_folderstore)) {    
1829                                 priv->details_widget = create_details_widget (GTK_WIDGET (self),
1830                                                                 TNY_ACCOUNT (selected_folderstore));
1831                                 
1832                                 wrap_in_scrolled_window (priv->contents_widget, 
1833                                                          priv->details_widget);
1834                         }
1835                         g_object_unref (selected_folderstore);
1836                         modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1837                                                               FALSE);
1838                 }
1839                 break;
1840         }
1841         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1842                 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1843                 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1844                                                       FALSE);
1845                 break;
1846         default:
1847                 g_return_if_reached ();
1848         }
1849
1850         /* Show */
1851         gtk_widget_show_all (priv->contents_widget);
1852 }
1853
1854 ModestMainWindowContentsStyle
1855 modest_main_window_get_contents_style (ModestMainWindow *self)
1856 {
1857         ModestMainWindowPrivate *priv;
1858
1859         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1860
1861         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1862         return priv->contents_style;
1863 }
1864
1865
1866 static void 
1867 on_configuration_key_changed (ModestConf* conf, 
1868                               const gchar *key, 
1869                               ModestConfEvent event,
1870                               ModestConfNotificationId id, 
1871                               ModestMainWindow *self)
1872 {
1873         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1874         TnyAccount *account = NULL;
1875
1876         if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
1877                 return;
1878
1879         if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1880                 return;
1881
1882         if (priv->folder_view) 
1883                 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1884
1885         if (account && TNY_IS_ACCOUNT (account) &&
1886             strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
1887                 GList *children;
1888                 GtkLabel *label;
1889                 const gchar *device_name;
1890                 gchar *new_text, *gray_color_markup;
1891                 
1892                 /* Get label */
1893                 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1894                 label = GTK_LABEL (children->data);
1895                 
1896                 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1897                                                       MODEST_CONF_DEVICE_NAME, NULL);
1898
1899                 gray_color_markup = get_gray_color_markup (GTK_WIDGET (self));          
1900                 new_text = create_device_name_visual_string (device_name, gray_color_markup);
1901                 
1902                 gtk_label_set_markup (label, new_text);
1903                 gtk_widget_show (GTK_WIDGET (label));
1904                 
1905                 g_free (gray_color_markup);
1906                 g_free (new_text);
1907                 g_list_free (children);
1908         }
1909         g_object_unref (account);
1910 }
1911
1912 static gboolean
1913 set_toolbar_transfer_mode (ModestMainWindow *self)
1914 {
1915         ModestMainWindowPrivate *priv = NULL;
1916         
1917         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1918
1919         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1920
1921         set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1922         
1923         if (priv->progress_bar_timeout > 0) {
1924                 g_source_remove (priv->progress_bar_timeout);
1925                 priv->progress_bar_timeout = 0;
1926         }
1927
1928         return FALSE;
1929 }
1930
1931 static void 
1932 set_toolbar_mode (ModestMainWindow *self, 
1933                   ModestToolBarModes mode)
1934 {
1935         ModestWindowPrivate *parent_priv = NULL;
1936         ModestMainWindowPrivate *priv = NULL;
1937         GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1938         
1939         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1940
1941         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1942         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1943
1944         /* In case this was called before the toolbar exists: */
1945         if (!(parent_priv->toolbar))
1946                 return;
1947
1948         g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar)); 
1949         
1950         sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1951         refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1952         cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1953
1954         /* Sets current toolbar mode */
1955         priv->current_toolbar_mode = mode;
1956
1957         /* Checks the dimming rules */
1958         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1959
1960         /* Show and hide toolbar items */
1961         switch (mode) {
1962         case TOOLBAR_MODE_NORMAL:
1963                 if (sort_action)
1964                         gtk_action_set_visible (sort_action, TRUE);
1965                 if (refresh_action)
1966                         gtk_action_set_visible (refresh_action, TRUE);
1967                 if (priv->progress_toolitem) {
1968                         gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1969                         gtk_widget_hide (priv->progress_toolitem);
1970                 }
1971                 if (priv->progress_bar)
1972                         gtk_widget_hide (priv->progress_bar);
1973                 
1974                 if (cancel_action)
1975                         gtk_action_set_visible (cancel_action, FALSE);
1976
1977                 /* Hide toolbar if optimized view is enabled */
1978                 if (priv->optimized_view)
1979                         gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
1980                 break;
1981         case TOOLBAR_MODE_TRANSFER:
1982                 if (sort_action)
1983                         gtk_action_set_visible (sort_action, FALSE);
1984                 if (refresh_action)
1985                         gtk_action_set_visible (refresh_action, FALSE);
1986                 if (cancel_action)
1987                         gtk_action_set_visible (cancel_action, TRUE);
1988                 if (priv->progress_toolitem) {
1989                         gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1990                         gtk_widget_show (priv->progress_toolitem);
1991                 }
1992                 if (priv->progress_bar)
1993                         gtk_widget_show (priv->progress_bar);
1994
1995                 /* Show toolbar if it's hiden (optimized view ) */
1996                 if (priv->optimized_view)
1997                         gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1998                 break;
1999         default:
2000                 g_return_if_reached ();
2001         }
2002 }
2003
2004 gboolean
2005 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
2006 {
2007         ModestMainWindowPrivate *priv;
2008
2009         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2010         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2011
2012         return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
2013 }
2014
2015 static void
2016 cancel_progressbar (GtkToolButton *toolbutton,
2017                     ModestMainWindow *self)
2018 {
2019         GSList *tmp;
2020         ModestMainWindowPrivate *priv;
2021         
2022         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2023
2024         /* Get operation observers and cancel all the operations */
2025         tmp = priv->progress_widgets;
2026         while (tmp) {
2027                 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2028                 tmp=g_slist_next(tmp);
2029         }
2030 }
2031
2032 static gboolean
2033 observers_empty (ModestMainWindow *self)
2034 {
2035         GSList *tmp = NULL;
2036         ModestMainWindowPrivate *priv;
2037         gboolean is_empty = TRUE;
2038         guint pending_ops = 0;
2039  
2040         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2041         tmp = priv->progress_widgets;
2042
2043         /* Check all observers */
2044         while (tmp && is_empty)  {
2045                 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2046                 is_empty = pending_ops == 0;
2047                 
2048                 tmp = g_slist_next(tmp);
2049         }
2050         
2051         return is_empty;
2052 }
2053
2054
2055 /**
2056  * Gets the toolbar mode needed for each mail operation. It stores in
2057  * @mode_changed if the toolbar mode has changed or not
2058  */
2059 static ModestToolBarModes
2060 get_toolbar_mode_from_mail_operation (ModestMainWindow *self,
2061                                       ModestMailOperation *mail_op,
2062                                       gboolean *mode_changed)
2063 {
2064         ModestToolBarModes mode;
2065         ModestMainWindowPrivate *priv;
2066
2067         *mode_changed = FALSE;
2068         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2069
2070         /* Get toolbar mode from operation id*/
2071         switch (modest_mail_operation_get_type_operation (mail_op)) {
2072         case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2073         case MODEST_MAIL_OPERATION_TYPE_OPEN:
2074                 mode = TOOLBAR_MODE_TRANSFER;
2075                 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2076                         *mode_changed = TRUE;
2077                 break;
2078         default:
2079                 mode = TOOLBAR_MODE_NORMAL;             
2080         }
2081         return mode;
2082 }
2083
2084 static void 
2085 on_mail_operation_started (ModestMailOperation *mail_op,
2086                            gpointer user_data)
2087 {
2088         ModestMainWindow *self;
2089         ModestMailOperationTypeOperation op_type;
2090         ModestMainWindowPrivate *priv;
2091         ModestToolBarModes mode;
2092         GSList *tmp;
2093         gboolean mode_changed = FALSE;
2094         TnyAccount *account;
2095
2096         self = MODEST_MAIN_WINDOW (user_data);
2097         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2098
2099         /* Do not show progress for receiving operations if the
2100            account is the local account or the MMC one */
2101         op_type = modest_mail_operation_get_type_operation (mail_op);
2102         account = modest_mail_operation_get_account (mail_op);
2103         if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2104                 gboolean is_remote;
2105
2106                 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2107                               modest_tny_account_is_memory_card_account (account));
2108                 g_object_unref (account);
2109                 if (!is_remote)
2110                         return;
2111         }
2112                
2113         /* Get toolbar mode from operation id*/
2114         mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2115
2116         /* Add operation observers and change toolbar if neccessary*/
2117         tmp = priv->progress_widgets;
2118         if (mode == TOOLBAR_MODE_TRANSFER) {
2119                 if (mode_changed)
2120                         set_toolbar_transfer_mode(self);                    
2121
2122                 while (tmp) {
2123                         modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2124                                                               mail_op);
2125                         tmp = g_slist_next (tmp);
2126                 }
2127         }
2128 }
2129
2130 static void 
2131 on_mail_operation_finished (ModestMailOperation *mail_op,
2132                             gpointer user_data)
2133 {
2134         ModestToolBarModes mode;
2135         ModestMailOperationTypeOperation op_type;
2136         GSList *tmp = NULL;
2137         ModestMainWindow *self;
2138         gboolean mode_changed;
2139         TnyAccount *account;
2140         ModestMainWindowPrivate *priv;
2141
2142         self = MODEST_MAIN_WINDOW (user_data);
2143         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2144
2145         /* The mail operation was not added to the progress objects if
2146            the account was the local account or the MMC one */
2147         op_type = modest_mail_operation_get_type_operation (mail_op);
2148         account = modest_mail_operation_get_account (mail_op);
2149         if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) {
2150                 gboolean is_remote;
2151
2152                 is_remote = !(modest_tny_account_is_virtual_local_folders (account) ||
2153                               modest_tny_account_is_memory_card_account (account));
2154                 g_object_unref (account);
2155                 if (!is_remote)
2156                         return;
2157         }
2158
2159         /* Get toolbar mode from operation id*/
2160         mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed);
2161
2162         /* Change toolbar mode */
2163         tmp = priv->progress_widgets;
2164         if (mode == TOOLBAR_MODE_TRANSFER) {                    
2165                 while (tmp) {
2166                         modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2167                                                                  mail_op);
2168                         tmp = g_slist_next (tmp);
2169                 }
2170                 
2171                 /* If no more operations are being observed, NORMAL mode is enabled again */
2172                 if (observers_empty (self)) {
2173                         set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);                           
2174                 }
2175         }
2176 }
2177
2178 static void
2179 on_queue_changed (ModestMailOperationQueue *queue,
2180                   ModestMailOperation *mail_op,
2181                   ModestMailOperationQueueNotification type,
2182                   ModestMainWindow *self)
2183 {
2184         ModestMainWindowPrivate *priv;
2185
2186         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2187
2188         if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
2189                 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2190                                                                G_OBJECT (mail_op),
2191                                                                "operation-started",
2192                                                                G_CALLBACK (on_mail_operation_started),
2193                                                                self);
2194                 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
2195                                                                G_OBJECT (mail_op),
2196                                                                "operation-finished",
2197                                                                G_CALLBACK (on_mail_operation_finished),
2198                                                                self);
2199         } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
2200                 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2201                                                                   G_OBJECT (mail_op),
2202                                                                   "operation-started");
2203                 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
2204                                                                   G_OBJECT (mail_op),
2205                                                                   "operation-finished");
2206         }
2207 }
2208
2209 static void
2210 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2211 {
2212         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2213         GtkAction *action;
2214
2215         /* Get account data */
2216         ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
2217         ModestAccountData *acc_data = modest_account_mgr_get_account_data (mgr, acc_name);
2218
2219         /* Set the new visible & active account */
2220         if (acc_data && acc_data->store_account) { 
2221                 modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view,
2222                                                                              acc_data->store_account->account_name);
2223                 modest_window_set_active_account (MODEST_WINDOW (self), acc_data->account_name);
2224                 action = gtk_action_group_get_action (priv->view_additions_group, acc_data->account_name);
2225                 if (action != NULL) {
2226                         if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2227                                 modest_maemo_toggle_action_set_active_block_notify (
2228                                         GTK_TOGGLE_ACTION (action),
2229                                         TRUE);
2230                         }
2231                 }
2232         }
2233         
2234         modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2235
2236
2237         /* Free */
2238         if (acc_data)
2239                 modest_account_mgr_free_account_data (mgr, acc_data);
2240 }
2241
2242 /* Make sure that at least one account is "viewed": */
2243 static void
2244 set_at_least_one_account_visible(ModestMainWindow *self)
2245 {
2246         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2247         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2248
2249         if (!(priv->folder_view)) {
2250                 /* It is too early to do this. */
2251                 return; 
2252         }
2253         
2254         const gchar *active_server_account_name = 
2255                 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);        
2256         if (!active_server_account_name ||
2257                 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2258         {
2259                 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2260                 if (first_modest_name) {
2261                         set_account_visible (self, first_modest_name);
2262                         g_free (first_modest_name);
2263                 }
2264         }
2265 }
2266
2267 static void 
2268 on_show_account_action_toggled  (GtkToggleAction *action,
2269                                    gpointer user_data)
2270 {
2271         ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2272
2273         const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2274         if (gtk_toggle_action_get_active (action))
2275                 set_account_visible (self, acc_name);
2276 }
2277
2278 static void
2279 refresh_account (const gchar *account_name)
2280 {
2281         ModestWindow *win;
2282
2283         win = MODEST_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2284
2285         /* If account_name == NULL, we must update all (option All) */
2286         if (!account_name)
2287                 modest_ui_actions_do_send_receive_all (win);
2288         else
2289                 modest_ui_actions_do_send_receive (account_name, win);
2290         
2291 }
2292
2293 static void 
2294 on_refresh_account_action_activated  (GtkAction *action,
2295                                       gpointer user_data)
2296 {
2297         refresh_account ((const gchar*) user_data);
2298 }
2299
2300 static void
2301 on_send_receive_csm_activated (GtkMenuItem *item,
2302                                gpointer user_data)
2303 {
2304         refresh_account ((const gchar*) user_data);
2305 }
2306
2307 static gboolean
2308 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2309 {
2310         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2311
2312         hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2313         return FALSE;
2314
2315 }
2316
2317 static gboolean
2318 on_folder_view_focus_in (GtkWidget *widget,
2319                          GdkEventFocus *event,
2320                          gpointer userdata)
2321 {
2322         ModestMainWindow *main_window = NULL;
2323         
2324         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2325         main_window = MODEST_MAIN_WINDOW (userdata);
2326         
2327         /* Update toolbar dimming state */
2328         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2329
2330         return FALSE;
2331 }
2332
2333 static gboolean
2334 on_header_view_focus_in (GtkWidget *widget,
2335                          GdkEventFocus *event,
2336                          gpointer userdata)
2337 {
2338         ModestMainWindow *main_window = NULL;
2339         ModestMainWindowPrivate *priv = NULL;
2340
2341         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2342         main_window = MODEST_MAIN_WINDOW (userdata);
2343         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2344
2345         /* Update toolbar dimming state */
2346         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2347
2348         return FALSE;
2349 }
2350
2351 static void 
2352 modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
2353                                                 TnyFolderStore *folder_store, 
2354                                                 gboolean selected,
2355                                                 ModestMainWindow *main_window)
2356 {
2357         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2358         GtkAction *action = NULL;
2359         gboolean show_reply = TRUE;
2360         gboolean show_forward = TRUE;
2361         gboolean show_cancel_send = FALSE;
2362         gboolean show_clipboard = TRUE;
2363         gboolean show_delete = TRUE;
2364
2365         if (selected) {
2366                 if (TNY_IS_ACCOUNT (folder_store)) {
2367                         show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2368                 } else if (TNY_IS_FOLDER (folder_store)) {
2369                         if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2370                                 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2371                                         TNY_FOLDER (folder_store));
2372                                 switch (folder_type) {
2373                                 case TNY_FOLDER_TYPE_DRAFTS:
2374                                         show_clipboard = show_delete = TRUE;
2375                                         show_reply = show_forward = show_cancel_send = FALSE;
2376                                         break;
2377                                 case TNY_FOLDER_TYPE_SENT:
2378                                         show_forward = show_clipboard = show_delete = TRUE;
2379                                         show_reply = show_cancel_send = FALSE;
2380                                         break;
2381                                 case TNY_FOLDER_TYPE_OUTBOX:
2382                                         show_clipboard = show_delete = show_cancel_send = TRUE;
2383                                         show_reply = show_forward = FALSE;
2384                                         break;
2385                                 default:
2386                                         show_reply = show_forward = show_clipboard = show_delete = TRUE;
2387                                         show_cancel_send = FALSE;
2388                                 }
2389                         } else {
2390                                 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2391                                 show_cancel_send = FALSE;
2392                         }
2393                 }
2394         }
2395
2396         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2397         gtk_action_set_visible (action, show_reply);
2398         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2399         gtk_action_set_visible (action, show_reply);
2400         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2401         gtk_action_set_visible (action, show_forward);
2402         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2403         gtk_action_set_visible (action, show_cancel_send);
2404         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2405         gtk_action_set_visible (action, show_delete);
2406
2407         /* We finally call to the ui actions handler, after updating properly
2408          * the header view CSM */
2409         modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2410 }
2411
2412 gboolean 
2413 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2414                                                    GtkTreeModel *model,
2415                                                    GtkTreeRowReference *row_reference,
2416                                                    ModestMainWindow *self)
2417 {
2418         ModestMainWindowPrivate *priv = NULL;
2419         GtkTreeModel *header_model = NULL;
2420         GtkTreePath *path = NULL;
2421
2422         g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2423         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2424         g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2425
2426         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2427         header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2428
2429         /* Do nothing if we changed the folder in the main view */
2430         if (header_model != model)
2431                 return FALSE;
2432
2433         /* Select the message in the header view */
2434         path = gtk_tree_row_reference_get_path (row_reference);
2435         gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2436                                   path, NULL, FALSE);
2437         gtk_tree_path_free (path);
2438
2439         return TRUE;
2440 }
2441
2442 static gboolean
2443 show_updating_banner (gpointer user_data)
2444 {
2445         ModestMainWindowPrivate *priv = NULL;
2446
2447         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2448
2449         priv->updating_banner = 
2450                 modest_platform_animation_banner (GTK_WIDGET (user_data), NULL,
2451                                                   _CS ("ckdg_pb_updating"));
2452
2453         /* Remove timeout */
2454         priv->updating_banner_timeout = 0;
2455         return FALSE;
2456 }
2457
2458 /**
2459  * We use this function to show/hide a progress banner showing
2460  * "Updating" while the header view is being filled. We're not showing
2461  * it unless the update takes more than 2 seconds
2462  *
2463  * If starting = TRUE then the refresh is starting, otherwise it means
2464  * that is has just finished
2465  */
2466 static void 
2467 on_updating_msg_list (ModestHeaderView *header_view,
2468                       gboolean starting,
2469                       gpointer user_data)
2470 {
2471         ModestMainWindowPrivate *priv = NULL;
2472
2473         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
2474
2475         /* Remove old timeout */
2476         if (priv->updating_banner_timeout > 0) {
2477                 g_source_remove (priv->updating_banner_timeout);
2478                 priv->updating_banner_timeout = 0;
2479         }
2480
2481         /* Create a new timeout */
2482         if (starting) {
2483                 priv->updating_banner_timeout = 
2484                         g_timeout_add (2000, show_updating_banner, user_data);
2485         } else {
2486                 /* Remove the banner if exists */
2487                 if (priv->updating_banner) {
2488                         gtk_widget_destroy (priv->updating_banner);
2489                         priv->updating_banner = NULL;
2490                 }
2491         }
2492 }