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