2007-05-07 Murray Cumming <murrayc@murrayc.com>
[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                 const gboolean hibernation_prevented = 
452                         modest_window_mgr_get_hibernation_is_prevented (
453         modest_runtime_get_window_mgr ()); 
454         
455                 if (hibernation_prevented)
456                         hildon_program_set_can_hibernate (app, FALSE);
457                 else {
458                         /* Allow hibernation, after saving the state: */
459                         modest_osso_save_state();
460                         hildon_program_set_can_hibernate (app, TRUE);
461                 }
462         }
463         
464 }
465
466
467
468 ModestWindow*
469 modest_main_window_new (void)
470 {
471         ModestMainWindow *self; 
472         ModestMainWindowPrivate *priv;
473         ModestWindowPrivate *parent_priv;
474         GtkWidget *folder_win;
475         GtkActionGroup *action_group;
476         GError *error = NULL;
477         TnyFolderStoreQuery *query;
478         GdkPixbuf *window_icon;
479         ModestConf *conf;
480         GtkAction *action;
481
482         self  = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
483         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
484         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
485
486         parent_priv->ui_manager = gtk_ui_manager_new();
487         action_group = gtk_action_group_new ("ModestMainWindowActions");
488         gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
489
490         /* Add common actions */
491         gtk_action_group_add_actions (action_group,
492                                       modest_action_entries,
493                                       G_N_ELEMENTS (modest_action_entries),
494                                       self);
495
496         gtk_action_group_add_actions (action_group,
497                                       modest_folder_view_action_entries,
498                                       G_N_ELEMENTS (modest_folder_view_action_entries),
499                                       self);
500
501         gtk_action_group_add_toggle_actions (action_group,
502                                              modest_toggle_action_entries,
503                                              G_N_ELEMENTS (modest_toggle_action_entries),
504                                              self);
505
506         gtk_action_group_add_toggle_actions (action_group,
507                                              modest_main_window_toggle_action_entries,
508                                              G_N_ELEMENTS (modest_main_window_toggle_action_entries),
509                                              self);
510
511         gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
512         g_object_unref (action_group);
513
514         /* Load the UI definition */
515         gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
516                                          MODEST_UIDIR "modest-main-window-ui.xml", &error);
517         if (error != NULL) {
518                 g_warning ("Could not merge modest-ui.xml: %s", error->message);
519                 g_error_free (error);
520                 error = NULL;
521         }
522
523         /* Add accelerators */
524         gtk_window_add_accel_group (GTK_WINDOW (self), 
525                                     gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
526
527         /* Menubar. Update the state of some toggles */
528         parent_priv->menubar = modest_maemo_utils_menubar_to_menu (parent_priv->ui_manager);
529         conf = modest_runtime_get_conf ();
530         action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
531                                             "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
532         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
533                                       modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR, NULL));
534         action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
535                                             "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
536         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
537                                       modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR_FULLSCREEN, NULL));
538         hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
539
540         /* folder view */
541         query = tny_folder_store_query_new ();
542         tny_folder_store_query_add_item (query, NULL,
543                                          TNY_FOLDER_STORE_QUERY_OPTION_SUBSCRIBED);
544         priv->folder_view = MODEST_FOLDER_VIEW(modest_folder_view_new (query));
545         if (!priv->folder_view)
546                 g_printerr ("modest: cannot instantiate folder view\n");
547         g_object_unref (G_OBJECT (query));
548         modest_folder_view_set_style (priv->folder_view,
549                                       MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
550
551         /* Get device name */
552         modest_maemo_utils_get_device_name ();
553
554         /* header view */
555         priv->header_view  =
556                 MODEST_HEADER_VIEW(modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
557         if (!priv->header_view)
558                 g_printerr ("modest: cannot instantiate header view\n");
559         modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
560         
561         /* Create scrolled windows */
562         folder_win = gtk_scrolled_window_new (NULL, NULL);
563         priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
564         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
565                                         GTK_POLICY_NEVER,
566                                         GTK_POLICY_AUTOMATIC);
567         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
568                                         GTK_POLICY_NEVER,
569                                         GTK_POLICY_AUTOMATIC);
570
571         wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
572         wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET(priv->header_view));
573
574         /* paned */
575         priv->main_paned = gtk_hpaned_new ();
576         gtk_paned_add1 (GTK_PANED(priv->main_paned), folder_win);
577         gtk_paned_add2 (GTK_PANED(priv->main_paned), priv->contents_widget);
578         gtk_widget_show (GTK_WIDGET(priv->header_view));
579         gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
580
581         /* putting it all together... */
582         priv->main_vbox = gtk_vbox_new (FALSE, 6);
583         gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
584
585         gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
586         restore_sizes (MODEST_MAIN_WINDOW(self));
587
588         /* Set window icon */
589         window_icon = modest_platform_get_icon (MODEST_APP_ICON);
590         gtk_window_set_icon (GTK_WINDOW (self), window_icon);
591         
592         /* Connect signals */
593         connect_signals (self);
594
595         /* Set account store */
596         tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
597                                                   TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
598
599         /* do send & receive when we are idle */
600         g_idle_add ((GSourceFunc)sync_accounts_cb, self);
601         
602
603         HildonProgram *app = hildon_program_get_instance ();
604         hildon_program_add_window (app, HILDON_WINDOW (self));
605         
606         /* Register HildonProgram  signal handlers: */
607         /* These are apparently deprecated, according to the 
608          * "HildonApp/HildonAppView to HildonProgram/HildonWindow migration guide",
609          * though the API reference does not mention that:
610          *
611         g_signal_connect (G_OBJECT(app), "topmost_status_lose",
612                 G_CALLBACK (on_hildon_program_save_state), self);
613         g_signal_connect (G_OBJECT(app), "topmost_status_acquire",
614                 G_CALLBACK (on_hildon_program_status_acquire), self);
615     */
616         g_signal_connect (G_OBJECT(app), "notify::is-topmost",
617                 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
618                 
619         /* Load previous osso state, for instance if we are being restored from 
620          * hibernation:  */
621         modest_osso_load_state();
622
623         return MODEST_WINDOW(self);
624 }
625
626 gboolean 
627 modest_main_window_close_all (ModestMainWindow *self)
628 {
629         GtkWidget *note;
630         GtkResponseType response;
631
632         /* Create the confirmation dialog MSG-NOT308 */
633         note = hildon_note_new_confirmation_add_buttons (GTK_WINDOW (self),
634                                                          _("emev_nc_close_windows"),
635                                                          _("mcen_bd_yes"), GTK_RESPONSE_YES,
636                                                          _("mcen_bd_no"), GTK_RESPONSE_NO,
637                                                          NULL);
638
639         response = gtk_dialog_run (GTK_DIALOG (note));
640         gtk_widget_destroy (GTK_WIDGET (note));
641
642         if (response == GTK_RESPONSE_YES)
643                 return TRUE;
644         else
645                 return FALSE;
646 }
647
648
649 void 
650 modest_main_window_set_style (ModestMainWindow *self, 
651                               ModestMainWindowStyle style)
652 {
653         ModestMainWindowPrivate *priv;
654         ModestWindowPrivate *parent_priv;
655         GtkAction *action;
656
657         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
658
659         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
660         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
661
662         /* no change -> nothing to do */
663         if (priv->style == style)
664                 return;
665
666         /* Get toggle button */
667         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarToggleView");
668
669         priv->style = style;
670
671         switch (style) {
672         case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
673                 /* Remove main paned */
674                 g_object_ref (priv->main_paned);
675                 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
676
677                 /* Reparent the contents widget to the main vbox */
678                 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
679
680                 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
681                 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
682                 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
683
684                 break;
685         case MODEST_MAIN_WINDOW_STYLE_SPLIT:
686                 /* Remove header view */
687                 g_object_ref (priv->contents_widget);
688                 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
689
690                 /* Reparent the main paned */
691                 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
692                 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
693
694                 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
695                 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), FALSE);
696                 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
697
698                 break;
699         default:
700                 g_return_if_reached ();
701         }
702
703         /* Let header view grab the focus if it's being shown */
704         if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
705                 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
706         else 
707                 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
708
709         /* Show changes */
710         gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
711 }
712
713 ModestMainWindowStyle
714 modest_main_window_get_style (ModestMainWindow *self)
715 {
716         ModestMainWindowPrivate *priv;
717
718         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
719
720         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
721         return priv->style;
722 }
723
724
725
726 static gboolean
727 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
728 {
729         if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
730                 ModestWindowPrivate *parent_priv;
731                 ModestWindowMgr *mgr;
732                 gboolean is_fullscreen;
733                 GtkAction *fs_toggle_action;
734                 gboolean active;
735                 
736                 mgr = modest_runtime_get_window_mgr ();
737                 
738                 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
739
740                 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
741                 
742                 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
743                 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
744                 if (is_fullscreen != active) {
745                         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
746                 }
747         }
748
749         return FALSE;
750
751 }
752
753 static void
754 set_homogeneous (GtkWidget *widget,
755                  gpointer data)
756 {
757         gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
758         gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
759 }
760
761 static void 
762 modest_main_window_show_toolbar (ModestWindow *self,
763                                  gboolean show_toolbar)
764 {
765         ModestMainWindowPrivate *priv = NULL;
766         ModestWindowPrivate *parent_priv = NULL;        
767         GtkWidget *reply_button = NULL, *menu = NULL;
768         GtkWidget *placeholder = NULL;
769         gint insert_index;
770
771         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
772         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
773         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
774
775         /* Set optimized view status */
776         priv->optimized_view = !show_toolbar;
777
778         if (!parent_priv->toolbar) {
779                 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, 
780                                                                   "/ToolBar");
781
782                 /* Set homogeneous toolbar */
783                 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar), 
784                                        set_homogeneous, NULL);
785         
786                 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
787                 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
788                 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
789                 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
790                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
791                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
792                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
793                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
794
795                 /* Add ProgressBar (Transfer toolbar) */ 
796                 priv->progress_bar = modest_progress_bar_widget_new ();
797                 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
798                 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
799                 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
800                 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
801                 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
802                 
803                 /* Connect cancel 'clicked' signal to abort progress mode */
804                 g_signal_connect(priv->cancel_toolitem, "clicked",
805                                  G_CALLBACK(cancel_progressbar),
806                                  self);
807                 
808                 /* Add it to the observers list */
809                 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
810
811                 /* Add to window */
812                 hildon_window_add_toolbar (HILDON_WINDOW (self), 
813                                            GTK_TOOLBAR (parent_priv->toolbar));
814
815                 /* Set reply button tap and hold menu */
816                 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager, 
817                                                           "/ToolBar/ToolbarMessageReply");
818                 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
819                                                   "/ToolbarReplyCSM");
820                 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
821
822                 /* Set send & receive button tap and hold menu */
823                 on_account_update (TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()),
824                                    NULL, self);
825         }
826
827         if (show_toolbar) {
828                 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
829                 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
830                 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
831                 
832                 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
833                 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
834         } else
835                 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
836
837 }
838
839 /*
840  * TODO: modify the menu dynamically. Add handlers to each item of the
841  * menu when created
842  */
843 static void 
844 on_account_update (TnyAccountStore *account_store, 
845                    gchar *accout_name,
846                    gpointer user_data)
847 {
848         ModestMainWindow *self;
849         ModestMainWindowPrivate *priv;
850         ModestWindowPrivate *parent_priv;
851         TnyList *account_list;
852         GtkWidget *item, *send_receive_button;
853         TnyIterator *iter;
854         ModestAccountMgr *mgr;
855         gchar *default_account;
856
857         self = MODEST_MAIN_WINDOW (user_data);
858         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
859         parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
860
861         /* If there is no toolbar then exit */
862         if (!parent_priv->toolbar)
863                 return;
864
865         if (priv->accounts_popup && gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)) ) {
866                 /* gtk_menu_detach will also unreference the popup, 
867                  * so we can forget about this instance, and create a new one later:
868                  */
869                 gtk_menu_detach (GTK_MENU (priv->accounts_popup));
870                 priv->accounts_popup = NULL;
871         }
872
873         /* Get accounts */
874         account_list = tny_simple_list_new ();
875         tny_account_store_get_accounts (account_store, 
876                                         account_list, 
877                                         TNY_ACCOUNT_STORE_STORE_ACCOUNTS);
878
879         /* If there is only one account do not show any menu */
880         if (tny_list_get_length (account_list) <= 1)
881                 goto free;
882         
883         /* Get send receive button */
884         send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager, 
885                                                           "/ToolBar/ToolbarSendReceive");
886
887         /* Create the menu */
888         priv->accounts_popup = gtk_menu_new ();
889         item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
890         gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
891         item = gtk_separator_menu_item_new ();
892         gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
893
894         iter = tny_list_create_iterator (account_list);
895         mgr = modest_runtime_get_account_mgr ();
896         default_account = modest_account_mgr_get_default_account (mgr);
897
898         do {
899                 TnyAccount *acc = NULL;
900                 const gchar *acc_name = NULL;
901
902                 /* Create tool item */
903                 acc = TNY_ACCOUNT (tny_iterator_get_current (iter));
904                 if (acc)
905                         acc_name = tny_account_get_name (acc);
906
907                 /* Create display name */
908                 gchar *display_name = NULL;
909                 if (acc_name) {
910                         if (default_account && !(strcmp (default_account, acc_name) == 0))
911                                 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"), acc_name);
912                         else
913                                 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"), acc_name);
914                 }
915                 else
916                 {
917                         /* TODO: This probably should never happen: */
918                         display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"), "");
919                 }
920                 
921
922                 item = gtk_menu_item_new_with_label (display_name);
923
924                 /* Free */
925                 g_free (display_name);
926                 g_object_unref (acc);
927
928                 /* Append item */
929                 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
930
931                 /* Go to next */
932                 tny_iterator_next (iter);
933
934         } while (!tny_iterator_is_done (iter));
935
936         g_object_unref (iter);
937
938         /* Mandatory in order to view the menu contents */
939         gtk_widget_show_all (priv->accounts_popup);
940
941         /* Setup tap_and_hold */
942         gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
943
944  free:
945
946         /* Free */
947         g_object_unref (account_list);
948 }
949
950 /* 
951  * This function manages the key events used to navigate between
952  * header and folder views (when the window is in split view)
953  *
954  * FROM         KEY        ACTION
955  * -------------------------------------------------
956  * HeaderView   GDK_Left   Move focus to folder view
957  * FolderView   GDK_Right  Move focus to header view
958  *
959  * There is no need to scroll to selected row, the widgets will be the
960  * responsibles of doing that (probably managing the focus-in event
961  */
962 static gboolean 
963 on_inner_widgets_key_pressed (GtkWidget *widget,
964                               GdkEventKey *event,
965                               gpointer user_data)
966 {
967         ModestMainWindowPrivate *priv;
968
969         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
970
971         /* Do nothing if we're in SIMPLE style */
972         if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
973                 return FALSE;
974
975         if (MODEST_IS_HEADER_VIEW (widget) && event->keyval == GDK_Left)
976                 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
977         else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
978                 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
979
980         return FALSE;
981 }
982
983 static void
984 set_alignment (GtkWidget *widget,
985                gpointer data)
986 {
987         gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
988         gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
989 }
990
991 static GtkWidget *
992 create_details_widget (TnyAccount *account)
993 {
994         GtkWidget *vbox;
995         gchar *label;
996
997         vbox = gtk_vbox_new (FALSE, 0);
998
999         /* Account description */
1000         if (!strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1001                 gchar *device_name;
1002
1003                 /* Get device name */
1004                 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1005                                                       MODEST_CONF_DEVICE_NAME, NULL);
1006    
1007                 label = g_strdup_printf ("%s: %s",
1008                                          _("mcen_fi_localroot_description"),
1009                                          device_name);
1010                 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1011                 g_free (device_name);
1012                 g_free (label);
1013         } else if (!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1014                 /* TODO: MMC ? */
1015                 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new ("FIXME: MMC ?"), FALSE, FALSE, 0);
1016         } else {
1017                 GString *proto;
1018
1019                 /* Put proto in uppercase */
1020                 proto = g_string_new (tny_account_get_proto (account));
1021                 proto = g_string_ascii_up (proto);
1022
1023                 label = g_strdup_printf ("%s %s: %s", 
1024                                          proto->str,
1025                                          _("mcen_fi_remoteroot_account"),
1026                                          tny_account_get_name (account));
1027                 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1028                 g_string_free (proto, TRUE);
1029                 g_free (label);
1030         }
1031
1032         /* Message count */
1033         label = g_strdup_printf ("%s: %d", _("mcen_fi_rootfolder_messages"), 
1034                                  modest_tny_account_get_message_count (account));
1035         gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1036         g_free (label);
1037
1038         /* Folder count */
1039         label = g_strdup_printf ("%s: %d", _("mcen_fi_rootfolder_folders"), 
1040                                  modest_tny_account_get_folder_count (account));
1041         gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1042         g_free (label);
1043
1044         /* Size / Date */
1045         if (!strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1046                 /* FIXME: format size */
1047                 label = g_strdup_printf ("%s: %d", _("mcen_fi_rootfolder_size"), 
1048                                          modest_tny_account_get_local_size (account));
1049                 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1050                 g_free (label);
1051         } else if (!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1052                 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new ("FIXME: MMC ?"), FALSE, FALSE, 0);
1053         } else {
1054                 label = g_strdup_printf ("%s: %s", _("mcen_ti_lastupdated"), "08/08/08");
1055                 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1056                 g_free (label);
1057         }
1058
1059         /* Set alignment */
1060         gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1061
1062         return vbox;
1063 }
1064
1065 void 
1066 modest_main_window_set_contents_style (ModestMainWindow *self, 
1067                                        ModestMainWindowContentsStyle style)
1068 {
1069         ModestMainWindowPrivate *priv;
1070         GtkWidget *content;
1071         TnyAccount *account;
1072
1073         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1074
1075         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1076
1077         /* We allow to set the same content style than the previously
1078            set if there are details, because it could happen when we're
1079            selecting different accounts consecutively */
1080         if ((priv->contents_style == style) &&
1081             (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS))
1082                 return;
1083
1084         /* Remove previous child. Delete it if it was an account
1085            details widget */
1086         content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1087         if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1088                 g_object_ref (content);
1089         gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1090
1091         priv->contents_style = style;
1092
1093         switch (priv->contents_style) {
1094         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1095                 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1096                 break;
1097         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1098                 /* TODO: show here account details */
1099                 account = TNY_ACCOUNT (modest_folder_view_get_selected (priv->folder_view));
1100                 priv->details_widget = create_details_widget (account);
1101
1102                 wrap_in_scrolled_window (priv->contents_widget, 
1103                                          priv->details_widget);
1104                 break;
1105         default:
1106                 g_return_if_reached ();
1107         }
1108
1109         /* Show */
1110         gtk_widget_show_all (priv->contents_widget);
1111 }
1112
1113 static void 
1114 on_configuration_key_changed (ModestConf* conf, 
1115                               const gchar *key, 
1116                               ModestConfEvent event, 
1117                               ModestMainWindow *self)
1118 {
1119         ModestMainWindowPrivate *priv;
1120         TnyAccount *account;
1121
1122         if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
1123                 return;
1124
1125         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1126
1127         if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1128                 return;
1129
1130         account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1131         if (TNY_IS_ACCOUNT (account) &&
1132             !strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1133                 GList *children;
1134                 GtkLabel *label;
1135                 const gchar *device_name;
1136                 gchar *new_text;
1137                 
1138                 /* Get label */
1139                 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1140                 label = GTK_LABEL (children->data);
1141                 
1142                 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1143                                                       MODEST_CONF_DEVICE_NAME, NULL);
1144                 
1145                 new_text = g_strdup_printf ("%s: %s",
1146                                             _("mcen_fi_localroot_description"),
1147                                             device_name);
1148                 
1149                 gtk_label_set_text (label, new_text);
1150                 gtk_widget_show (GTK_WIDGET (label));
1151                 
1152                 g_free (new_text);
1153                 g_list_free (children);
1154         }
1155 }
1156
1157 static void 
1158 set_toolbar_mode (ModestMainWindow *self, 
1159                   ModestToolBarModes mode)
1160 {
1161         ModestWindowPrivate *parent_priv = NULL;
1162         ModestMainWindowPrivate *priv = NULL;
1163         GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1164         
1165         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1166
1167         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1168         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1169
1170         g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar)); 
1171         
1172         sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1173         refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1174         cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1175
1176         /* Sets current toolbar mode */
1177         priv->current_toolbar_mode = mode;
1178
1179         /* Show and hide toolbar items */
1180         switch (mode) {
1181         case TOOLBAR_MODE_NORMAL:
1182                 if (sort_action) 
1183                         gtk_action_set_visible (sort_action, TRUE);
1184                 if (refresh_action) 
1185                         gtk_action_set_visible (refresh_action, TRUE);
1186                 if (priv->progress_toolitem) {
1187                         gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1188                         gtk_widget_hide (priv->progress_toolitem);
1189                 }
1190                 if (priv->progress_bar)
1191                         gtk_widget_hide (priv->progress_bar);                   
1192                 
1193                 if (cancel_action)
1194                         gtk_action_set_visible (cancel_action, FALSE);
1195
1196                 /* Hide toolbar if optimized view is enabled */
1197                 if (priv->optimized_view)
1198                         gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
1199                 break;
1200         case TOOLBAR_MODE_TRANSFER:
1201                 if (sort_action)
1202                         gtk_action_set_visible (sort_action, FALSE);
1203                 if (refresh_action)
1204                         gtk_action_set_visible (refresh_action, FALSE);
1205                 if (cancel_action)
1206                         gtk_action_set_visible (cancel_action, TRUE);
1207                 if (priv->progress_toolitem) {
1208                         gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1209                         gtk_widget_show (priv->progress_toolitem);
1210                 }
1211                 if (priv->progress_bar)
1212                         gtk_widget_show (priv->progress_bar);                   
1213
1214                 /* Show toolbar if it's hiden (optimized view ) */
1215                 if (priv->optimized_view)
1216                         gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1217                 break;
1218         default:
1219                 g_return_if_reached ();
1220         }
1221 }
1222
1223 static void
1224 cancel_progressbar (GtkToolButton *toolbutton,
1225                     ModestMainWindow *self)
1226 {
1227         GSList *tmp;
1228         ModestMainWindowPrivate *priv;
1229         
1230         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1231
1232         /* Get operation observers and cancel its current operation */
1233         tmp = priv->progress_widgets;
1234         while (tmp) {
1235                 modest_progress_object_cancel_current_operation (MODEST_PROGRESS_OBJECT(tmp->data));
1236                 tmp=g_slist_next(tmp);
1237         }
1238 }
1239
1240 static gboolean
1241 observers_empty (ModestMainWindow *self)
1242 {
1243         GSList *tmp = NULL;
1244         ModestMainWindowPrivate *priv;
1245         gboolean is_empty = TRUE;
1246         guint pending_ops = 0;
1247  
1248         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1249         tmp = priv->progress_widgets;
1250
1251         /* Check all observers */
1252         while (tmp && is_empty)  {
1253                 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
1254                 is_empty = pending_ops == 0;
1255                 
1256                 tmp = g_slist_next(tmp);
1257         }
1258         
1259         return is_empty;
1260 }
1261
1262 static void
1263 on_queue_changed (ModestMailOperationQueue *queue,
1264                   ModestMailOperation *mail_op,
1265                   ModestMailOperationQueueNotification type,
1266                   ModestMainWindow *self)
1267 {
1268         ModestMainWindowPrivate *priv;
1269         ModestMailOperationId op_id;
1270         ModestToolBarModes mode;
1271         GSList *tmp;
1272         gboolean mode_changed = FALSE;
1273
1274         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1275         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1276                
1277         /* Get toolbar mode from operation id*/
1278         op_id = modest_mail_operation_get_id (mail_op);
1279         switch (op_id) {
1280         case MODEST_MAIL_OPERATION_ID_SEND:
1281         case MODEST_MAIL_OPERATION_ID_RECEIVE:
1282                 mode = TOOLBAR_MODE_TRANSFER;
1283                 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
1284                         mode_changed = TRUE;
1285                 break;
1286         default:
1287                 mode = TOOLBAR_MODE_NORMAL;
1288                 
1289         }
1290                 
1291                        
1292         /* Add operation observers and change toolbar if neccessary*/
1293         tmp = priv->progress_widgets;
1294         switch (type) {
1295         case MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED:
1296                 if (mode_changed)
1297                         set_toolbar_mode (self, mode);
1298                 if (mode == TOOLBAR_MODE_TRANSFER) {
1299                         while (tmp) {
1300                                 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
1301                                                                       mail_op);
1302                                 tmp = g_slist_next (tmp);
1303                         }
1304                 }
1305                 break;
1306         case MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED:
1307                 if (mode == TOOLBAR_MODE_TRANSFER) {
1308                         while (tmp) {
1309                                 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
1310                                                                          mail_op);
1311                                 tmp = g_slist_next (tmp);
1312                         }
1313                         
1314                         /* If no more operations are being observed, NORMAL mode is enabled again */
1315                         if (observers_empty (self))
1316                                 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
1317                 }
1318                 break;
1319         }       
1320 }