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