c9af125198312d60ebaa0fd2b1d75bcb336665b2
[modest] / src / maemo / modest-main-window.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include <glib/gi18n.h>
31 #include <gtk/gtktreeviewcolumn.h>
32 #include <tny-account-store-view.h>
33 #include <tny-simple-list.h>
34 #include <tny-maemo-conic-device.h>
35 #include "modest-hildon-includes.h"
36 #include "modest-defs.h"
37 #include <string.h>
38
39 #include "widgets/modest-main-window.h"
40 #include "widgets/modest-msg-edit-window.h"
41 #include "widgets/modest-account-view-window.h"
42 #include "modest-runtime.h"
43 #include "modest-account-mgr-helpers.h"
44 #include "modest-platform.h"
45 #include "modest-widget-memory.h"
46 #include "modest-window-priv.h"
47 #include "modest-main-window-ui.h"
48 #include "modest-main-window-ui-dimming.h"
49 #include "modest-account-mgr.h"
50 #include "modest-tny-account.h"
51 #include "modest-conf.h"
52 #include <modest-maemo-utils.h>
53 #include "modest-tny-platform-factory.h"
54 #include "modest-tny-msg.h"
55 #include "modest-mail-operation.h"
56 #include "modest-icon-names.h"
57 #include "modest-progress-bar-widget.h"
58 #include "modest-text-utils.h"
59 #include "modest-ui-dimming-manager.h"
60 #include "maemo/modest-osso-state-saving.h"
61
62 #ifdef MODEST_HILDON_VERSION_0
63 #include <hildon-widgets/hildon-program.h>
64 #else
65 #include <hildon/hildon-program.h>
66 #endif /*MODEST_HILDON_VERSION_0*/
67
68 #define MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS "ModestMainWindowActionAdditions"
69
70 /* 'private'/'protected' functions */
71 static void modest_main_window_class_init    (ModestMainWindowClass *klass);
72 static void modest_main_window_init          (ModestMainWindow *obj);
73 static void modest_main_window_finalize      (GObject *obj);
74 static gboolean modest_main_window_window_state_event (GtkWidget *widget, 
75                                                            GdkEventWindowState *event, 
76                                                            gpointer userdata);
77
78 static void connect_signals (ModestMainWindow *self);
79
80 static void restore_settings (ModestMainWindow *self);
81 static void save_state (ModestWindow *self);
82
83 static void modest_main_window_show_toolbar   (ModestWindow *window,
84                                                gboolean show_toolbar);
85
86 static void cancel_progressbar (GtkToolButton *toolbutton,
87                                 ModestMainWindow *self);
88
89 static void         on_queue_changed                     (ModestMailOperationQueue *queue,
90                                                           ModestMailOperation *mail_op,
91                                                           ModestMailOperationQueueNotification type,
92                                                           ModestMainWindow *self);
93
94 static void on_account_update                 (TnyAccountStore *account_store, 
95                                                const gchar *account_name,
96                                                gpointer user_data);
97
98 static gboolean on_inner_widgets_key_pressed  (GtkWidget *widget,
99                                                GdkEventKey *event,
100                                                gpointer user_data);
101
102 static void on_configuration_key_changed      (ModestConf* conf, 
103                                                const gchar *key, 
104                                                ModestConfEvent event, 
105                                                ModestMainWindow *self);
106
107 static void set_toolbar_mode                  (ModestMainWindow *self, 
108                                                ModestToolBarModes mode);
109
110 static gboolean set_toolbar_transfer_mode     (ModestMainWindow *self); 
111
112 static void on_show_account_action_activated      (GtkAction *action,
113                                                    gpointer user_data);
114
115 static void on_refresh_account_action_activated   (GtkAction *action,
116                                                    gpointer user_data);
117
118 static void on_send_receive_csm_activated         (GtkMenuItem *item,
119                                                    gpointer user_data);
120 /* list my signals */
121 enum {
122         /* MY_SIGNAL_1, */
123         /* MY_SIGNAL_2, */
124         LAST_SIGNAL
125 };
126
127
128 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
129 struct _ModestMainWindowPrivate {
130         GtkWidget *msg_paned;
131         GtkWidget *main_paned;
132         GtkWidget *main_vbox;
133         GtkWidget *contents_widget;
134
135         /* Progress observers */
136         GtkWidget        *progress_bar;
137         GSList           *progress_widgets;
138
139         /* Tollbar items */
140         GtkWidget   *progress_toolitem;
141         GtkWidget   *cancel_toolitem;
142         GtkWidget   *sort_toolitem;
143         GtkWidget   *refresh_toolitem;
144         ModestToolBarModes current_toolbar_mode;
145
146         /* Merge ids used to add/remove accounts to the ViewMenu*/
147         GByteArray *merge_ids;
148
149         /* On-demand widgets */
150         GtkWidget *accounts_popup;
151         GtkWidget *details_widget;
152
153         /* Optimized view enabled */
154         gboolean optimized_view;
155
156         ModestHeaderView *header_view;
157         ModestFolderView *folder_view;
158
159         ModestMainWindowStyle style;
160         ModestMainWindowContentsStyle contents_style;
161
162         guint progress_bar_timeout;
163
164 };
165 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
166                                                 MODEST_TYPE_MAIN_WINDOW, \
167                                                 ModestMainWindowPrivate))
168
169 typedef struct _GetMsgAsyncHelper {
170         ModestMainWindowPrivate *main_window_private;
171         guint action;
172         ModestTnyMsgReplyType reply_type;
173         ModestTnyMsgForwardType forward_type;
174         gchar *from;
175         TnyIterator *iter;
176 } GetMsgAsyncHelper;
177
178
179 /* globals */
180 static GtkWindowClass *parent_class = NULL;
181
182
183 /* Private actions */
184 /* This is the context sensitive menu: */
185 static const GtkActionEntry modest_folder_view_action_entries [] = {
186
187         /* Folder View CSM actions */
188         { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
189         { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
190         { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL, NULL },
191         { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
192         { "FolderViewCSMSearchMessages", NULL, N_("mcen_me_inbox_search"), NULL, NULL, NULL },
193         { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
194 };
195
196 static const GtkActionEntry modest_header_view_action_entries [] = {
197
198         /* Header View CSM actions */
199         { "HeaderViewCSMOpen",          NULL,  N_("mcen_me_inbox_open"),        NULL,       NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
200         { "HeaderViewCSMReply",         NULL,  N_("mcen_me_inbox_reply"),       NULL,      NULL, G_CALLBACK (modest_ui_actions_on_reply) },
201         { "HeaderViewCSMReplyAll",      NULL,  N_("mcen_me_inbox_replytoall"),  NULL,      NULL, G_CALLBACK (modest_ui_actions_on_reply_all) },
202         { "HeaderViewCSMForward",       NULL,  N_("mcen_me_inbox_forward"),     NULL,      NULL, G_CALLBACK (modest_ui_actions_on_forward) },
203         { "HeaderViewCSMCut",           NULL,  N_("mcen_me_inbox_cut"),         "<CTRL>X", NULL, G_CALLBACK (modest_ui_actions_on_cut) },
204         { "HeaderViewCSMCopy",          NULL,  N_("mcen_me_inbox_copy"),        "<CTRL>C", NULL, G_CALLBACK (modest_ui_actions_on_copy) },
205         { "HeaderViewCSMPaste",         NULL,  N_("mcen_me_inbox_paste"),       "<CTRL>V", NULL, G_CALLBACK (modest_ui_actions_on_paste) },
206         { "HeaderViewCSMDelete",        NULL,  N_("mcen_me_inbox_delete"),      NULL,      NULL, G_CALLBACK (modest_ui_actions_on_delete) },
207         { "HeaderViewCSMCancelSending", NULL,  N_("mcen_me_outbox_cancelsend"), NULL,      NULL, NULL },
208         { "HeaderViewCSMHelp",          NULL,  N_("mcen_me_inbox_help"),        NULL,      NULL, G_CALLBACK (modest_ui_actions_on_help) },
209 };
210
211 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
212         { "ToolbarToggleView", MODEST_STOCK_SPLIT_VIEW, N_("gqn_toolb_rss_fldonoff"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), FALSE },
213 };
214
215 /************************************************************************/
216
217 GType
218 modest_main_window_get_type (void)
219 {
220         static GType my_type = 0;
221         if (!my_type) {
222                 static const GTypeInfo my_info = {
223                         sizeof(ModestMainWindowClass),
224                         NULL,           /* base init */
225                         NULL,           /* base finalize */
226                         (GClassInitFunc) modest_main_window_class_init,
227                         NULL,           /* class finalize */
228                         NULL,           /* class data */
229                         sizeof(ModestMainWindow),
230                         1,              /* n_preallocs */
231                         (GInstanceInitFunc) modest_main_window_init,
232                         NULL
233                 };
234                 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
235                                                   "ModestMainWindow",
236                                                   &my_info, 0);
237         }
238         return my_type;
239 }
240
241 static void
242 modest_main_window_class_init (ModestMainWindowClass *klass)
243 {
244         GObjectClass *gobject_class;
245         gobject_class = (GObjectClass*) klass;
246         ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
247
248         parent_class            = g_type_class_peek_parent (klass);
249         gobject_class->finalize = modest_main_window_finalize;
250
251         g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
252         
253         modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
254         modest_window_class->save_state_func = save_state;
255 }
256
257 static void
258 modest_main_window_init (ModestMainWindow *obj)
259 {
260         ModestMainWindowPrivate *priv;
261
262         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
263
264         priv->msg_paned    = NULL;
265         priv->main_paned   = NULL;      
266         priv->main_vbox    = NULL;
267         priv->header_view  = NULL;
268         priv->folder_view  = NULL;
269         priv->contents_widget  = NULL;
270         priv->accounts_popup  = NULL;
271         priv->details_widget  = NULL;
272
273         priv->progress_widgets  = NULL;
274         priv->progress_bar = NULL;
275         priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
276
277         priv->style  = MODEST_MAIN_WINDOW_STYLE_SPLIT;
278         priv->contents_style  = MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS;
279
280         priv->merge_ids = NULL;
281
282         priv->optimized_view  = FALSE;
283         priv->progress_bar_timeout = 0;
284 }
285
286 static void
287 modest_main_window_finalize (GObject *obj)
288 {
289         ModestMainWindowPrivate *priv;
290
291         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
292
293         g_slist_free (priv->progress_widgets);
294
295         g_byte_array_free (priv->merge_ids, TRUE);
296
297         if (priv->progress_bar_timeout > 0) {
298                 g_source_remove (priv->progress_bar_timeout);
299                 priv->progress_bar_timeout = 0;
300         }
301
302         G_OBJECT_CLASS(parent_class)->finalize (obj);
303 }
304
305 GtkWidget*
306 modest_main_window_get_child_widget (ModestMainWindow *self,
307                                      ModestWidgetType widget_type)
308 {
309         ModestMainWindowPrivate *priv;
310         GtkWidget *widget;
311         
312         g_return_val_if_fail (self, NULL);
313         g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_WIDGET_TYPE_NUM,
314                               NULL);
315         
316         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
317
318         switch (widget_type) {
319         case MODEST_WIDGET_TYPE_HEADER_VIEW:
320                 widget = (GtkWidget*)priv->header_view; break;
321         case MODEST_WIDGET_TYPE_FOLDER_VIEW:
322                 widget = (GtkWidget*)priv->folder_view; break;
323         default:
324                 return NULL;
325         }
326
327         return widget ? GTK_WIDGET(widget) : NULL;
328 }
329
330
331
332 static void
333 restore_settings (ModestMainWindow *self)
334 {
335         ModestConf *conf;
336         ModestMainWindowPrivate *priv;
337
338         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
339
340         conf = modest_runtime_get_conf ();
341
342         modest_widget_memory_restore (conf, G_OBJECT(self),
343                                       MODEST_CONF_MAIN_WINDOW_KEY);
344         modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
345                                       MODEST_CONF_HEADER_VIEW_KEY);
346         modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
347                                       MODEST_CONF_FOLDER_VIEW_KEY);
348         modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
349                                       MODEST_CONF_MAIN_PANED_KEY);
350
351         /* We need to force a redraw here in order to get the right
352            position of the horizontal paned separator */
353         gtk_widget_show (GTK_WIDGET (self));
354 }
355
356
357 static void
358 save_state (ModestWindow *window)
359 {
360         ModestConf *conf;
361         ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
362         ModestMainWindowPrivate *priv;
363                 
364         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
365         conf = modest_runtime_get_conf ();
366         
367         modest_widget_memory_save (conf,G_OBJECT(self), 
368                                    MODEST_CONF_MAIN_WINDOW_KEY);
369         modest_widget_memory_save (conf, G_OBJECT(priv->main_paned), 
370                                    MODEST_CONF_MAIN_PANED_KEY);
371         modest_widget_memory_save (conf, G_OBJECT(priv->header_view), 
372                                    MODEST_CONF_HEADER_VIEW_KEY);
373         modest_widget_memory_save (conf, G_OBJECT(priv->folder_view), 
374                                    MODEST_CONF_FOLDER_VIEW_KEY);
375 }
376
377 static void
378 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
379 {
380         if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
381                 gtk_scrolled_window_add_with_viewport
382                         (GTK_SCROLLED_WINDOW(win), widget);
383         else
384                 gtk_container_add (GTK_CONTAINER(win),
385                                    widget);
386 }
387
388
389 static gboolean
390 on_delete_event (GtkWidget *widget, GdkEvent  *event, ModestMainWindow *self)
391 {
392         modest_window_save_state (MODEST_WINDOW(self));
393         return FALSE;
394 }
395
396
397 static void
398 on_account_store_connecting_finished (TnyAccountStore *store, ModestMainWindow *self)
399 {
400         /* When going online, do the equivalent of pressing the send/receive button, 
401          * as per the specification:
402          * (without the check for >0 accounts, though that is not specified): */
403
404         TnyDevice *device = tny_account_store_get_device (store);
405         
406         /* Check that we are really online.
407          * This signal should not be emitted when we are not connected, 
408          * but it seems to happen sometimes: */
409          if (!tny_device_is_online (device))
410                 return;
411                 
412         const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device));
413         printf ("DEBUG: %s: connection id=%s\n", __FUNCTION__, iap_id);
414         
415         /* Stop the existing send queues: */
416         modest_runtime_remove_all_send_queues ();
417         
418         /* Create the send queues again, using the appropriate transport accounts 
419          * for this new connection.
420          * This could be the first time that they are created if this is the first 
421          * connection. */
422         /* TODO: Does this really destroy the TnySendQueues and their threads
423          * We do not want 2 TnySendQueues to exist with the same underlying 
424          * outbox directory. */
425         GSList *account_names = modest_account_mgr_account_names (
426                 modest_runtime_get_account_mgr(), 
427                 TRUE /* enabled accounts only */);
428         GSList *iter = account_names;
429         while (iter) {
430                 const gchar *account_name = (const gchar*)(iter->data);
431                         if (account_name) {
432                         TnyTransportAccount *account = TNY_TRANSPORT_ACCOUNT (
433                                 modest_tny_account_store_get_transport_account_for_open_connection
434                                                  (modest_runtime_get_account_store(), account_name));
435                         if (account) {
436                                 printf ("debug: %s:\n  Transport account for %s: %s\n", __FUNCTION__, account_name, 
437                                         tny_account_get_id(TNY_ACCOUNT(account)));
438                                 modest_runtime_get_send_queue (account);
439                         }
440                 }
441                 
442                 iter = g_slist_next (iter);
443         }
444         
445         g_slist_free (account_names);
446         
447         
448         modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (self));
449 }
450
451 static void
452 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
453 {
454         g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
455
456         /* Update dimmed */     
457         modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");  
458 }
459
460 static void
461 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
462 {
463         g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
464
465         /* Update visibility */
466
467         /* Update dimmed */     
468         modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");  
469 }
470
471 static void
472 connect_signals (ModestMainWindow *self)
473 {       
474         ModestWindowPrivate *parent_priv;
475         ModestMainWindowPrivate *priv;
476         GtkWidget *menu;
477         
478         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
479         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
480         
481         /* folder view */
482         g_signal_connect (G_OBJECT(priv->folder_view), "key-press-event",
483                           G_CALLBACK(on_inner_widgets_key_pressed), self);
484         g_signal_connect (G_OBJECT(priv->folder_view), "folder_selection_changed",
485                           G_CALLBACK(modest_ui_actions_on_folder_selection_changed), self);
486         g_signal_connect (G_OBJECT(priv->folder_view), "folder-display-name-changed",
487                           G_CALLBACK(modest_ui_actions_on_folder_display_name_changed), self);
488
489         /* Folder view CSM */
490         menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
491         gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
492         g_signal_connect (G_OBJECT(priv->folder_view), "tap-and-hold",
493                           G_CALLBACK(_folder_view_csm_menu_activated),
494                           self);
495         /* header view */
496 /*      g_signal_connect (G_OBJECT(priv->header_view), "status_update", */
497 /*                        G_CALLBACK(modest_ui_actions_on_header_status_update), self); */
498         g_signal_connect (G_OBJECT(priv->header_view), "header_selected",
499                           G_CALLBACK(modest_ui_actions_on_header_selected), self);
500         g_signal_connect (G_OBJECT(priv->header_view), "header_activated",
501                           G_CALLBACK(modest_ui_actions_on_header_activated), self);
502         g_signal_connect (G_OBJECT(priv->header_view), "item_not_found",
503                           G_CALLBACK(modest_ui_actions_on_item_not_found), self);
504         g_signal_connect (G_OBJECT(priv->header_view), "key-press-event",
505                           G_CALLBACK(on_inner_widgets_key_pressed), self);
506
507         /* Header view CSM */
508         menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
509         gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
510         g_signal_connect (G_OBJECT(priv->header_view), "tap-and-hold",
511                           G_CALLBACK(_header_view_csm_menu_activated),
512                           self);
513         
514         /* window */
515         g_signal_connect (G_OBJECT(self), "delete-event", G_CALLBACK(on_delete_event), self);
516         g_signal_connect (G_OBJECT (self), "window-state-event",
517                           G_CALLBACK (modest_main_window_window_state_event),
518                           NULL);
519         g_signal_connect (G_OBJECT(self), "delete-event", G_CALLBACK(on_delete_event), self);
520
521         /* Mail Operation Queue */
522         g_signal_connect (G_OBJECT (modest_runtime_get_mail_operation_queue ()),
523                           "queue-changed",
524                           G_CALLBACK (on_queue_changed),
525                           self);
526
527         /* Track changes in the device name */
528         g_signal_connect (G_OBJECT(modest_runtime_get_conf ()),
529                           "key_changed",
530                           G_CALLBACK (on_configuration_key_changed), 
531                           self);
532
533         /* Track account changes. We need to refresh the toolbar */
534         g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
535                           "account_update",
536                           G_CALLBACK (on_account_update),
537                           self);
538
539         /* Account store */
540         g_signal_connect (G_OBJECT (modest_runtime_get_account_store()), "password_requested",
541                           G_CALLBACK (modest_ui_actions_on_password_requested), self);
542                           
543         /* Device */
544         g_signal_connect (G_OBJECT(modest_runtime_get_account_store()), "connecting-finished",
545                           G_CALLBACK(on_account_store_connecting_finished), self);
546 }
547
548 #if 0
549 /** Idle handler, to send/receive at startup .*/
550 gboolean
551 sync_accounts_cb (ModestMainWindow *win)
552 {
553         modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (win));
554         return FALSE; /* Do not call this idle handler again. */
555 }
556 #endif
557
558 static void on_hildon_program_is_topmost_notify(GObject *self,
559         GParamSpec *propert_param, gpointer user_data)
560 {
561         HildonProgram *app = HILDON_PROGRAM (self);
562         
563         /*
564         ModestWindow* self = MODEST_WINDOW(user_data);
565         */
566         
567         /* Note that use of hildon_program_set_can_hibernate() 
568          * is generally referred to as "setting the killable flag", 
569          * though hibernation does not seem equal to death.
570          * murrayc */
571                  
572         if (hildon_program_get_is_topmost (app)) {
573                 /* Prevent hibernation when the progam comes to the foreground,
574                  * because hibernation should only happen when the application 
575                  * is in the background: */
576                 hildon_program_set_can_hibernate (app, FALSE);
577         } else {
578                 /* Allow hibernation if the program has gone to the background: */
579                 
580                 /* However, prevent hibernation while the settings are being changed: */
581                 const gboolean hibernation_prevented = 
582                         modest_window_mgr_get_hibernation_is_prevented (
583         modest_runtime_get_window_mgr ()); 
584         
585                 if (hibernation_prevented)
586                         hildon_program_set_can_hibernate (app, FALSE);
587                 else {
588                         /* Allow hibernation, after saving the state: */
589                         modest_osso_save_state();
590                         hildon_program_set_can_hibernate (app, TRUE);
591                 }
592         }
593         
594 }
595
596
597
598 ModestWindow*
599 modest_main_window_new (void)
600 {
601         ModestMainWindow *self = NULL;  
602         ModestMainWindowPrivate *priv = NULL;
603         ModestWindowPrivate *parent_priv = NULL;
604         GtkWidget *folder_win = NULL;
605         ModestDimmingRulesGroup *menu_rules_group = NULL;
606         ModestDimmingRulesGroup *toolbar_rules_group = NULL;
607         GtkActionGroup *action_group = NULL;
608         GError *error = NULL;
609         TnyFolderStoreQuery *query = NULL;
610         GdkPixbuf *window_icon = NULL; 
611         ModestConf *conf = NULL;
612         GtkAction *action = NULL;
613
614         self  = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
615         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
616         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
617
618         parent_priv->ui_manager = gtk_ui_manager_new();
619         parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
620
621         action_group = gtk_action_group_new ("ModestMainWindowActions");
622         gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
623
624         menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules");
625         toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules");
626
627         /* Add common actions */
628         gtk_action_group_add_actions (action_group,
629                                       modest_action_entries,
630                                       G_N_ELEMENTS (modest_action_entries),
631                                       self);
632
633         gtk_action_group_add_actions (action_group,
634                                       modest_folder_view_action_entries,
635                                       G_N_ELEMENTS (modest_folder_view_action_entries),
636                                       self);
637
638         gtk_action_group_add_actions (action_group,
639                                       modest_header_view_action_entries,
640                                       G_N_ELEMENTS (modest_header_view_action_entries),
641                                       self);
642
643         gtk_action_group_add_toggle_actions (action_group,
644                                              modest_toggle_action_entries,
645                                              G_N_ELEMENTS (modest_toggle_action_entries),
646                                              self);
647
648         gtk_action_group_add_toggle_actions (action_group,
649                                              modest_main_window_toggle_action_entries,
650                                              G_N_ELEMENTS (modest_main_window_toggle_action_entries),
651                                              self);
652
653         gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
654         g_object_unref (action_group);
655
656         /* Load the UI definition */
657         gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
658                                          MODEST_UIDIR "modest-main-window-ui.xml", &error);
659         if (error != NULL) {
660                 g_warning ("Could not merge modest-ui.xml: %s", error->message);
661                 g_error_free (error);
662                 error = NULL;
663         }
664
665         /* Add common dimming rules */
666         modest_dimming_rules_group_add_rules (menu_rules_group, 
667                                               modest_main_window_menu_dimming_entries,
668                                               G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
669                                               self);
670         modest_dimming_rules_group_add_rules (toolbar_rules_group, 
671                                               modest_main_window_toolbar_dimming_entries,
672                                               G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
673                                               self);
674
675         /* Insert dimming rules group for this window */
676         modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
677         modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
678         g_object_unref (menu_rules_group);
679         g_object_unref (toolbar_rules_group);
680         
681         /* Add accelerators */
682         gtk_window_add_accel_group (GTK_WINDOW (self), 
683                                     gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
684
685         /* Menubar. Update the state of some toggles */
686         parent_priv->menubar = modest_maemo_utils_menubar_to_menu (parent_priv->ui_manager);
687         conf = modest_runtime_get_conf ();
688         action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
689                                             "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
690         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
691                                       modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR, NULL));
692         action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
693                                             "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
694         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
695                                       modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR_FULLSCREEN, NULL));
696         hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
697
698         /* Get device name */
699         modest_maemo_utils_get_device_name ();
700
701         /* folder view */
702         query = tny_folder_store_query_new ();
703         tny_folder_store_query_add_item (query, NULL,
704                                          TNY_FOLDER_STORE_QUERY_OPTION_SUBSCRIBED);
705         priv->folder_view = MODEST_FOLDER_VIEW(modest_folder_view_new (query));
706         if (!priv->folder_view)
707                 g_printerr ("modest: cannot instantiate folder view\n");
708         g_object_unref (G_OBJECT (query));
709         modest_folder_view_set_style (priv->folder_view,
710                                       MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
711
712         /* header view */
713         priv->header_view  =
714                 MODEST_HEADER_VIEW(modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
715         if (!priv->header_view)
716                 g_printerr ("modest: cannot instantiate header view\n");
717         modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
718         
719         /* Create scrolled windows */
720         folder_win = gtk_scrolled_window_new (NULL, NULL);
721         priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
722         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
723                                         GTK_POLICY_NEVER,
724                                         GTK_POLICY_AUTOMATIC);
725         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
726                                         GTK_POLICY_NEVER,
727                                         GTK_POLICY_AUTOMATIC);
728
729         wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
730         wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET(priv->header_view));
731
732         /* paned */
733         priv->main_paned = gtk_hpaned_new ();
734         gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
735         gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
736         gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
737
738         /* putting it all together... */
739         priv->main_vbox = gtk_vbox_new (FALSE, 6);
740         gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
741
742         gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
743
744         /* Set window icon */
745         window_icon = modest_platform_get_icon (MODEST_APP_ICON);
746         gtk_window_set_icon (GTK_WINDOW (self), window_icon);
747         
748         /* Connect signals */
749         connect_signals (self);
750
751         /* Set account store */
752         tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
753                                                   TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
754
755         /* Do send & receive when we are idle */
756         /* TODO: Enable this again. I have commented it out because, 
757          * at least in scratchbox, this can cause us to start a second 
758          * update (in response to a connection change) when we are already 
759          * doing an update (started here, at startup). Tinymail doesn't like that.
760          * murrayc.
761          */
762         /* g_idle_add ((GSourceFunc)sync_accounts_cb, self); */
763         
764         HildonProgram *app = hildon_program_get_instance ();
765         hildon_program_add_window (app, HILDON_WINDOW (self));
766         
767         /* Register HildonProgram  signal handlers: */
768         /* These are apparently deprecated, according to the 
769          * "HildonApp/HildonAppView to HildonProgram/HildonWindow migration guide",
770          * though the API reference does not mention that:
771          *
772         g_signal_connect (G_OBJECT(app), "topmost_status_lose",
773                 G_CALLBACK (on_hildon_program_save_state), self);
774         g_signal_connect (G_OBJECT(app), "topmost_status_acquire",
775                 G_CALLBACK (on_hildon_program_status_acquire), self);
776     */
777         g_signal_connect (G_OBJECT(app), "notify::is-topmost",
778                 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
779                 
780         /* Load previous osso state, for instance if we are being restored from 
781          * hibernation:  */
782         modest_osso_load_state();
783
784         /* Restore window & widget settings */
785         restore_settings (MODEST_MAIN_WINDOW(self));
786
787         return MODEST_WINDOW(self);
788 }
789
790 gboolean 
791 modest_main_window_close_all (ModestMainWindow *self)
792 {
793         GtkWidget *note;
794         GtkResponseType response;
795
796         /* Create the confirmation dialog MSG-NOT308 */
797         note = hildon_note_new_confirmation_add_buttons (GTK_WINDOW (self),
798                                                          _("emev_nc_close_windows"),
799                                                          _("mcen_bd_yes"), GTK_RESPONSE_YES,
800                                                          _("mcen_bd_no"), GTK_RESPONSE_NO,
801                                                          NULL);
802
803         response = gtk_dialog_run (GTK_DIALOG (note));
804         gtk_widget_destroy (GTK_WIDGET (note));
805
806         if (response == GTK_RESPONSE_YES)
807                 return TRUE;
808         else
809                 return FALSE;
810 }
811
812
813 void 
814 modest_main_window_set_style (ModestMainWindow *self, 
815                               ModestMainWindowStyle style)
816 {
817         ModestMainWindowPrivate *priv;
818         ModestWindowPrivate *parent_priv;
819         GtkAction *action;
820
821         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
822
823         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
824         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
825
826         /* no change -> nothing to do */
827         if (priv->style == style)
828                 return;
829
830         /* Get toggle button */
831         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarToggleView");
832
833         priv->style = style;
834         switch (style) {
835         case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
836                 /* Remove main paned */
837                 g_object_ref (priv->main_paned);
838                 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
839
840                 /* Reparent the contents widget to the main vbox */
841                 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
842
843                 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
844                 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
845                 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
846
847                 break;
848         case MODEST_MAIN_WINDOW_STYLE_SPLIT:
849                 /* Remove header view */
850                 g_object_ref (priv->contents_widget);
851                 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
852
853                 /* Reparent the main paned */
854                 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
855                 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
856
857                 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
858                 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), FALSE);
859                 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
860
861                 break;
862         default:
863                 g_return_if_reached ();
864         }
865
866         /* Let header view grab the focus if it's being shown */
867         if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
868                 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
869         else 
870                 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
871
872         /* Show changes */
873         gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
874 }
875
876 ModestMainWindowStyle
877 modest_main_window_get_style (ModestMainWindow *self)
878 {
879         ModestMainWindowPrivate *priv;
880
881         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
882
883         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
884         return priv->style;
885 }
886
887
888
889 static gboolean
890 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
891 {
892         if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
893                 ModestWindowPrivate *parent_priv;
894                 ModestWindowMgr *mgr;
895                 gboolean is_fullscreen;
896                 GtkAction *fs_toggle_action;
897                 gboolean active;
898                 
899                 mgr = modest_runtime_get_window_mgr ();
900                 
901                 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
902
903                 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
904                 
905                 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
906                 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
907                 if (is_fullscreen != active) {
908                         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
909                 }
910         }
911
912         return FALSE;
913
914 }
915
916 static void
917 set_homogeneous (GtkWidget *widget,
918                  gpointer data)
919 {
920         gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
921         gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
922 }
923
924 static void 
925 modest_main_window_show_toolbar (ModestWindow *self,
926                                  gboolean show_toolbar)
927 {
928         ModestMainWindowPrivate *priv = NULL;
929         ModestWindowPrivate *parent_priv = NULL;        
930         GtkWidget *reply_button = NULL, *menu = NULL;
931         GtkWidget *placeholder = NULL;
932         gint insert_index;
933
934         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
935         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
936         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
937
938         /* Set optimized view status */
939         priv->optimized_view = !show_toolbar;
940
941         if (!parent_priv->toolbar) {
942                 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, 
943                                                                   "/ToolBar");
944
945                 /* Set homogeneous toolbar */
946                 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar), 
947                                        set_homogeneous, NULL);
948         
949                 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
950                 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
951                 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
952                 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
953                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
954                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
955                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
956                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
957
958                 /* Add ProgressBar (Transfer toolbar) */ 
959                 priv->progress_bar = modest_progress_bar_widget_new ();
960                 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
961                 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
962                 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
963                 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
964                 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
965                 
966                 /* Connect cancel 'clicked' signal to abort progress mode */
967                 g_signal_connect(priv->cancel_toolitem, "clicked",
968                                  G_CALLBACK(cancel_progressbar),
969                                  self);
970                 
971                 /* Add it to the observers list */
972                 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
973
974                 /* Add to window */
975                 hildon_window_add_toolbar (HILDON_WINDOW (self), 
976                                            GTK_TOOLBAR (parent_priv->toolbar));
977
978                 /* Set reply button tap and hold menu */
979                 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager, 
980                                                           "/ToolBar/ToolbarMessageReply");
981                 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
982                                                   "/ToolbarReplyCSM");
983                 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
984
985                 /* Set send & receive button tap and hold menu */
986                 on_account_update (TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()),
987                                    NULL, self);
988         }
989
990         if (show_toolbar) {
991                 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */ 
992                 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
993                 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
994
995                 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
996                 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
997         } else
998                 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
999
1000 }
1001
1002 static gint
1003 compare_display_names (ModestAccountData *a,
1004                        ModestAccountData *b)
1005 {
1006         return strcmp (a->display_name, b->display_name);
1007 }
1008
1009 static void 
1010 on_account_update (TnyAccountStore *account_store, 
1011                    const gchar *account_name,
1012                    gpointer user_data)
1013 {
1014         GSList *account_names, *iter, *accounts;
1015         ModestMainWindow *self;
1016         ModestMainWindowPrivate *priv;
1017         ModestWindowPrivate *parent_priv;
1018         ModestAccountMgr *mgr;
1019         gint i, num_accounts;                                   
1020         GtkActionGroup *action_group;
1021         GList *groups;
1022         gchar *default_account;
1023         GtkWidget *send_receive_button, *item;
1024                 
1025         self = MODEST_MAIN_WINDOW (user_data);
1026         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
1027         parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1028
1029         /* Get enabled account IDs */
1030         mgr = modest_runtime_get_account_mgr ();
1031         account_names = modest_account_mgr_account_names (mgr, TRUE);
1032         iter = account_names;
1033         accounts = NULL;
1034
1035         while (iter) {
1036                 ModestAccountData *account_data = 
1037                         modest_account_mgr_get_account_data (mgr, (gchar*) iter->data);
1038                 accounts = g_slist_prepend (accounts, account_data);
1039
1040                 iter = iter->next;
1041         }
1042         g_slist_free (account_names);
1043
1044         /* Order the list of accounts by its display name */
1045         accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
1046         num_accounts = g_slist_length (accounts);
1047
1048         /* Delete old send&receive popup items. We can not just do a
1049            menu_detach because it does not work well with
1050            tap_and_hold */
1051         if (priv->accounts_popup)
1052                 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup), 
1053                                        (GtkCallback) gtk_widget_destroy, NULL);
1054
1055         /* Delete old entries in the View menu. Do not free groups, it
1056            belongs to Gtk+ */
1057         groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
1058         while (groups) {
1059                 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
1060                              gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
1061                         gtk_ui_manager_remove_action_group (parent_priv->ui_manager, 
1062                                                             GTK_ACTION_GROUP (groups->data));
1063                         groups = NULL;
1064                         /* Remove uis */
1065                         if (priv->merge_ids) {
1066                                 for (i = 0; i < priv->merge_ids->len; i++)
1067                                         gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
1068                                 g_byte_array_free (priv->merge_ids, TRUE);
1069                         }
1070                         /* We need to call this in order to ensure
1071                            that the new actions are added in the right
1072                            order (alphabetical */
1073                         gtk_ui_manager_ensure_update (parent_priv->ui_manager);
1074                 } else 
1075                         groups = g_list_next (groups);
1076         }
1077         priv->merge_ids = g_byte_array_sized_new (num_accounts);
1078
1079         /* Get send receive button */
1080         send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1081                                                           "/ToolBar/ToolbarSendReceive");
1082
1083         /* Create the menu */
1084         if (num_accounts > 1) {
1085                 if (!priv->accounts_popup)
1086                         priv->accounts_popup = gtk_menu_new ();
1087                 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
1088                 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1089                 g_signal_connect (G_OBJECT (item), 
1090                                   "activate", 
1091                                   G_CALLBACK (on_send_receive_csm_activated),
1092                                   NULL);
1093                 item = gtk_separator_menu_item_new ();
1094                 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1095         }
1096
1097         /* Create a new action group */
1098         default_account = modest_account_mgr_get_default_account (mgr);
1099         action_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
1100         for (i = 0; i < num_accounts; i++) {
1101                 gchar *display_name = NULL;
1102                 
1103                 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
1104
1105                 /* Create display name. The default account is shown differently */
1106                 if (default_account && account_data->account_name && 
1107                         !(strcmp (default_account, account_data->account_name) == 0)) {
1108                         display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"), 
1109                                                         account_data->display_name);
1110                 }
1111                 else {
1112                         display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"), 
1113                                                         account_data->display_name);
1114                 }
1115
1116                 /* Create action and add it to the action group. The
1117                    action name must be the account name, this way we
1118                    could know in the handlers the account to show */
1119                 if(account_data->account_name) {
1120                         gchar* item_name, *refresh_action_name;
1121                         guint8 merge_id;
1122                         GtkAction *view_account_action, *refresh_account_action;
1123
1124                         view_account_action = gtk_action_new (account_data->account_name,
1125                                                               display_name, NULL, NULL);
1126                         gtk_action_group_add_action (action_group, view_account_action);
1127
1128                         /* Add ui from account data. We allow 2^9-1 account
1129                            changes in a single execution because we're
1130                            downcasting the guint to a guint8 in order to use a
1131                            GByteArray, it should be enough */
1132                         item_name = g_strconcat (account_data->account_name, "Menu", NULL);
1133                         merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
1134                         priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
1135                         gtk_ui_manager_add_ui (parent_priv->ui_manager,
1136                                                merge_id,
1137                                                "/MenuBar/ViewMenu/ViewMenuAdditions",
1138                                                item_name,
1139                                                account_data->account_name,
1140                                                GTK_UI_MANAGER_MENUITEM,
1141                                                FALSE);
1142         
1143                         /* Connect the action signal "activate" */
1144                         g_signal_connect (G_OBJECT (view_account_action),
1145                                           "activate",
1146                                           G_CALLBACK (on_show_account_action_activated),
1147                                           self);
1148
1149                         /* Create the items for the Tools->Send&Receive submenu */
1150                         refresh_action_name = g_strconcat ("SendReceive", account_data->account_name, NULL);
1151                         refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name, 
1152                                                                  display_name, NULL, NULL);
1153                         gtk_action_group_add_action (action_group, refresh_account_action);
1154
1155                         merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
1156                         priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
1157                         gtk_ui_manager_add_ui (parent_priv->ui_manager, 
1158                                                merge_id,
1159                                                "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
1160                                                item_name,
1161                                                refresh_action_name,
1162                                                GTK_UI_MANAGER_MENUITEM,
1163                                                FALSE);
1164                         g_free (refresh_action_name);
1165
1166                         g_signal_connect_data (G_OBJECT (refresh_account_action), 
1167                                                "activate", 
1168                                                G_CALLBACK (on_refresh_account_action_activated), 
1169                                                g_strdup (account_data->account_name),
1170                                                (GClosureNotify) g_free,
1171                                                0);
1172
1173                         /* Create item and add it to the send&receive
1174                            CSM. If there is only one account then
1175                            it'll be no menu */
1176                         if (priv->accounts_popup) {
1177                                 item = gtk_menu_item_new_with_label (display_name);
1178                                 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1179                                 g_signal_connect_data (G_OBJECT (item), 
1180                                                        "activate", 
1181                                                        G_CALLBACK (on_send_receive_csm_activated),
1182                                                        g_strdup (account_data->account_name),
1183                                                        (GClosureNotify) g_free,
1184                                                        0);
1185                         }
1186                         g_free (item_name);
1187                 }
1188
1189                 /* Frees */
1190                 g_free (display_name);
1191                 modest_account_mgr_free_account_data (mgr, account_data);
1192         }
1193         gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 1);
1194
1195         if (priv->accounts_popup) {
1196                 /* Mandatory in order to view the menu contents */
1197                 gtk_widget_show_all (priv->accounts_popup);
1198
1199                 /* Setup tap_and_hold just if was not done before*/
1200                 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
1201                         gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
1202         }
1203
1204         /* Frees */
1205         g_slist_free (accounts);
1206         g_free (default_account);
1207 }
1208
1209 /* 
1210  * This function manages the key events used to navigate between
1211  * header and folder views (when the window is in split view)
1212  *
1213  * FROM         KEY        ACTION
1214  * -------------------------------------------------
1215  * HeaderView   GDK_Left   Move focus to folder view
1216  * FolderView   GDK_Right  Move focus to header view
1217  *
1218  * There is no need to scroll to selected row, the widgets will be the
1219  * responsibles of doing that (probably managing the focus-in event
1220  */
1221 static gboolean 
1222 on_inner_widgets_key_pressed (GtkWidget *widget,
1223                               GdkEventKey *event,
1224                               gpointer user_data)
1225 {
1226         ModestMainWindowPrivate *priv;
1227
1228         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1229
1230         /* Do nothing if we're in SIMPLE style */
1231         if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1232                 return FALSE;
1233
1234         if (MODEST_IS_HEADER_VIEW (widget) && event->keyval == GDK_Left)
1235                 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1236         else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1237                 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1238
1239         return FALSE;
1240 }
1241
1242 static void
1243 set_alignment (GtkWidget *widget,
1244                gpointer data)
1245 {
1246         gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1247         gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1248 }
1249
1250 static GtkWidget *
1251 create_details_widget (TnyAccount *account)
1252 {
1253         GtkWidget *vbox;
1254         gchar *label;
1255
1256         vbox = gtk_vbox_new (FALSE, 0);
1257
1258         /* Account description: */
1259         
1260         if (modest_tny_account_is_virtual_local_folders (account)) {
1261                 /* Local folders: */
1262         
1263                 /* Get device name */
1264                 gchar *device_name = modest_conf_get_string (modest_runtime_get_conf(),
1265                                                       MODEST_CONF_DEVICE_NAME, NULL);
1266    
1267                 label = g_strdup_printf (_("mcen_fi_localroot_description"),
1268                                          device_name);
1269                 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1270                 g_free (device_name);
1271                 g_free (label);
1272         } else {
1273                 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1274                         gtk_box_pack_start (GTK_BOX (vbox), 
1275                                 gtk_label_new (tny_account_get_name (account)), 
1276                                 FALSE, FALSE, 0);
1277                 } else {
1278                         /* Other accounts, such as IMAP and POP: */
1279                         
1280                         GString *proto;
1281                         gchar *tmp;
1282         
1283                         /* Put proto in uppercase */
1284                         proto = g_string_new (tny_account_get_proto (account));
1285                         proto = g_string_ascii_up (proto);
1286                         
1287                         /* note: mcen_fi_localroot_description is something like "%s account"
1288                          * however, we should display "%s account: %s"... therefore, ugly tmp */
1289                         tmp   = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1290                         label = g_strdup_printf ("%s: %s", tmp,tny_account_get_name (account));
1291                         g_free (tmp);
1292
1293                         gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1294                         g_string_free (proto, TRUE);
1295                         g_free (label);
1296                 }
1297         }
1298
1299         /* Message count */
1300         TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1301         label = g_strdup_printf ("%s: %d", _("mcen_fi_rootfolder_messages"), 
1302                                  modest_tny_folder_store_get_message_count (folder_store));
1303         gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1304         g_free (label);
1305
1306         /* Folder count */
1307         label = g_strdup_printf ("%s: %d", _("mcen_fi_rootfolder_folders"), 
1308                                  modest_tny_folder_store_get_folder_count (folder_store));
1309         gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1310         g_free (label);
1311
1312         /* Size / Date */
1313         if (modest_tny_account_is_virtual_local_folders (account)) {
1314                 /* FIXME: format size */
1315                 label = g_strdup_printf ("%s: %d", _("mcen_fi_rootfolder_size"), 
1316                                          modest_tny_folder_store_get_local_size (folder_store));
1317                 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1318                 g_free (label);
1319         } else if (TNY_IS_ACCOUNT(folder_store)) {
1320                 TnyAccount *account = TNY_ACCOUNT(folder_store);
1321                 
1322                 time_t last_updated;
1323                 gchar *last_updated_string;
1324                 /* Get last updated from configuration */
1325                 last_updated = modest_account_mgr_get_int (modest_runtime_get_account_mgr (), 
1326                                                           tny_account_get_id (account), 
1327                                                           MODEST_ACCOUNT_LAST_UPDATED, 
1328                                                           TRUE);
1329                 if (last_updated > 0) 
1330                         last_updated_string = modest_text_utils_get_display_date(last_updated);
1331                 else
1332                         last_updated_string = g_strdup (_("FIXME: Never"));
1333
1334                 label = g_strdup_printf ("%s: %s", _("mcen_ti_lastupdated"), last_updated_string);
1335                 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1336                 g_free (last_updated_string);
1337                 g_free (label);
1338         }
1339
1340         /* Set alignment */
1341         gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1342
1343         return vbox;
1344 }
1345
1346 void 
1347 modest_main_window_set_contents_style (ModestMainWindow *self, 
1348                                        ModestMainWindowContentsStyle style)
1349 {
1350         ModestMainWindowPrivate *priv;
1351
1352         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1353
1354         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1355
1356         /* We allow to set the same content style than the previously
1357            set if there are details, because it could happen when we're
1358            selecting different accounts consecutively */
1359         if ((priv->contents_style == style) &&
1360             (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS))
1361                 return;
1362
1363         /* Remove previous child. Delete it if it was an account
1364            details widget */
1365         GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1366         if (content) {
1367                 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1368                         g_object_ref (content);
1369                 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1370         }
1371
1372         priv->contents_style = style;
1373
1374         switch (priv->contents_style) {
1375         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1376                 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1377                 break;
1378         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1379         {
1380                 /* TODO: show here account details */
1381                 TnyFolderStore *selected_folderstore = 
1382                         modest_folder_view_get_selected (priv->folder_view);
1383                 if (TNY_IS_ACCOUNT (selected_folderstore)) {    
1384                         priv->details_widget = create_details_widget (
1385                                 TNY_ACCOUNT (selected_folderstore));
1386
1387                         wrap_in_scrolled_window (priv->contents_widget, 
1388                                          priv->details_widget);
1389                 }
1390                 break;
1391         }
1392         default:
1393                 g_return_if_reached ();
1394         }
1395
1396         /* Show */
1397         gtk_widget_show_all (priv->contents_widget);
1398 }
1399
1400 static void 
1401 on_configuration_key_changed (ModestConf* conf, 
1402                               const gchar *key, 
1403                               ModestConfEvent event, 
1404                               ModestMainWindow *self)
1405 {
1406         ModestMainWindowPrivate *priv;
1407         TnyAccount *account;
1408
1409         if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
1410                 return;
1411
1412         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1413
1414         if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1415                 return;
1416
1417         account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1418         if (TNY_IS_ACCOUNT (account) &&
1419             !strcmp (tny_account_get_id (account), MODEST_ACTUAL_LOCAL_FOLDERS_ACCOUNT_ID)) {
1420                 GList *children;
1421                 GtkLabel *label;
1422                 const gchar *device_name;
1423                 gchar *new_text;
1424                 
1425                 /* Get label */
1426                 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1427                 label = GTK_LABEL (children->data);
1428                 
1429                 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1430                                                       MODEST_CONF_DEVICE_NAME, NULL);
1431                 
1432                 new_text = g_strdup_printf ("%s: %s",
1433                                             _("mcen_fi_localroot_description"),
1434                                             device_name);
1435                 
1436                 gtk_label_set_text (label, new_text);
1437                 gtk_widget_show (GTK_WIDGET (label));
1438                 
1439                 g_free (new_text);
1440                 g_list_free (children);
1441         }
1442 }
1443
1444 static gboolean
1445 set_toolbar_transfer_mode (ModestMainWindow *self)
1446 {
1447         ModestMainWindowPrivate *priv = NULL;
1448         
1449         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1450
1451         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1452
1453         set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1454         
1455         if (priv->progress_bar_timeout > 0) {
1456                 g_source_remove (priv->progress_bar_timeout);
1457                 priv->progress_bar_timeout = 0;
1458         }
1459
1460         return FALSE;
1461 }
1462
1463 static void 
1464 set_toolbar_mode (ModestMainWindow *self, 
1465                   ModestToolBarModes mode)
1466 {
1467         ModestWindowPrivate *parent_priv = NULL;
1468         ModestMainWindowPrivate *priv = NULL;
1469         GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1470         
1471         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1472
1473         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1474         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1475
1476         g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar)); 
1477         
1478         sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1479         refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1480         cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1481
1482         /* Sets current toolbar mode */
1483         priv->current_toolbar_mode = mode;
1484
1485         /* Show and hide toolbar items */
1486         switch (mode) {
1487         case TOOLBAR_MODE_NORMAL:
1488                 if (sort_action) 
1489                         gtk_action_set_visible (sort_action, TRUE);
1490                 if (refresh_action) 
1491                         gtk_action_set_visible (refresh_action, TRUE);
1492                 if (priv->progress_toolitem) {
1493                         gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1494                         gtk_widget_hide (priv->progress_toolitem);
1495                 }
1496                 if (priv->progress_bar)
1497                         gtk_widget_hide (priv->progress_bar);                   
1498                 
1499                 if (cancel_action)
1500                         gtk_action_set_visible (cancel_action, FALSE);
1501
1502                 /* Hide toolbar if optimized view is enabled */
1503                 if (priv->optimized_view)
1504                         gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
1505                 break;
1506         case TOOLBAR_MODE_TRANSFER:
1507                 if (sort_action)
1508                         gtk_action_set_visible (sort_action, FALSE);
1509                 if (refresh_action)
1510                         gtk_action_set_visible (refresh_action, FALSE);
1511                 if (cancel_action)
1512                         gtk_action_set_visible (cancel_action, TRUE);
1513                 if (priv->progress_toolitem) {
1514                         gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1515                         gtk_widget_show (priv->progress_toolitem);
1516                 }
1517                 if (priv->progress_bar)
1518                         gtk_widget_show (priv->progress_bar);                   
1519
1520                 /* Show toolbar if it's hiden (optimized view ) */
1521                 if (priv->optimized_view)
1522                         gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1523                 break;
1524         default:
1525                 g_return_if_reached ();
1526         }
1527 }
1528
1529 static void
1530 cancel_progressbar (GtkToolButton *toolbutton,
1531                     ModestMainWindow *self)
1532 {
1533         GSList *tmp;
1534         ModestMainWindowPrivate *priv;
1535         
1536         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1537
1538         /* Get operation observers and cancel its current operation */
1539         tmp = priv->progress_widgets;
1540         while (tmp) {
1541                 modest_progress_object_cancel_current_operation (MODEST_PROGRESS_OBJECT(tmp->data));
1542                 tmp=g_slist_next(tmp);
1543         }
1544 }
1545
1546 static gboolean
1547 observers_empty (ModestMainWindow *self)
1548 {
1549         GSList *tmp = NULL;
1550         ModestMainWindowPrivate *priv;
1551         gboolean is_empty = TRUE;
1552         guint pending_ops = 0;
1553  
1554         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1555         tmp = priv->progress_widgets;
1556
1557         /* Check all observers */
1558         while (tmp && is_empty)  {
1559                 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
1560                 is_empty = pending_ops == 0;
1561                 
1562                 tmp = g_slist_next(tmp);
1563         }
1564         
1565         return is_empty;
1566 }
1567
1568 static void
1569 on_queue_changed (ModestMailOperationQueue *queue,
1570                   ModestMailOperation *mail_op,
1571                   ModestMailOperationQueueNotification type,
1572                   ModestMainWindow *self)
1573 {
1574         ModestMainWindowPrivate *priv;
1575         ModestMailOperationTypeOperation op_type;
1576         ModestToolBarModes mode;
1577         GSList *tmp;
1578         gboolean mode_changed = FALSE;
1579 /*      ModestMailOperationStatus status; */
1580
1581         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1582         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1583                
1584         /* Get toolbar mode from operation id*/
1585         op_type = modest_mail_operation_get_type_operation (mail_op);
1586         switch (op_type) {
1587         case MODEST_MAIL_OPERATION_TYPE_SEND:
1588         case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
1589                 mode = TOOLBAR_MODE_TRANSFER;
1590                 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
1591                         mode_changed = TRUE;
1592                 break;
1593         default:
1594                 mode = TOOLBAR_MODE_NORMAL;
1595                 
1596         }
1597                 
1598                        
1599         /* Add operation observers and change toolbar if neccessary*/
1600         tmp = priv->progress_widgets;
1601         switch (type) {
1602         case MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED:
1603                 if (mode == TOOLBAR_MODE_TRANSFER) {
1604                         if (mode_changed)
1605                                 set_toolbar_transfer_mode(self);                    
1606                         while (tmp) {
1607                                 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
1608                                                                       mail_op);
1609                                 tmp = g_slist_next (tmp);
1610                         }
1611                 }
1612                 break;
1613         case MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED:
1614                 /* Change toolbar mode */
1615                 if (mode == TOOLBAR_MODE_TRANSFER) {                    
1616                         while (tmp) {
1617                                 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
1618                                                                          mail_op);
1619                                 tmp = g_slist_next (tmp);
1620                         }
1621                         
1622                         /* If no more operations are being observed, NORMAL mode is enabled again */
1623                         if (observers_empty (self)) {
1624                                 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
1625                                 
1626                         }
1627                 }
1628
1629                 break;
1630         }       
1631
1632 }
1633
1634 static void 
1635 on_show_account_action_activated  (GtkAction *action,
1636                                    gpointer user_data)
1637 {
1638         ModestAccountData *acc_data;
1639         ModestMainWindow *self;
1640         ModestMainWindowPrivate *priv;
1641         ModestAccountMgr *mgr;
1642         const gchar *acc_name;
1643
1644         self = MODEST_MAIN_WINDOW (user_data);
1645         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1646
1647         /* Get account data */
1648         acc_name = gtk_action_get_name (action);
1649         mgr = modest_runtime_get_account_mgr ();
1650         acc_data = modest_account_mgr_get_account_data (mgr, acc_name);
1651
1652         /* Set the new visible & active account */
1653         if (acc_data->store_account) { 
1654                 modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view,
1655                                                                              acc_data->store_account->account_name);
1656                 modest_window_set_active_account (MODEST_WINDOW (self), acc_data->account_name);
1657         }
1658
1659         /* Free */
1660         modest_account_mgr_free_account_data (mgr, acc_data);
1661 }
1662
1663 static void
1664 refresh_account (const gchar *account_name)
1665 {
1666         ModestWindow *win;
1667
1668         win = MODEST_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
1669
1670         /* If account_name == NULL, we must update all (option All) */
1671         if (!account_name)
1672                 modest_ui_actions_do_send_receive_all (win);
1673         else
1674                 modest_ui_actions_do_send_receive (account_name, win);
1675 }
1676
1677 static void 
1678 on_refresh_account_action_activated  (GtkAction *action,
1679                                       gpointer user_data)
1680 {
1681         refresh_account ((const gchar*) user_data);
1682 }
1683
1684 static void
1685 on_send_receive_csm_activated (GtkMenuItem *item,
1686                                gpointer user_data)
1687 {
1688         refresh_account ((const gchar*) user_data);
1689 }