2007-06-05 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 <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 ("%s: %s",
1268                                          _("mcen_fi_localroot_description"),
1269                                          device_name);
1270                 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1271                 g_free (device_name);
1272                 g_free (label);
1273         } else {
1274                 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1275                         gtk_box_pack_start (GTK_BOX (vbox), 
1276                                 gtk_label_new (tny_account_get_name (account)), 
1277                                 FALSE, FALSE, 0);
1278                 } else {
1279                         /* Other accounts, such as IMAP and POP: */
1280                         
1281                         GString *proto;
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                         label = g_strdup_printf ("%s %s: %s", 
1288                                                  proto->str,
1289                                                  _("mcen_fi_remoteroot_account"),
1290                                                  tny_account_get_name (account));
1291                         gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1292                         g_string_free (proto, TRUE);
1293                         g_free (label);
1294                 }
1295         }
1296
1297         /* Message count */
1298         TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1299         label = g_strdup_printf ("%s: %d", _("mcen_fi_rootfolder_messages"), 
1300                                  modest_tny_folder_store_get_message_count (folder_store));
1301         gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1302         g_free (label);
1303
1304         /* Folder count */
1305         label = g_strdup_printf ("%s: %d", _("mcen_fi_rootfolder_folders"), 
1306                                  modest_tny_folder_store_get_folder_count (folder_store));
1307         gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1308         g_free (label);
1309
1310         /* Size / Date */
1311         if (modest_tny_account_is_virtual_local_folders (account)) {
1312                 /* FIXME: format size */
1313                 label = g_strdup_printf ("%s: %d", _("mcen_fi_rootfolder_size"), 
1314                                          modest_tny_folder_store_get_local_size (folder_store));
1315                 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1316                 g_free (label);
1317         } else if (TNY_IS_ACCOUNT(folder_store)) {
1318                 TnyAccount *account = TNY_ACCOUNT(folder_store);
1319                 
1320                 time_t last_updated;
1321                 gchar *last_updated_string;
1322                 /* Get last updated from configuration */
1323                 last_updated = modest_account_mgr_get_int (modest_runtime_get_account_mgr (), 
1324                                                           tny_account_get_id (account), 
1325                                                           MODEST_ACCOUNT_LAST_UPDATED, 
1326                                                           TRUE);
1327                 if (last_updated > 0) 
1328                         last_updated_string = modest_text_utils_get_display_date(last_updated);
1329                 else
1330                         last_updated_string = g_strdup (_("FIXME: Never"));
1331
1332                 label = g_strdup_printf ("%s: %s", _("mcen_ti_lastupdated"), last_updated_string);
1333                 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1334                 g_free (last_updated_string);
1335                 g_free (label);
1336         }
1337
1338         /* Set alignment */
1339         gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1340
1341         return vbox;
1342 }
1343
1344 void 
1345 modest_main_window_set_contents_style (ModestMainWindow *self, 
1346                                        ModestMainWindowContentsStyle style)
1347 {
1348         ModestMainWindowPrivate *priv;
1349
1350         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1351
1352         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1353
1354         /* We allow to set the same content style than the previously
1355            set if there are details, because it could happen when we're
1356            selecting different accounts consecutively */
1357         if ((priv->contents_style == style) &&
1358             (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS))
1359                 return;
1360
1361         /* Remove previous child. Delete it if it was an account
1362            details widget */
1363         GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1364         if (content) {
1365                 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1366                         g_object_ref (content);
1367                 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1368         }
1369
1370         priv->contents_style = style;
1371
1372         switch (priv->contents_style) {
1373         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1374                 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1375                 break;
1376         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1377         {
1378                 /* TODO: show here account details */
1379                 TnyFolderStore *selected_folderstore = 
1380                         modest_folder_view_get_selected (priv->folder_view);
1381                 if (TNY_IS_ACCOUNT (selected_folderstore)) {    
1382                         priv->details_widget = create_details_widget (
1383                                 TNY_ACCOUNT (selected_folderstore));
1384
1385                         wrap_in_scrolled_window (priv->contents_widget, 
1386                                          priv->details_widget);
1387                 }
1388                 break;
1389         }
1390         default:
1391                 g_return_if_reached ();
1392         }
1393
1394         /* Show */
1395         gtk_widget_show_all (priv->contents_widget);
1396 }
1397
1398 static void 
1399 on_configuration_key_changed (ModestConf* conf, 
1400                               const gchar *key, 
1401                               ModestConfEvent event, 
1402                               ModestMainWindow *self)
1403 {
1404         ModestMainWindowPrivate *priv;
1405         TnyAccount *account;
1406
1407         if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
1408                 return;
1409
1410         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1411
1412         if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1413                 return;
1414
1415         account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1416         if (TNY_IS_ACCOUNT (account) &&
1417             !strcmp (tny_account_get_id (account), MODEST_ACTUAL_LOCAL_FOLDERS_ACCOUNT_ID)) {
1418                 GList *children;
1419                 GtkLabel *label;
1420                 const gchar *device_name;
1421                 gchar *new_text;
1422                 
1423                 /* Get label */
1424                 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1425                 label = GTK_LABEL (children->data);
1426                 
1427                 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1428                                                       MODEST_CONF_DEVICE_NAME, NULL);
1429                 
1430                 new_text = g_strdup_printf ("%s: %s",
1431                                             _("mcen_fi_localroot_description"),
1432                                             device_name);
1433                 
1434                 gtk_label_set_text (label, new_text);
1435                 gtk_widget_show (GTK_WIDGET (label));
1436                 
1437                 g_free (new_text);
1438                 g_list_free (children);
1439         }
1440 }
1441
1442 static gboolean
1443 set_toolbar_transfer_mode (ModestMainWindow *self)
1444 {
1445         ModestMainWindowPrivate *priv = NULL;
1446         
1447         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1448
1449         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1450
1451         set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1452         
1453         if (priv->progress_bar_timeout > 0) {
1454                 g_source_remove (priv->progress_bar_timeout);
1455                 priv->progress_bar_timeout = 0;
1456         }
1457
1458         return FALSE;
1459 }
1460
1461 static void 
1462 set_toolbar_mode (ModestMainWindow *self, 
1463                   ModestToolBarModes mode)
1464 {
1465         ModestWindowPrivate *parent_priv = NULL;
1466         ModestMainWindowPrivate *priv = NULL;
1467         GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1468         
1469         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1470
1471         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1472         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1473
1474         g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar)); 
1475         
1476         sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1477         refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1478         cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1479
1480         /* Sets current toolbar mode */
1481         priv->current_toolbar_mode = mode;
1482
1483         /* Show and hide toolbar items */
1484         switch (mode) {
1485         case TOOLBAR_MODE_NORMAL:
1486                 if (sort_action) 
1487                         gtk_action_set_visible (sort_action, TRUE);
1488                 if (refresh_action) 
1489                         gtk_action_set_visible (refresh_action, TRUE);
1490                 if (priv->progress_toolitem) {
1491                         gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1492                         gtk_widget_hide (priv->progress_toolitem);
1493                 }
1494                 if (priv->progress_bar)
1495                         gtk_widget_hide (priv->progress_bar);                   
1496                 
1497                 if (cancel_action)
1498                         gtk_action_set_visible (cancel_action, FALSE);
1499
1500                 /* Hide toolbar if optimized view is enabled */
1501                 if (priv->optimized_view)
1502                         gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
1503                 break;
1504         case TOOLBAR_MODE_TRANSFER:
1505                 if (sort_action)
1506                         gtk_action_set_visible (sort_action, FALSE);
1507                 if (refresh_action)
1508                         gtk_action_set_visible (refresh_action, FALSE);
1509                 if (cancel_action)
1510                         gtk_action_set_visible (cancel_action, TRUE);
1511                 if (priv->progress_toolitem) {
1512                         gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1513                         gtk_widget_show (priv->progress_toolitem);
1514                 }
1515                 if (priv->progress_bar)
1516                         gtk_widget_show (priv->progress_bar);                   
1517
1518                 /* Show toolbar if it's hiden (optimized view ) */
1519                 if (priv->optimized_view)
1520                         gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1521                 break;
1522         default:
1523                 g_return_if_reached ();
1524         }
1525 }
1526
1527 static void
1528 cancel_progressbar (GtkToolButton *toolbutton,
1529                     ModestMainWindow *self)
1530 {
1531         GSList *tmp;
1532         ModestMainWindowPrivate *priv;
1533         
1534         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1535
1536         /* Get operation observers and cancel its current operation */
1537         tmp = priv->progress_widgets;
1538         while (tmp) {
1539                 modest_progress_object_cancel_current_operation (MODEST_PROGRESS_OBJECT(tmp->data));
1540                 tmp=g_slist_next(tmp);
1541         }
1542 }
1543
1544 static gboolean
1545 observers_empty (ModestMainWindow *self)
1546 {
1547         GSList *tmp = NULL;
1548         ModestMainWindowPrivate *priv;
1549         gboolean is_empty = TRUE;
1550         guint pending_ops = 0;
1551  
1552         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1553         tmp = priv->progress_widgets;
1554
1555         /* Check all observers */
1556         while (tmp && is_empty)  {
1557                 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
1558                 is_empty = pending_ops == 0;
1559                 
1560                 tmp = g_slist_next(tmp);
1561         }
1562         
1563         return is_empty;
1564 }
1565
1566 static void
1567 on_queue_changed (ModestMailOperationQueue *queue,
1568                   ModestMailOperation *mail_op,
1569                   ModestMailOperationQueueNotification type,
1570                   ModestMainWindow *self)
1571 {
1572         ModestMainWindowPrivate *priv;
1573         ModestMailOperationTypeOperation op_type;
1574         ModestToolBarModes mode;
1575         GSList *tmp;
1576         gboolean mode_changed = FALSE;
1577 /*      ModestMailOperationStatus status; */
1578
1579         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1580         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1581                
1582         /* Get toolbar mode from operation id*/
1583         op_type = modest_mail_operation_get_type_operation (mail_op);
1584         switch (op_type) {
1585         case MODEST_MAIL_OPERATION_TYPE_SEND:
1586         case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
1587                 mode = TOOLBAR_MODE_TRANSFER;
1588                 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
1589                         mode_changed = TRUE;
1590                 break;
1591         default:
1592                 mode = TOOLBAR_MODE_NORMAL;
1593                 
1594         }
1595                 
1596                        
1597         /* Add operation observers and change toolbar if neccessary*/
1598         tmp = priv->progress_widgets;
1599         switch (type) {
1600         case MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED:
1601                 if (mode == TOOLBAR_MODE_TRANSFER) {
1602                         if (mode_changed)
1603                                 set_toolbar_transfer_mode(self);                    
1604                         while (tmp) {
1605                                 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
1606                                                                       mail_op);
1607                                 tmp = g_slist_next (tmp);
1608                         }
1609                 }
1610                 break;
1611         case MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED:
1612                 /* Change toolbar mode */
1613                 if (mode == TOOLBAR_MODE_TRANSFER) {                    
1614                         while (tmp) {
1615                                 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
1616                                                                          mail_op);
1617                                 tmp = g_slist_next (tmp);
1618                         }
1619                         
1620                         /* If no more operations are being observed, NORMAL mode is enabled again */
1621                         if (observers_empty (self)) {
1622                                 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
1623                                 
1624                         }
1625                 }
1626
1627                 break;
1628         }       
1629
1630 }
1631
1632 static void 
1633 on_show_account_action_activated  (GtkAction *action,
1634                                    gpointer user_data)
1635 {
1636         ModestAccountData *acc_data;
1637         ModestMainWindow *self;
1638         ModestMainWindowPrivate *priv;
1639         ModestAccountMgr *mgr;
1640         const gchar *acc_name;
1641
1642         self = MODEST_MAIN_WINDOW (user_data);
1643         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1644
1645         /* Get account data */
1646         acc_name = gtk_action_get_name (action);
1647         mgr = modest_runtime_get_account_mgr ();
1648         acc_data = modest_account_mgr_get_account_data (mgr, acc_name);
1649
1650         /* Set the new visible & active account */
1651         if (acc_data->store_account) { 
1652                 modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view,
1653                                                                              acc_data->store_account->account_name);
1654                 modest_window_set_active_account (MODEST_WINDOW (self), acc_data->account_name);
1655         }
1656
1657         /* Free */
1658         modest_account_mgr_free_account_data (mgr, acc_data);
1659 }
1660
1661 static void
1662 refresh_account (const gchar *account_name)
1663 {
1664         ModestWindow *win;
1665
1666         win = MODEST_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
1667
1668         /* If account_name == NULL, we must update all (option All) */
1669         if (!account_name)
1670                 modest_ui_actions_do_send_receive_all (win);
1671         else
1672                 modest_ui_actions_do_send_receive (account_name, win);
1673 }
1674
1675 static void 
1676 on_refresh_account_action_activated  (GtkAction *action,
1677                                       gpointer user_data)
1678 {
1679         refresh_account ((const gchar*) user_data);
1680 }
1681
1682 static void
1683 on_send_receive_csm_activated (GtkMenuItem *item,
1684                                gpointer user_data)
1685 {
1686         refresh_account ((const gchar*) user_data);
1687 }