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