* Fixed a compilation warning
[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 "modest-hildon-includes.h"
35 #include "modest-defs.h"
36 #include <string.h>
37
38 #include "widgets/modest-main-window.h"
39 #include "widgets/modest-msg-edit-window.h"
40 #include "widgets/modest-account-view-window.h"
41 #include "modest-runtime.h"
42 #include "modest-account-mgr-helpers.h"
43 #include "modest-platform.h"
44 #include "modest-widget-memory.h"
45 #include "modest-window-priv.h"
46 #include "modest-main-window-ui.h"
47 #include "modest-account-mgr.h"
48 #include "modest-tny-account.h"
49 #include "modest-conf.h"
50 #include <modest-maemo-utils.h>
51 #include "modest-tny-platform-factory.h"
52 #include "modest-tny-msg.h"
53 #include "modest-mail-operation.h"
54 #include "modest-icon-names.h"
55 #include "modest-progress-bar-widget.h"
56 #include "maemo/modest-osso-state-saving.h"
57
58 #ifdef MODEST_HILDON_VERSION_0
59 #include <hildon-widgets/hildon-program.h>
60 #else
61 #include <hildon/hildon-program.h>
62 #endif /*MODEST_HILDON_VERSION_0*/
63
64 #define MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS "ModestMainWindowActionAdditions"
65
66 /* 'private'/'protected' functions */
67 static void modest_main_window_class_init    (ModestMainWindowClass *klass);
68 static void modest_main_window_init          (ModestMainWindow *obj);
69 static void modest_main_window_finalize      (GObject *obj);
70 static gboolean modest_main_window_window_state_event (GtkWidget *widget, 
71                                                            GdkEventWindowState *event, 
72                                                            gpointer userdata);
73
74 static void connect_signals (ModestMainWindow *self);
75
76 static void restore_settings (ModestMainWindow *self);
77 static void save_state (ModestWindow *self);
78
79 static void modest_main_window_show_toolbar   (ModestWindow *window,
80                                                gboolean show_toolbar);
81
82 static void cancel_progressbar (GtkToolButton *toolbutton,
83                                 ModestMainWindow *self);
84
85 static void         on_queue_changed                     (ModestMailOperationQueue *queue,
86                                                           ModestMailOperation *mail_op,
87                                                           ModestMailOperationQueueNotification type,
88                                                           ModestMainWindow *self);
89
90 static void on_account_update                 (TnyAccountStore *account_store, 
91                                                gchar *account_name,
92                                                gpointer user_data);
93
94 static gboolean on_inner_widgets_key_pressed  (GtkWidget *widget,
95                                                GdkEventKey *event,
96                                                gpointer user_data);
97
98 static void on_configuration_key_changed      (ModestConf* conf, 
99                                                const gchar *key, 
100                                                ModestConfEvent event, 
101                                                ModestMainWindow *self);
102
103 static void set_toolbar_mode                  (ModestMainWindow *self, 
104                                                ModestToolBarModes mode);
105
106 static void on_show_account_action_activated  (GtkAction *action,
107                                                gpointer user_data);
108
109 /* list my signals */
110 enum {
111         /* MY_SIGNAL_1, */
112         /* MY_SIGNAL_2, */
113         LAST_SIGNAL
114 };
115
116
117 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
118 struct _ModestMainWindowPrivate {
119         GtkWidget *msg_paned;
120         GtkWidget *main_paned;
121         GtkWidget *main_vbox;
122         GtkWidget *contents_widget;
123
124         /* Progress observers */
125         GtkWidget        *progress_bar;
126         GSList           *progress_widgets;
127
128         /* Tollbar items */
129         GtkWidget   *progress_toolitem;
130         GtkWidget   *cancel_toolitem;
131         GtkWidget   *sort_toolitem;
132         GtkWidget   *refresh_toolitem;
133         ModestToolBarModes current_toolbar_mode;
134
135         /* Merge ids used to add/remove accounts to the ViewMenu*/
136         GByteArray *merge_ids;
137
138         /* On-demand widgets */
139         GtkWidget *accounts_popup;
140         GtkWidget *details_widget;
141
142         /* Optimized view enabled */
143         gboolean optimized_view;
144
145         ModestHeaderView *header_view;
146         ModestFolderView *folder_view;
147
148         ModestMainWindowStyle style;
149         ModestMainWindowContentsStyle contents_style;
150 };
151 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
152                                                 MODEST_TYPE_MAIN_WINDOW, \
153                                                 ModestMainWindowPrivate))
154
155 typedef struct _GetMsgAsyncHelper {
156         ModestMainWindowPrivate *main_window_private;
157         guint action;
158         ModestTnyMsgReplyType reply_type;
159         ModestTnyMsgForwardType forward_type;
160         gchar *from;
161         TnyIterator *iter;
162 } GetMsgAsyncHelper;
163
164
165 /* globals */
166 static GtkWindowClass *parent_class = NULL;
167
168
169 /* Private actions */
170 static const GtkActionEntry modest_folder_view_action_entries [] = {
171
172         /* Folder View CSM actions */
173         { "FolderViewCSMNewFolder", NULL, N_("FIXME: New Folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
174         { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
175         { "FolderViewCSMPasteMsgs", NULL, N_("FIXME: Paste"), NULL, NULL, NULL },
176         { "FolderViewCSMDeleteFolder", NULL, N_("FIXME: Delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
177         { "FolderViewCSMSearchMessages", NULL, N_("mcen_me_inbox_search"), NULL, NULL, NULL },
178         { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, NULL },
179 };
180
181
182 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
183         { "ToolbarToggleView", MODEST_STOCK_SPLIT_VIEW, N_("gqn_toolb_rss_fldonoff"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), FALSE },
184 };
185
186 /************************************************************************/
187
188 GType
189 modest_main_window_get_type (void)
190 {
191         static GType my_type = 0;
192         if (!my_type) {
193                 static const GTypeInfo my_info = {
194                         sizeof(ModestMainWindowClass),
195                         NULL,           /* base init */
196                         NULL,           /* base finalize */
197                         (GClassInitFunc) modest_main_window_class_init,
198                         NULL,           /* class finalize */
199                         NULL,           /* class data */
200                         sizeof(ModestMainWindow),
201                         1,              /* n_preallocs */
202                         (GInstanceInitFunc) modest_main_window_init,
203                         NULL
204                 };
205                 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
206                                                   "ModestMainWindow",
207                                                   &my_info, 0);
208         }
209         return my_type;
210 }
211
212 static void
213 modest_main_window_class_init (ModestMainWindowClass *klass)
214 {
215         GObjectClass *gobject_class;
216         gobject_class = (GObjectClass*) klass;
217         ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
218
219         parent_class            = g_type_class_peek_parent (klass);
220         gobject_class->finalize = modest_main_window_finalize;
221
222         g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
223         
224         modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
225         modest_window_class->save_state_func = save_state;
226 }
227
228 static void
229 modest_main_window_init (ModestMainWindow *obj)
230 {
231         ModestMainWindowPrivate *priv;
232
233         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
234
235         priv->msg_paned    = NULL;
236         priv->main_paned   = NULL;      
237         priv->main_vbox    = NULL;
238         priv->header_view  = NULL;
239         priv->folder_view  = NULL;
240         priv->contents_widget  = NULL;
241         priv->accounts_popup  = NULL;
242         priv->details_widget  = NULL;
243
244         priv->optimized_view  = FALSE;
245
246         priv->progress_widgets  = NULL;
247         priv->progress_bar = NULL;
248         priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
249
250         priv->style  = MODEST_MAIN_WINDOW_STYLE_SPLIT;
251         priv->contents_style  = MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS;
252
253         priv->merge_ids = NULL;
254 }
255
256 static void
257 modest_main_window_finalize (GObject *obj)
258 {
259         ModestMainWindowPrivate *priv;
260
261         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
262
263         g_slist_free (priv->progress_widgets);
264
265         g_byte_array_free (priv->merge_ids, TRUE);
266
267         G_OBJECT_CLASS(parent_class)->finalize (obj);
268 }
269
270 GtkWidget*
271 modest_main_window_get_child_widget (ModestMainWindow *self,
272                                      ModestWidgetType widget_type)
273 {
274         ModestMainWindowPrivate *priv;
275         GtkWidget *widget;
276         
277         g_return_val_if_fail (self, NULL);
278         g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_WIDGET_TYPE_NUM,
279                               NULL);
280         
281         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
282
283         switch (widget_type) {
284         case MODEST_WIDGET_TYPE_HEADER_VIEW:
285                 widget = (GtkWidget*)priv->header_view; break;
286         case MODEST_WIDGET_TYPE_FOLDER_VIEW:
287                 widget = (GtkWidget*)priv->folder_view; break;
288         default:
289                 return NULL;
290         }
291
292         return widget ? GTK_WIDGET(widget) : NULL;
293 }
294
295
296
297 static void
298 restore_settings (ModestMainWindow *self)
299 {
300         ModestConf *conf;
301         ModestMainWindowPrivate *priv;
302
303         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
304
305         conf = modest_runtime_get_conf ();
306         
307         modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
308                                       MODEST_CONF_MAIN_PANED_KEY);
309         modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
310                                       MODEST_CONF_HEADER_VIEW_KEY);
311         modest_widget_memory_restore (conf, G_OBJECT(self), 
312                                       MODEST_CONF_MAIN_WINDOW_KEY);
313 }
314
315
316 static void
317 save_state (ModestWindow *window)
318 {
319         ModestConf *conf;
320         ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
321         ModestMainWindowPrivate *priv;
322                 
323         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
324         conf = modest_runtime_get_conf ();
325         
326         modest_widget_memory_save (conf,G_OBJECT(self), 
327                                    MODEST_CONF_MAIN_WINDOW_KEY);
328         modest_widget_memory_save (conf, G_OBJECT(priv->main_paned), 
329                                    MODEST_CONF_MAIN_PANED_KEY);
330         modest_widget_memory_save (conf, G_OBJECT(priv->header_view), 
331                                    MODEST_CONF_HEADER_VIEW_KEY);
332 }
333
334 static void
335 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
336 {
337         if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
338                 gtk_scrolled_window_add_with_viewport
339                         (GTK_SCROLLED_WINDOW(win), widget);
340         else
341                 gtk_container_add (GTK_CONTAINER(win),
342                                    widget);
343 }
344
345
346 static gboolean
347 on_delete_event (GtkWidget *widget, GdkEvent  *event, ModestMainWindow *self)
348 {
349         modest_window_save_state (MODEST_WINDOW(self));
350         return FALSE;
351 }
352
353
354 static void
355 on_connection_changed (TnyDevice *device, gboolean online, ModestMainWindow *self)
356 {
357         /* When going online, do the equivalent of pressing the send/receive button, 
358          * as per the specification:
359          * (without the check for >0 accounts, though that is not specified): */
360         if (online) {
361                 do_send_receive (MODEST_WINDOW (self));
362         }
363 }
364
365
366
367 static void
368 connect_signals (ModestMainWindow *self)
369 {       
370         ModestWindowPrivate *parent_priv;
371         ModestMainWindowPrivate *priv;
372         GtkWidget *menu;
373         
374         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
375         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
376         
377         /* folder view */
378         g_signal_connect (G_OBJECT(priv->folder_view), "key-press-event",
379                           G_CALLBACK(on_inner_widgets_key_pressed), self);
380         g_signal_connect (G_OBJECT(priv->folder_view), "folder_selection_changed",
381                           G_CALLBACK(modest_ui_actions_on_folder_selection_changed), self);
382         g_signal_connect (G_OBJECT(priv->folder_view), "folder-display-name-changed",
383                           G_CALLBACK(modest_ui_actions_on_folder_display_name_changed), self);
384
385         menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
386         gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
387
388         /* header view */
389 /*      g_signal_connect (G_OBJECT(priv->header_view), "status_update", */
390 /*                        G_CALLBACK(modest_ui_actions_on_header_status_update), self); */
391         g_signal_connect (G_OBJECT(priv->header_view), "header_selected",
392                           G_CALLBACK(modest_ui_actions_on_header_selected), self);
393         g_signal_connect (G_OBJECT(priv->header_view), "header_activated",
394                           G_CALLBACK(modest_ui_actions_on_header_activated), self);
395         g_signal_connect (G_OBJECT(priv->header_view), "item_not_found",
396                           G_CALLBACK(modest_ui_actions_on_item_not_found), self);
397         g_signal_connect (G_OBJECT(priv->header_view), "key-press-event",
398                           G_CALLBACK(on_inner_widgets_key_pressed), self);
399
400         /* window */
401         g_signal_connect (G_OBJECT(self), "delete-event", G_CALLBACK(on_delete_event), self);
402         g_signal_connect (G_OBJECT (self), "window-state-event",
403                           G_CALLBACK (modest_main_window_window_state_event),
404                           NULL);
405         g_signal_connect (G_OBJECT(self), "delete-event", G_CALLBACK(on_delete_event), self);
406
407         /* Mail Operation Queue */
408         g_signal_connect (G_OBJECT (modest_runtime_get_mail_operation_queue ()),
409                           "queue-changed",
410                           G_CALLBACK (on_queue_changed),
411                           self);
412
413         /* Track changes in the device name */
414         g_signal_connect (G_OBJECT(modest_runtime_get_conf ()),
415                           "key_changed",
416                           G_CALLBACK (on_configuration_key_changed), 
417                           self);
418
419         /* Track account changes. We need to refresh the toolbar */
420         g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
421                           "account_update",
422                           G_CALLBACK (on_account_update),
423                           self);
424
425         /* Device */
426         g_signal_connect (G_OBJECT(modest_runtime_get_device()), "connection_changed",
427                           G_CALLBACK(on_connection_changed), self);
428 }
429
430 /** Idle handler, to send/receive at startup .*/
431 gboolean
432 sync_accounts_cb (ModestMainWindow *win)
433 {
434         do_send_receive (MODEST_WINDOW(win));
435         return FALSE; /* Do not call this idle handler again. */
436 }
437
438 static void on_hildon_program_is_topmost_notify(GObject *self,
439         GParamSpec *propert_param, gpointer user_data)
440 {
441         HildonProgram *app = HILDON_PROGRAM (self);
442         
443         /*
444         ModestWindow* self = MODEST_WINDOW(user_data);
445         */
446         
447         /* Note that use of hildon_program_set_can_hibernate() 
448          * is generally referred to as "setting the killable flag", 
449          * though hibernation does not seem equal to death.
450          * murrayc */
451                  
452         if (hildon_program_get_is_topmost (app)) {
453                 /* Prevent hibernation when the progam comes to the foreground,
454                  * because hibernation should only happen when the application 
455                  * is in the background: */
456                 hildon_program_set_can_hibernate (app, FALSE);
457         } else {
458                 /* Allow hibernation if the program has gone to the background: */
459                 
460                 /* However, prevent hibernation while the settings are being changed: */
461                 const gboolean hibernation_prevented = 
462                         modest_window_mgr_get_hibernation_is_prevented (
463         modest_runtime_get_window_mgr ()); 
464         
465                 if (hibernation_prevented)
466                         hildon_program_set_can_hibernate (app, FALSE);
467                 else {
468                         /* Allow hibernation, after saving the state: */
469                         modest_osso_save_state();
470                         hildon_program_set_can_hibernate (app, TRUE);
471                 }
472         }
473         
474 }
475
476
477
478 ModestWindow*
479 modest_main_window_new (void)
480 {
481         ModestMainWindow *self; 
482         ModestMainWindowPrivate *priv;
483         ModestWindowPrivate *parent_priv;
484         GtkWidget *folder_win;
485         GtkActionGroup *action_group;
486         GError *error = NULL;
487         TnyFolderStoreQuery *query;
488         GdkPixbuf *window_icon;
489         ModestConf *conf;
490         GtkAction *action;
491
492         self  = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
493         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
494         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
495
496         parent_priv->ui_manager = gtk_ui_manager_new();
497         action_group = gtk_action_group_new ("ModestMainWindowActions");
498         gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
499
500         /* Add common actions */
501         gtk_action_group_add_actions (action_group,
502                                       modest_action_entries,
503                                       G_N_ELEMENTS (modest_action_entries),
504                                       self);
505
506         gtk_action_group_add_actions (action_group,
507                                       modest_folder_view_action_entries,
508                                       G_N_ELEMENTS (modest_folder_view_action_entries),
509                                       self);
510
511         gtk_action_group_add_toggle_actions (action_group,
512                                              modest_toggle_action_entries,
513                                              G_N_ELEMENTS (modest_toggle_action_entries),
514                                              self);
515
516         gtk_action_group_add_toggle_actions (action_group,
517                                              modest_main_window_toggle_action_entries,
518                                              G_N_ELEMENTS (modest_main_window_toggle_action_entries),
519                                              self);
520
521         gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
522         g_object_unref (action_group);
523
524         /* Load the UI definition */
525         gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
526                                          MODEST_UIDIR "modest-main-window-ui.xml", &error);
527         if (error != NULL) {
528                 g_warning ("Could not merge modest-ui.xml: %s", error->message);
529                 g_error_free (error);
530                 error = NULL;
531         }
532
533         /* Add accelerators */
534         gtk_window_add_accel_group (GTK_WINDOW (self), 
535                                     gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
536
537         /* Menubar. Update the state of some toggles */
538         parent_priv->menubar = modest_maemo_utils_menubar_to_menu (parent_priv->ui_manager);
539         conf = modest_runtime_get_conf ();
540         action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
541                                             "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
542         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
543                                       modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR, NULL));
544         action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
545                                             "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
546         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
547                                       modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR_FULLSCREEN, NULL));
548         hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
549
550         /* folder view */
551         query = tny_folder_store_query_new ();
552         tny_folder_store_query_add_item (query, NULL,
553                                          TNY_FOLDER_STORE_QUERY_OPTION_SUBSCRIBED);
554         priv->folder_view = MODEST_FOLDER_VIEW(modest_folder_view_new (query));
555         if (!priv->folder_view)
556                 g_printerr ("modest: cannot instantiate folder view\n");
557         g_object_unref (G_OBJECT (query));
558         modest_folder_view_set_style (priv->folder_view,
559                                       MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
560
561         /* Get device name */
562         modest_maemo_utils_get_device_name ();
563
564         /* header view */
565         priv->header_view  =
566                 MODEST_HEADER_VIEW(modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
567         if (!priv->header_view)
568                 g_printerr ("modest: cannot instantiate header view\n");
569         modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
570         
571         /* Create scrolled windows */
572         folder_win = gtk_scrolled_window_new (NULL, NULL);
573         priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
574         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
575                                         GTK_POLICY_NEVER,
576                                         GTK_POLICY_AUTOMATIC);
577         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
578                                         GTK_POLICY_NEVER,
579                                         GTK_POLICY_AUTOMATIC);
580
581         wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
582         wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET(priv->header_view));
583
584         /* paned */
585         priv->main_paned = gtk_hpaned_new ();
586         gtk_paned_add1 (GTK_PANED(priv->main_paned), folder_win);
587         gtk_paned_add2 (GTK_PANED(priv->main_paned), priv->contents_widget);
588         gtk_widget_show (GTK_WIDGET(priv->header_view));
589         gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
590
591         /* putting it all together... */
592         priv->main_vbox = gtk_vbox_new (FALSE, 6);
593         gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
594
595         gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
596         restore_settings (MODEST_MAIN_WINDOW(self));
597
598         /* Set window icon */
599         window_icon = modest_platform_get_icon (MODEST_APP_ICON);
600         gtk_window_set_icon (GTK_WINDOW (self), window_icon);
601         
602         /* Connect signals */
603         connect_signals (self);
604
605         /* Set account store */
606         tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
607                                                   TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
608
609         /* do send & receive when we are idle */
610         g_idle_add ((GSourceFunc)sync_accounts_cb, self);
611         
612
613         HildonProgram *app = hildon_program_get_instance ();
614         hildon_program_add_window (app, HILDON_WINDOW (self));
615         
616         /* Register HildonProgram  signal handlers: */
617         /* These are apparently deprecated, according to the 
618          * "HildonApp/HildonAppView to HildonProgram/HildonWindow migration guide",
619          * though the API reference does not mention that:
620          *
621         g_signal_connect (G_OBJECT(app), "topmost_status_lose",
622                 G_CALLBACK (on_hildon_program_save_state), self);
623         g_signal_connect (G_OBJECT(app), "topmost_status_acquire",
624                 G_CALLBACK (on_hildon_program_status_acquire), self);
625     */
626         g_signal_connect (G_OBJECT(app), "notify::is-topmost",
627                 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
628                 
629         /* Load previous osso state, for instance if we are being restored from 
630          * hibernation:  */
631         modest_osso_load_state();
632
633         return MODEST_WINDOW(self);
634 }
635
636 gboolean 
637 modest_main_window_close_all (ModestMainWindow *self)
638 {
639         GtkWidget *note;
640         GtkResponseType response;
641
642         /* Create the confirmation dialog MSG-NOT308 */
643         note = hildon_note_new_confirmation_add_buttons (GTK_WINDOW (self),
644                                                          _("emev_nc_close_windows"),
645                                                          _("mcen_bd_yes"), GTK_RESPONSE_YES,
646                                                          _("mcen_bd_no"), GTK_RESPONSE_NO,
647                                                          NULL);
648
649         response = gtk_dialog_run (GTK_DIALOG (note));
650         gtk_widget_destroy (GTK_WIDGET (note));
651
652         if (response == GTK_RESPONSE_YES)
653                 return TRUE;
654         else
655                 return FALSE;
656 }
657
658
659 void 
660 modest_main_window_set_style (ModestMainWindow *self, 
661                               ModestMainWindowStyle style)
662 {
663         ModestMainWindowPrivate *priv;
664         ModestWindowPrivate *parent_priv;
665         GtkAction *action;
666
667         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
668
669         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
670         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
671
672         /* no change -> nothing to do */
673         if (priv->style == style)
674                 return;
675
676         /* Get toggle button */
677         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarToggleView");
678
679         priv->style = style;
680
681         switch (style) {
682         case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
683                 /* Remove main paned */
684                 g_object_ref (priv->main_paned);
685                 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
686
687                 /* Reparent the contents widget to the main vbox */
688                 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
689
690                 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
691                 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
692                 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
693
694                 break;
695         case MODEST_MAIN_WINDOW_STYLE_SPLIT:
696                 /* Remove header view */
697                 g_object_ref (priv->contents_widget);
698                 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
699
700                 /* Reparent the main paned */
701                 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
702                 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
703
704                 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
705                 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), FALSE);
706                 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
707
708                 break;
709         default:
710                 g_return_if_reached ();
711         }
712
713         /* Let header view grab the focus if it's being shown */
714         if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
715                 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
716         else 
717                 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
718
719         /* Show changes */
720         gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
721 }
722
723 ModestMainWindowStyle
724 modest_main_window_get_style (ModestMainWindow *self)
725 {
726         ModestMainWindowPrivate *priv;
727
728         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
729
730         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
731         return priv->style;
732 }
733
734
735
736 static gboolean
737 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
738 {
739         if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
740                 ModestWindowPrivate *parent_priv;
741                 ModestWindowMgr *mgr;
742                 gboolean is_fullscreen;
743                 GtkAction *fs_toggle_action;
744                 gboolean active;
745                 
746                 mgr = modest_runtime_get_window_mgr ();
747                 
748                 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
749
750                 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
751                 
752                 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
753                 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
754                 if (is_fullscreen != active) {
755                         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
756                 }
757         }
758
759         return FALSE;
760
761 }
762
763 static void
764 set_homogeneous (GtkWidget *widget,
765                  gpointer data)
766 {
767         gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
768         gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
769 }
770
771 static void 
772 modest_main_window_show_toolbar (ModestWindow *self,
773                                  gboolean show_toolbar)
774 {
775         ModestMainWindowPrivate *priv = NULL;
776         ModestWindowPrivate *parent_priv = NULL;        
777         GtkWidget *reply_button = NULL, *menu = NULL;
778         GtkWidget *placeholder = NULL;
779         gint insert_index;
780
781         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
782         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
783         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
784
785         /* Set optimized view status */
786         priv->optimized_view = !show_toolbar;
787
788         if (!parent_priv->toolbar) {
789                 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, 
790                                                                   "/ToolBar");
791
792                 /* Set homogeneous toolbar */
793                 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar), 
794                                        set_homogeneous, NULL);
795         
796                 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
797                 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
798                 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
799                 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
800                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
801                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
802                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
803                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
804
805                 /* Add ProgressBar (Transfer toolbar) */ 
806                 priv->progress_bar = modest_progress_bar_widget_new ();
807                 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
808                 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
809                 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
810                 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
811                 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
812                 
813                 /* Connect cancel 'clicked' signal to abort progress mode */
814                 g_signal_connect(priv->cancel_toolitem, "clicked",
815                                  G_CALLBACK(cancel_progressbar),
816                                  self);
817                 
818                 /* Add it to the observers list */
819                 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
820
821                 /* Add to window */
822                 hildon_window_add_toolbar (HILDON_WINDOW (self), 
823                                            GTK_TOOLBAR (parent_priv->toolbar));
824
825                 /* Set reply button tap and hold menu */
826                 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager, 
827                                                           "/ToolBar/ToolbarMessageReply");
828                 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
829                                                   "/ToolbarReplyCSM");
830                 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
831
832                 /* Set send & receive button tap and hold menu */
833                 on_account_update (TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()),
834                                    NULL, self);
835         }
836
837         if (show_toolbar) {
838                 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
839                 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
840                 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
841                 
842                 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
843                 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
844         } else
845                 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
846
847 }
848
849 static gint
850 compare_display_names (ModestAccountData *a,
851                        ModestAccountData *b)
852 {
853         return strcmp (a->display_name, b->display_name);
854 }
855
856 /*
857  * TODO: modify the menu dynamically. Add handlers to each item of the
858  * menu when created
859  */
860 static void 
861 on_account_update (TnyAccountStore *account_store, 
862                    gchar *accout_name,
863                    gpointer user_data)
864 {
865         GSList *account_names, *iter, *accounts;
866         ModestMainWindow *self;
867         ModestMainWindowPrivate *priv;
868         ModestWindowPrivate *parent_priv;
869         ModestAccountMgr *mgr;
870         gint i, num_accounts;
871         ModestAccountData *account_data;                                        
872         GtkActionGroup *action_group;
873         GList *groups;
874         gchar *default_account;
875         GtkWidget *send_receive_button, *item;
876                 
877         self = MODEST_MAIN_WINDOW (user_data);
878         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
879         parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
880
881         /* Get enabled account IDs */
882         mgr = modest_runtime_get_account_mgr ();
883         account_names = modest_account_mgr_account_names (mgr, TRUE);
884         iter = account_names;
885         accounts = NULL;
886
887         while (iter) {
888                 account_data = modest_account_mgr_get_account_data (mgr, (gchar*) iter->data);
889                 accounts = g_slist_prepend (accounts, account_data);
890
891                 iter = iter->next;
892         }
893         g_slist_free (account_names);
894
895         /* Order the list of accounts by its display name */
896         accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
897         num_accounts = g_slist_length (accounts);
898
899         /* Delete old send&receive popup items. We can not just do a
900            menu_detach because it does not work well with
901            tap_and_hold */
902         if (priv->accounts_popup)
903                 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup), (GtkCallback) gtk_widget_destroy, NULL);
904
905         /* Delete old entries in the View menu. Do not free groups, it
906            belongs to Gtk+ */
907         groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
908         while (groups) {
909                 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
910                              gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
911                         gtk_ui_manager_remove_action_group (parent_priv->ui_manager, 
912                                                             GTK_ACTION_GROUP (groups->data));
913                         groups = NULL;
914                         /* Remove uis */
915                         if (priv->merge_ids) {
916                                 for (i = 0; i < priv->merge_ids->len; i++)
917                                         gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
918                                 g_byte_array_free (priv->merge_ids, TRUE);
919                         }
920                         /* We need to call this in order to ensure
921                            that the new actions are added in the right
922                            order (alphabetical */
923                         gtk_ui_manager_ensure_update (parent_priv->ui_manager);
924                 } else 
925                         groups = g_list_next (groups);
926         }
927         priv->merge_ids = g_byte_array_sized_new (num_accounts);
928
929         /* Get send receive button */
930         send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
931                                                           "/ToolBar/ToolbarSendReceive");
932
933         /* Create the menu */
934         if (num_accounts > 1) {
935                 if (!priv->accounts_popup)
936                         priv->accounts_popup = gtk_menu_new ();
937                 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
938                 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
939                 item = gtk_separator_menu_item_new ();
940                 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
941         }
942
943         /* Create a new action group */
944         default_account = modest_account_mgr_get_default_account (mgr);
945         action_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
946         for (i = 0; i < num_accounts; i++) {
947                 GtkAction *new_action;
948                 gchar* item_name, *display_name;
949                 guint8 merge_id;
950
951                 account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
952
953                 /* Create display name. The default account is shown differently */
954                 if (default_account && !(strcmp (default_account, account_data->account_name) == 0))
955                         display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"), 
956                                                         account_data->display_name);
957                 else
958                         display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"), 
959                                                         account_data->display_name);
960
961                 /* Create action and add it to the action group. The
962                    action name must be the account name, this way we
963                    could know in the handlers the account to show */
964                 new_action = gtk_action_new (account_data->account_name, display_name, NULL, NULL);
965                 gtk_action_group_add_action (action_group, new_action);
966
967                 /* Add ui from account data. We allow 2^9-1 account
968                    changes in a single execution because we're
969                    downcasting the guint to a guint8 in order to use a
970                    GByteArray, it should be enough */
971                 item_name = g_strconcat (account_data->account_name, "Menu");
972                 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
973                 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
974                 gtk_ui_manager_add_ui (parent_priv->ui_manager, 
975                                        merge_id,
976                                        "/MenuBar/ViewMenu/ViewMenuAdditions",
977                                        item_name,
978                                        account_data->account_name,
979                                        GTK_UI_MANAGER_MENUITEM,
980                                        FALSE);
981
982                 /* Connect the action signal "activate" */
983                 g_signal_connect (G_OBJECT (new_action), 
984                                   "activate", 
985                                   G_CALLBACK (on_show_account_action_activated), 
986                                   self);
987
988                 /* Create item and add it to the send&receive CSM */
989                 item = gtk_menu_item_new_with_label (display_name);
990                 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
991
992                 /* Frees */
993                 g_free (display_name);
994                 g_free (item_name);
995                 modest_account_mgr_free_account_data (mgr, account_data);
996         }
997         gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 1);
998
999         if (priv->accounts_popup) {
1000                 /* Mandatory in order to view the menu contents */
1001                 gtk_widget_show_all (priv->accounts_popup);
1002
1003                 /* Setup tap_and_hold just if was not done before*/
1004                 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
1005                         gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
1006         }
1007
1008         /* Frees */
1009         g_slist_free (accounts);
1010         g_free (default_account);
1011 }
1012
1013 /* 
1014  * This function manages the key events used to navigate between
1015  * header and folder views (when the window is in split view)
1016  *
1017  * FROM         KEY        ACTION
1018  * -------------------------------------------------
1019  * HeaderView   GDK_Left   Move focus to folder view
1020  * FolderView   GDK_Right  Move focus to header view
1021  *
1022  * There is no need to scroll to selected row, the widgets will be the
1023  * responsibles of doing that (probably managing the focus-in event
1024  */
1025 static gboolean 
1026 on_inner_widgets_key_pressed (GtkWidget *widget,
1027                               GdkEventKey *event,
1028                               gpointer user_data)
1029 {
1030         ModestMainWindowPrivate *priv;
1031
1032         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1033
1034         /* Do nothing if we're in SIMPLE style */
1035         if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1036                 return FALSE;
1037
1038         if (MODEST_IS_HEADER_VIEW (widget) && event->keyval == GDK_Left)
1039                 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1040         else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1041                 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1042
1043         return FALSE;
1044 }
1045
1046 static void
1047 set_alignment (GtkWidget *widget,
1048                gpointer data)
1049 {
1050         gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1051         gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1052 }
1053
1054 static GtkWidget *
1055 create_details_widget (TnyAccount *account)
1056 {
1057         GtkWidget *vbox;
1058         gchar *label;
1059
1060         vbox = gtk_vbox_new (FALSE, 0);
1061
1062         /* Account description */
1063         if (!strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1064                 gchar *device_name;
1065
1066                 /* Get device name */
1067                 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1068                                                       MODEST_CONF_DEVICE_NAME, NULL);
1069    
1070                 label = g_strdup_printf ("%s: %s",
1071                                          _("mcen_fi_localroot_description"),
1072                                          device_name);
1073                 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1074                 g_free (device_name);
1075                 g_free (label);
1076         } else if (!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1077                 /* TODO: MMC ? */
1078                 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new ("FIXME: MMC ?"), FALSE, FALSE, 0);
1079         } else {
1080                 GString *proto;
1081
1082                 /* Put proto in uppercase */
1083                 proto = g_string_new (tny_account_get_proto (account));
1084                 proto = g_string_ascii_up (proto);
1085
1086                 label = g_strdup_printf ("%s %s: %s", 
1087                                          proto->str,
1088                                          _("mcen_fi_remoteroot_account"),
1089                                          tny_account_get_name (account));
1090                 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1091                 g_string_free (proto, TRUE);
1092                 g_free (label);
1093         }
1094
1095         /* Message count */
1096         label = g_strdup_printf ("%s: %d", _("mcen_fi_rootfolder_messages"), 
1097                                  modest_tny_account_get_message_count (account));
1098         gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1099         g_free (label);
1100
1101         /* Folder count */
1102         label = g_strdup_printf ("%s: %d", _("mcen_fi_rootfolder_folders"), 
1103                                  modest_tny_account_get_folder_count (account));
1104         gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1105         g_free (label);
1106
1107         /* Size / Date */
1108         if (!strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1109                 /* FIXME: format size */
1110                 label = g_strdup_printf ("%s: %d", _("mcen_fi_rootfolder_size"), 
1111                                          modest_tny_account_get_local_size (account));
1112                 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1113                 g_free (label);
1114         } else if (!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1115                 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new ("FIXME: MMC ?"), FALSE, FALSE, 0);
1116         } else {
1117                 label = g_strdup_printf ("%s: %s", _("mcen_ti_lastupdated"), "08/08/08");
1118                 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1119                 g_free (label);
1120         }
1121
1122         /* Set alignment */
1123         gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1124
1125         return vbox;
1126 }
1127
1128 void 
1129 modest_main_window_set_contents_style (ModestMainWindow *self, 
1130                                        ModestMainWindowContentsStyle style)
1131 {
1132         ModestMainWindowPrivate *priv;
1133         GtkWidget *content;
1134         TnyAccount *account;
1135
1136         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1137
1138         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1139
1140         /* We allow to set the same content style than the previously
1141            set if there are details, because it could happen when we're
1142            selecting different accounts consecutively */
1143         if ((priv->contents_style == style) &&
1144             (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS))
1145                 return;
1146
1147         /* Remove previous child. Delete it if it was an account
1148            details widget */
1149         content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1150         if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1151                 g_object_ref (content);
1152         gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1153
1154         priv->contents_style = style;
1155
1156         switch (priv->contents_style) {
1157         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1158                 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1159                 break;
1160         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1161                 /* TODO: show here account details */
1162                 account = TNY_ACCOUNT (modest_folder_view_get_selected (priv->folder_view));
1163                 priv->details_widget = create_details_widget (account);
1164
1165                 wrap_in_scrolled_window (priv->contents_widget, 
1166                                          priv->details_widget);
1167                 break;
1168         default:
1169                 g_return_if_reached ();
1170         }
1171
1172         /* Show */
1173         gtk_widget_show_all (priv->contents_widget);
1174 }
1175
1176 static void 
1177 on_configuration_key_changed (ModestConf* conf, 
1178                               const gchar *key, 
1179                               ModestConfEvent event, 
1180                               ModestMainWindow *self)
1181 {
1182         ModestMainWindowPrivate *priv;
1183         TnyAccount *account;
1184
1185         if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
1186                 return;
1187
1188         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1189
1190         if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1191                 return;
1192
1193         account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1194         if (TNY_IS_ACCOUNT (account) &&
1195             !strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1196                 GList *children;
1197                 GtkLabel *label;
1198                 const gchar *device_name;
1199                 gchar *new_text;
1200                 
1201                 /* Get label */
1202                 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1203                 label = GTK_LABEL (children->data);
1204                 
1205                 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1206                                                       MODEST_CONF_DEVICE_NAME, NULL);
1207                 
1208                 new_text = g_strdup_printf ("%s: %s",
1209                                             _("mcen_fi_localroot_description"),
1210                                             device_name);
1211                 
1212                 gtk_label_set_text (label, new_text);
1213                 gtk_widget_show (GTK_WIDGET (label));
1214                 
1215                 g_free (new_text);
1216                 g_list_free (children);
1217         }
1218 }
1219
1220 static void 
1221 set_toolbar_mode (ModestMainWindow *self, 
1222                   ModestToolBarModes mode)
1223 {
1224         ModestWindowPrivate *parent_priv = NULL;
1225         ModestMainWindowPrivate *priv = NULL;
1226         GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1227         
1228         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1229
1230         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1231         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1232
1233         g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar)); 
1234         
1235         sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1236         refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1237         cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1238
1239         /* Sets current toolbar mode */
1240         priv->current_toolbar_mode = mode;
1241
1242         /* Show and hide toolbar items */
1243         switch (mode) {
1244         case TOOLBAR_MODE_NORMAL:
1245                 if (sort_action) 
1246                         gtk_action_set_visible (sort_action, TRUE);
1247                 if (refresh_action) 
1248                         gtk_action_set_visible (refresh_action, TRUE);
1249                 if (priv->progress_toolitem) {
1250                         gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1251                         gtk_widget_hide (priv->progress_toolitem);
1252                 }
1253                 if (priv->progress_bar)
1254                         gtk_widget_hide (priv->progress_bar);                   
1255                 
1256                 if (cancel_action)
1257                         gtk_action_set_visible (cancel_action, FALSE);
1258
1259                 /* Hide toolbar if optimized view is enabled */
1260                 if (priv->optimized_view)
1261                         gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
1262                 break;
1263         case TOOLBAR_MODE_TRANSFER:
1264                 if (sort_action)
1265                         gtk_action_set_visible (sort_action, FALSE);
1266                 if (refresh_action)
1267                         gtk_action_set_visible (refresh_action, FALSE);
1268                 if (cancel_action)
1269                         gtk_action_set_visible (cancel_action, TRUE);
1270                 if (priv->progress_toolitem) {
1271                         gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1272                         gtk_widget_show (priv->progress_toolitem);
1273                 }
1274                 if (priv->progress_bar)
1275                         gtk_widget_show (priv->progress_bar);                   
1276
1277                 /* Show toolbar if it's hiden (optimized view ) */
1278                 if (priv->optimized_view)
1279                         gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1280                 break;
1281         default:
1282                 g_return_if_reached ();
1283         }
1284 }
1285
1286 static void
1287 cancel_progressbar (GtkToolButton *toolbutton,
1288                     ModestMainWindow *self)
1289 {
1290         GSList *tmp;
1291         ModestMainWindowPrivate *priv;
1292         
1293         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1294
1295         /* Get operation observers and cancel its current operation */
1296         tmp = priv->progress_widgets;
1297         while (tmp) {
1298                 modest_progress_object_cancel_current_operation (MODEST_PROGRESS_OBJECT(tmp->data));
1299                 tmp=g_slist_next(tmp);
1300         }
1301 }
1302
1303 static gboolean
1304 observers_empty (ModestMainWindow *self)
1305 {
1306         GSList *tmp = NULL;
1307         ModestMainWindowPrivate *priv;
1308         gboolean is_empty = TRUE;
1309         guint pending_ops = 0;
1310  
1311         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1312         tmp = priv->progress_widgets;
1313
1314         /* Check all observers */
1315         while (tmp && is_empty)  {
1316                 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
1317                 is_empty = pending_ops == 0;
1318                 
1319                 tmp = g_slist_next(tmp);
1320         }
1321         
1322         return is_empty;
1323 }
1324
1325 static void
1326 on_queue_changed (ModestMailOperationQueue *queue,
1327                   ModestMailOperation *mail_op,
1328                   ModestMailOperationQueueNotification type,
1329                   ModestMainWindow *self)
1330 {
1331         ModestMainWindowPrivate *priv;
1332         ModestMailOperationId op_id;
1333         ModestToolBarModes mode;
1334         GSList *tmp;
1335         gboolean mode_changed = FALSE;
1336
1337         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1338         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1339                
1340         /* Get toolbar mode from operation id*/
1341         op_id = modest_mail_operation_get_id (mail_op);
1342         switch (op_id) {
1343         case MODEST_MAIL_OPERATION_ID_SEND:
1344         case MODEST_MAIL_OPERATION_ID_RECEIVE:
1345                 mode = TOOLBAR_MODE_TRANSFER;
1346                 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
1347                         mode_changed = TRUE;
1348                 break;
1349         default:
1350                 mode = TOOLBAR_MODE_NORMAL;
1351                 
1352         }
1353                 
1354                        
1355         /* Add operation observers and change toolbar if neccessary*/
1356         tmp = priv->progress_widgets;
1357         switch (type) {
1358         case MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED:
1359                 if (mode_changed)
1360                         set_toolbar_mode (self, mode);
1361                 if (mode == TOOLBAR_MODE_TRANSFER) {
1362                         while (tmp) {
1363                                 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
1364                                                                       mail_op);
1365                                 tmp = g_slist_next (tmp);
1366                         }
1367                 }
1368                 break;
1369         case MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED:
1370                 if (mode == TOOLBAR_MODE_TRANSFER) {
1371                         while (tmp) {
1372                                 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
1373                                                                          mail_op);
1374                                 tmp = g_slist_next (tmp);
1375                         }
1376                         
1377                         /* If no more operations are being observed, NORMAL mode is enabled again */
1378                         if (observers_empty (self))
1379                                 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
1380                 }
1381                 break;
1382         }       
1383 }
1384
1385 static void 
1386 on_show_account_action_activated  (GtkAction *action,
1387                                    gpointer user_data)
1388 {
1389         ModestAccountData *acc_data;
1390         ModestMainWindow *self;
1391         ModestMainWindowPrivate *priv;
1392         ModestAccountMgr *mgr;
1393
1394         self = MODEST_MAIN_WINDOW (user_data);
1395         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1396
1397         /* Get account data */
1398         mgr = modest_runtime_get_account_mgr ();
1399         acc_data = modest_account_mgr_get_account_data (mgr, gtk_action_get_name (action));
1400
1401         /* Set the new visible account */
1402         if (acc_data->store_account) 
1403                 modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view,
1404                                                                              acc_data->store_account->account_name);
1405
1406         /* Free */
1407         modest_account_mgr_free_account_data (mgr, acc_data);
1408 }