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