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