* some fixes towards fixing the right-hand-pane-empty problem
[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 /* 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, gboolean do_folder_view_too)
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
368         modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
369                                       MODEST_CONF_HEADER_VIEW_KEY);
370
371         if (do_folder_view_too)
372                 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
373                                       MODEST_CONF_FOLDER_VIEW_KEY);
374         modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
375                                       MODEST_CONF_MAIN_PANED_KEY);
376
377         /* We need to force a redraw here in order to get the right
378            position of the horizontal paned separator */
379         gtk_widget_show (GTK_WIDGET (self));
380 }
381
382
383 static void
384 save_state (ModestWindow *window)
385 {
386         ModestConf *conf;
387         ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
388         ModestMainWindowPrivate *priv;
389                 
390         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
391         conf = modest_runtime_get_conf ();
392         
393         modest_widget_memory_save (conf,G_OBJECT(self), 
394                                    MODEST_CONF_MAIN_WINDOW_KEY);
395         modest_widget_memory_save (conf, G_OBJECT(priv->main_paned), 
396                                    MODEST_CONF_MAIN_PANED_KEY);
397         //      modest_widget_memory_save (conf, G_OBJECT(priv->header_view), 
398         //                         MODEST_CONF_HEADER_VIEW_KEY);
399         modest_widget_memory_save (conf, G_OBJECT(priv->folder_view), 
400                                    MODEST_CONF_FOLDER_VIEW_KEY);
401 }
402
403 static void
404 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
405 {
406         if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
407                 gtk_scrolled_window_add_with_viewport
408                         (GTK_SCROLLED_WINDOW(win), widget);
409         else
410                 gtk_container_add (GTK_CONTAINER(win),
411                                    widget);
412 }
413
414
415 static gboolean
416 on_delete_event (GtkWidget *widget, GdkEvent  *event, ModestMainWindow *self)
417 {
418         modest_window_save_state (MODEST_WINDOW(self));
419         return FALSE;
420 }
421
422
423 static void
424 on_account_store_connecting_finished (TnyAccountStore *store, ModestMainWindow *self)
425 {
426         /* When going online, do the equivalent of pressing the send/receive button, 
427          * as per the specification:
428          * (without the check for >0 accounts, though that is not specified): */
429
430         TnyDevice *device = tny_account_store_get_device (store);
431         
432         /* Check that we are really online.
433          * This signal should not be emitted when we are not connected, 
434          * but it seems to happen sometimes: */
435          if (!tny_device_is_online (device))
436                 return;
437                 
438         const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device));
439         printf ("DEBUG: %s: connection id=%s\n", __FUNCTION__, iap_id);
440         
441         /* Stop the existing send queues: */
442         modest_runtime_remove_all_send_queues ();
443         
444         /* Create the send queues again, using the appropriate transport accounts 
445          * for this new connection.
446          * This could be the first time that they are created if this is the first 
447          * connection. */
448         /* TODO: Does this really destroy the TnySendQueues and their threads
449          * We do not want 2 TnySendQueues to exist with the same underlying 
450          * outbox directory. */
451         GSList *account_names = modest_account_mgr_account_names (
452                 modest_runtime_get_account_mgr(), 
453                 TRUE /* enabled accounts only */);
454         GSList *iter = account_names;
455         while (iter) {
456                 const gchar *account_name = (const gchar*)(iter->data);
457                         if (account_name) {
458                         TnyTransportAccount *account = TNY_TRANSPORT_ACCOUNT (
459                                 modest_tny_account_store_get_transport_account_for_open_connection
460                                                  (modest_runtime_get_account_store(), account_name));
461                         if (account) {
462                                 printf ("debug: %s:\n  Transport account for %s: %s\n", __FUNCTION__, account_name, 
463                                         tny_account_get_id(TNY_ACCOUNT(account)));
464                                 modest_runtime_get_send_queue (account);
465                         }
466                 }
467                 
468                 iter = g_slist_next (iter);
469         }
470         
471         g_slist_free (account_names);
472         
473         
474         modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (self));
475 }
476
477 static void
478 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
479 {
480         g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
481
482         /* Update dimmed */     
483         modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");  
484 }
485
486 static void
487 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
488 {
489         g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
490
491         /* Update visibility */
492
493         /* Update dimmed */     
494         modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");  
495 }
496
497 static void
498 connect_signals (ModestMainWindow *self)
499 {       
500         ModestWindowPrivate *parent_priv;
501         ModestMainWindowPrivate *priv;
502         GtkWidget *menu;
503         
504         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
505         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
506
507         /* folder view */
508         g_signal_connect (G_OBJECT(priv->folder_view), "key-press-event",
509                           G_CALLBACK(on_inner_widgets_key_pressed), self);
510         g_signal_connect (G_OBJECT(priv->folder_view), "folder_selection_changed",
511                           G_CALLBACK(modest_ui_actions_on_folder_selection_changed), self);
512         g_signal_connect (G_OBJECT(priv->folder_view), "folder-display-name-changed",
513                           G_CALLBACK(modest_ui_actions_on_folder_display_name_changed), self);
514
515         /* Folder view CSM */
516         menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
517         gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
518         g_signal_connect (G_OBJECT(priv->folder_view), "tap-and-hold",
519                           G_CALLBACK(_folder_view_csm_menu_activated),
520                           self);
521         /* header view */
522         g_signal_connect (G_OBJECT(priv->header_view), "header_selected",
523                           G_CALLBACK(modest_ui_actions_on_header_selected), self);
524         g_signal_connect (G_OBJECT(priv->header_view), "header_activated",
525                           G_CALLBACK(modest_ui_actions_on_header_activated), self);
526         g_signal_connect (G_OBJECT(priv->header_view), "item_not_found",
527                           G_CALLBACK(modest_ui_actions_on_item_not_found), self);
528         g_signal_connect (G_OBJECT(priv->header_view), "key-press-event",
529                           G_CALLBACK(on_inner_widgets_key_pressed), self);
530         g_signal_connect (G_OBJECT(priv->header_view), "msg_count_changed",
531                           G_CALLBACK(_on_msg_count_changed), self);
532
533         /* Header view CSM */
534         menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
535         gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
536         g_signal_connect (G_OBJECT(priv->header_view), "tap-and-hold",
537                           G_CALLBACK(_header_view_csm_menu_activated),
538                           self);
539         
540         /* window */
541         g_signal_connect (G_OBJECT(self), "delete-event", G_CALLBACK(on_delete_event), self);
542         g_signal_connect (G_OBJECT (self), "window-state-event",
543                           G_CALLBACK (modest_main_window_window_state_event),
544                           NULL);
545         g_signal_connect (G_OBJECT(self), "delete-event", G_CALLBACK(on_delete_event), self);
546         
547         /* Mail Operation Queue */
548         priv->queue_changed_handler_uid = 
549                 g_signal_connect (G_OBJECT (modest_runtime_get_mail_operation_queue ()),
550                                   "queue-changed", G_CALLBACK (on_queue_changed), self);
551
552         /* Track changes in the device name */
553         g_signal_connect (G_OBJECT(modest_runtime_get_conf ()),
554                           "key_changed", G_CALLBACK (on_configuration_key_changed), 
555                           self);
556
557         /* Track account changes. We need to refresh the toolbar */
558         g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
559                           "account_update", G_CALLBACK (on_account_update),
560                           self);
561
562         /* Account store */
563         g_signal_connect (G_OBJECT (modest_runtime_get_account_store()), 
564                           "password_requested",
565                           G_CALLBACK (modest_ui_actions_on_password_requested), self);
566                           
567         /* Device */
568         g_signal_connect (G_OBJECT(modest_runtime_get_account_store()), 
569                           "connecting-finished",
570                           G_CALLBACK(on_account_store_connecting_finished), self);
571 }
572
573 #if 0
574 /** Idle handler, to send/receive at startup .*/
575 gboolean
576 sync_accounts_cb (ModestMainWindow *win)
577 {
578         modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (win));
579         return FALSE; /* Do not call this idle handler again. */
580 }
581 #endif
582
583 static void on_hildon_program_is_topmost_notify(GObject *self,
584         GParamSpec *propert_param, gpointer user_data)
585 {
586         HildonProgram *app = HILDON_PROGRAM (self);
587         
588         /*
589         ModestWindow* self = MODEST_WINDOW(user_data);
590         */
591         
592         /* Note that use of hildon_program_set_can_hibernate() 
593          * is generally referred to as "setting the killable flag", 
594          * though hibernation does not seem equal to death.
595          * murrayc */
596                  
597         if (hildon_program_get_is_topmost (app)) {
598                 /* Prevent hibernation when the progam comes to the foreground,
599                  * because hibernation should only happen when the application 
600                  * is in the background: */
601                 hildon_program_set_can_hibernate (app, FALSE);
602         } else {
603                 /* Allow hibernation if the program has gone to the background: */
604                 
605                 /* However, prevent hibernation while the settings are being changed: */
606                 const gboolean hibernation_prevented = 
607                         modest_window_mgr_get_hibernation_is_prevented (
608         modest_runtime_get_window_mgr ()); 
609         
610                 if (hibernation_prevented)
611                         hildon_program_set_can_hibernate (app, FALSE);
612                 else {
613                         /* Allow hibernation, after saving the state: */
614                         modest_osso_save_state();
615                         hildon_program_set_can_hibernate (app, TRUE);
616                 }
617         }
618         
619 }
620
621 static void
622 modest_main_window_on_show (GtkWidget *self, gpointer user_data)
623 {
624         GtkWidget *folder_win = (GtkWidget *) user_data;
625         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
626         
627         priv->folder_view = MODEST_FOLDER_VIEW(modest_folder_view_new (NULL));
628         if (!priv->folder_view)
629                 g_printerr ("modest: cannot instantiate folder view\n");
630
631         gtk_widget_show (GTK_WIDGET (priv->folder_view));
632
633         /* Connect signals */
634         connect_signals ((ModestMainWindow*)self);
635
636         modest_folder_view_set_style (priv->folder_view,
637                       MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
638
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         /* Check if accounts exist and show the account wizard if not */
646         gboolean accounts_exist = 
647                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
648
649         
650         if (!accounts_exist)
651         {
652                 /* This is necessary to have the main window shown behind the dialog 
653                 It's an ugly hack... jschmid */
654                 gtk_widget_show_all(GTK_WIDGET(self));
655                 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
656         }
657
658         wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
659         wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET(priv->header_view));
660
661         /* Load previous osso state, for instance if we are being restored from 
662          * hibernation:  */
663         modest_osso_load_state();
664
665         /* Restore window & widget settings */
666
667         restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
668 }
669
670 ModestWindow*
671 modest_main_window_new (void)
672 {
673         ModestMainWindow *self = NULL;  
674         ModestMainWindowPrivate *priv = NULL;
675         ModestWindowPrivate *parent_priv = NULL;
676         GtkWidget *folder_win = NULL;
677         ModestDimmingRulesGroup *menu_rules_group = NULL;
678         ModestDimmingRulesGroup *toolbar_rules_group = NULL;
679         GtkActionGroup *action_group = NULL;
680         GError *error = NULL;
681         GdkPixbuf *window_icon = NULL; 
682         ModestConf *conf = NULL;
683         GtkAction *action = NULL;
684
685         self  = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
686         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
687         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
688
689         parent_priv->ui_manager = gtk_ui_manager_new();
690         parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
691
692         action_group = gtk_action_group_new ("ModestMainWindowActions");
693         gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
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         gboolean folder_empty = FALSE;
1456         TnyFolderChangeChanged changed;
1457         
1458         g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1459         g_return_if_fail (TNY_IS_FOLDER(folder));
1460         g_return_if_fail (TNY_IS_FOLDER_CHANGE(change));
1461         
1462         changed = tny_folder_change_get_changed (change);
1463         
1464         /* If something changes */
1465         if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1466                 folder_empty = (tny_folder_change_get_new_all_count (change) == 0);     
1467         else
1468                 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1469         
1470         /* Set contents style of headers view */
1471         if (folder_empty)  {
1472                 modest_main_window_set_contents_style (main_window,
1473                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1474         }
1475         else {
1476                 modest_main_window_set_contents_style (main_window,
1477                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1478         }
1479         
1480 }
1481
1482 void 
1483 modest_main_window_set_contents_style (ModestMainWindow *self, 
1484                                        ModestMainWindowContentsStyle style)
1485 {
1486         ModestMainWindowPrivate *priv;
1487
1488         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1489
1490         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1491
1492         /* We allow to set the same content style than the previously
1493            set if there are details, because it could happen when we're
1494            selecting different accounts consecutively */
1495         if ((priv->contents_style == style) &&
1496             (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1497                 return;
1498
1499         /* Remove previous child. Delete it if it was an account
1500            details widget */
1501         GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1502         if (content) {
1503                 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1504                         g_object_ref (content);
1505                 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1506                         g_object_ref (priv->empty_view);
1507                         gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1508                 }
1509                 
1510                 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1511         }
1512
1513         priv->contents_style = style;
1514
1515         switch (priv->contents_style) {
1516         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1517                 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1518                 break;
1519         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1520         {
1521                 /* TODO: show here account details */
1522                 TnyFolderStore *selected_folderstore = 
1523                         modest_folder_view_get_selected (priv->folder_view);
1524                 if (TNY_IS_ACCOUNT (selected_folderstore)) {    
1525                         priv->details_widget = create_details_widget (
1526                                 TNY_ACCOUNT (selected_folderstore));
1527
1528                         wrap_in_scrolled_window (priv->contents_widget, 
1529                                          priv->details_widget);
1530                 }
1531                 break;
1532         }
1533         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1534                 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1535                 break;
1536         default:
1537                 g_return_if_reached ();
1538         }
1539
1540         /* Show */
1541         gtk_widget_show_all (priv->contents_widget);
1542 }
1543
1544 static void 
1545 on_configuration_key_changed (ModestConf* conf, 
1546                               const gchar *key, 
1547                               ModestConfEvent event, 
1548                               ModestMainWindow *self)
1549 {
1550         ModestMainWindowPrivate *priv;
1551         TnyAccount *account;
1552
1553         if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
1554                 return;
1555
1556         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1557
1558         if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1559                 return;
1560
1561         account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1562         if (TNY_IS_ACCOUNT (account) &&
1563             !strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1564                 GList *children;
1565                 GtkLabel *label;
1566                 const gchar *device_name;
1567                 gchar *new_text;
1568                 
1569                 /* Get label */
1570                 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1571                 label = GTK_LABEL (children->data);
1572                 
1573                 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1574                                                       MODEST_CONF_DEVICE_NAME, NULL);
1575                 
1576                 new_text = g_strdup_printf ("%s: %s",
1577                                             _("mcen_fi_localroot_description"),
1578                                             device_name);
1579                 
1580                 gtk_label_set_text (label, new_text);
1581                 gtk_widget_show (GTK_WIDGET (label));
1582                 
1583                 g_free (new_text);
1584                 g_list_free (children);
1585         }
1586 }
1587
1588 static gboolean
1589 set_toolbar_transfer_mode (ModestMainWindow *self)
1590 {
1591         ModestMainWindowPrivate *priv = NULL;
1592         
1593         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1594
1595         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1596
1597         set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1598         
1599         if (priv->progress_bar_timeout > 0) {
1600                 g_source_remove (priv->progress_bar_timeout);
1601                 priv->progress_bar_timeout = 0;
1602         }
1603
1604         return FALSE;
1605 }
1606
1607 static void 
1608 set_toolbar_mode (ModestMainWindow *self, 
1609                   ModestToolBarModes mode)
1610 {
1611         ModestWindowPrivate *parent_priv = NULL;
1612         ModestMainWindowPrivate *priv = NULL;
1613         GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1614         
1615         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1616
1617         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1618         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1619
1620         g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar)); 
1621         
1622         sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1623         refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1624         cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1625
1626         /* Sets current toolbar mode */
1627         priv->current_toolbar_mode = mode;
1628
1629         /* Show and hide toolbar items */
1630         switch (mode) {
1631         case TOOLBAR_MODE_NORMAL:
1632                 if (sort_action) 
1633                         gtk_action_set_visible (sort_action, TRUE);
1634                 if (refresh_action) 
1635                         gtk_action_set_visible (refresh_action, TRUE);
1636                 if (priv->progress_toolitem) {
1637                         gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1638                         gtk_widget_hide (priv->progress_toolitem);
1639                 }
1640                 if (priv->progress_bar)
1641                         gtk_widget_hide (priv->progress_bar);                   
1642                 
1643                 if (cancel_action)
1644                         gtk_action_set_visible (cancel_action, FALSE);
1645
1646                 /* Hide toolbar if optimized view is enabled */
1647                 if (priv->optimized_view)
1648                         gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
1649                 break;
1650         case TOOLBAR_MODE_TRANSFER:
1651                 if (sort_action)
1652                         gtk_action_set_visible (sort_action, FALSE);
1653                 if (refresh_action)
1654                         gtk_action_set_visible (refresh_action, FALSE);
1655                 if (cancel_action)
1656                         gtk_action_set_visible (cancel_action, TRUE);
1657                 if (priv->progress_toolitem) {
1658                         gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1659                         gtk_widget_show (priv->progress_toolitem);
1660                 }
1661                 if (priv->progress_bar)
1662                         gtk_widget_show (priv->progress_bar);                   
1663
1664                 /* Show toolbar if it's hiden (optimized view ) */
1665                 if (priv->optimized_view)
1666                         gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1667                 break;
1668         default:
1669                 g_return_if_reached ();
1670         }
1671 }
1672
1673 static void
1674 cancel_progressbar (GtkToolButton *toolbutton,
1675                     ModestMainWindow *self)
1676 {
1677         GSList *tmp;
1678         ModestMainWindowPrivate *priv;
1679         
1680         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1681
1682         /* Get operation observers and cancel its current operation */
1683         tmp = priv->progress_widgets;
1684         while (tmp) {
1685                 modest_progress_object_cancel_current_operation (MODEST_PROGRESS_OBJECT(tmp->data));
1686                 tmp=g_slist_next(tmp);
1687         }
1688 }
1689
1690 static gboolean
1691 observers_empty (ModestMainWindow *self)
1692 {
1693         GSList *tmp = NULL;
1694         ModestMainWindowPrivate *priv;
1695         gboolean is_empty = TRUE;
1696         guint pending_ops = 0;
1697  
1698         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1699         tmp = priv->progress_widgets;
1700
1701         /* Check all observers */
1702         while (tmp && is_empty)  {
1703                 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
1704                 is_empty = pending_ops == 0;
1705                 
1706                 tmp = g_slist_next(tmp);
1707         }
1708         
1709         return is_empty;
1710 }
1711
1712 static void
1713 on_queue_changed (ModestMailOperationQueue *queue,
1714                   ModestMailOperation *mail_op,
1715                   ModestMailOperationQueueNotification type,
1716                   ModestMainWindow *self)
1717 {
1718         ModestMainWindowPrivate *priv;
1719         ModestMailOperationTypeOperation op_type;
1720         ModestToolBarModes mode;
1721         GSList *tmp;
1722         gboolean mode_changed = FALSE;
1723 /*      ModestMailOperationStatus status; */
1724
1725         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1726         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1727                
1728         /* Get toolbar mode from operation id*/
1729         op_type = modest_mail_operation_get_type_operation (mail_op);
1730         switch (op_type) {
1731         case MODEST_MAIL_OPERATION_TYPE_SEND:
1732         case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
1733                 mode = TOOLBAR_MODE_TRANSFER;
1734                 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
1735                         mode_changed = TRUE;
1736                 break;
1737         default:
1738                 mode = TOOLBAR_MODE_NORMAL;
1739                 
1740         }
1741                 
1742                        
1743         /* Add operation observers and change toolbar if neccessary*/
1744         tmp = priv->progress_widgets;
1745         switch (type) {
1746         case MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED:
1747                 if (mode == TOOLBAR_MODE_TRANSFER) {
1748                         if (mode_changed)
1749                                 set_toolbar_transfer_mode(self);                    
1750                         while (tmp) {
1751                                 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
1752                                                                       mail_op);
1753                                 tmp = g_slist_next (tmp);
1754                         }
1755                 }
1756                 break;
1757         case MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED:
1758                 /* Change toolbar mode */
1759                 if (mode == TOOLBAR_MODE_TRANSFER) {                    
1760                         while (tmp) {
1761                                 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
1762                                                                          mail_op);
1763                                 tmp = g_slist_next (tmp);
1764                         }
1765                         
1766                         /* If no more operations are being observed, NORMAL mode is enabled again */
1767                         if (observers_empty (self)) {
1768                                 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
1769                                 
1770                         }
1771                 }
1772
1773                 break;
1774         }       
1775
1776 }
1777
1778 static void 
1779 on_show_account_action_activated  (GtkAction *action,
1780                                    gpointer user_data)
1781 {
1782         ModestAccountData *acc_data;
1783         ModestMainWindow *self;
1784         ModestMainWindowPrivate *priv;
1785         ModestAccountMgr *mgr;
1786         const gchar *acc_name;
1787
1788         self = MODEST_MAIN_WINDOW (user_data);
1789         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1790
1791         /* Get account data */
1792         acc_name = gtk_action_get_name (action);
1793         mgr = modest_runtime_get_account_mgr ();
1794         acc_data = modest_account_mgr_get_account_data (mgr, acc_name);
1795
1796         /* Set the new visible & active account */
1797         if (acc_data->store_account) { 
1798                 modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view,
1799                                                                              acc_data->store_account->account_name);
1800                 modest_window_set_active_account (MODEST_WINDOW (self), acc_data->account_name);
1801         }
1802
1803         /* Free */
1804         modest_account_mgr_free_account_data (mgr, acc_data);
1805 }
1806
1807 static void
1808 refresh_account (const gchar *account_name)
1809 {
1810         ModestWindow *win;
1811
1812         win = MODEST_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
1813
1814         /* If account_name == NULL, we must update all (option All) */
1815         if (!account_name)
1816                 modest_ui_actions_do_send_receive_all (win);
1817         else
1818                 modest_ui_actions_do_send_receive (account_name, win);
1819 }
1820
1821 static void 
1822 on_refresh_account_action_activated  (GtkAction *action,
1823                                       gpointer user_data)
1824 {
1825         refresh_account ((const gchar*) user_data);
1826 }
1827
1828 static void
1829 on_send_receive_csm_activated (GtkMenuItem *item,
1830                                gpointer user_data)
1831 {
1832         refresh_account ((const gchar*) user_data);
1833 }