280b946740887a2dd98d8a8baade6f7625a4a3db
[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  = -1; /* invalid contents style. We need this to select it for the first time */
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         wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
635 /*      wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET(priv->header_view)); */
636
637         gtk_widget_show (GTK_WIDGET (priv->folder_view));
638
639         /* Connect signals */
640         connect_signals ((ModestMainWindow*)self);
641
642         /* Set account store */
643         tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
644                                                   TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
645
646         /* Load previous osso state, for instance if we are being restored from 
647          * hibernation:  */
648         modest_osso_load_state ();
649
650         /* Restore window & widget settings */
651         
652         restore_settings (MODEST_MAIN_WINDOW(self), TRUE);
653
654         /* Check if accounts exist and show the account wizard if not */
655         gboolean accounts_exist = 
656                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
657
658         if (!accounts_exist) {
659                 /* This is necessary to have the main window shown behind the dialog 
660                 It's an ugly hack... jschmid */
661                 gtk_widget_show_all(GTK_WIDGET(self));
662                 modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self));
663         }
664 }
665
666 /* Debugging */
667 /* static void  */
668 /* on_window_destroy (ModestWindow *window,  */
669 /*                 ModestWindowMgr *self) */
670 /* { */
671 /*      ModestMainWindow *mw = NULL;     */
672 /*      ModestMainWindowPrivate *priv = NULL; */
673
674 /*      mw  = MODEST_MAIN_WINDOW (window); */
675 /*      priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self); */
676
677 /*      g_print ("\tMW: %d\n", ((GObject*)mw)->ref_count); */
678 /*      g_print ("\tHV: %d\n", ((GObject*)priv->header_view)->ref_count); */
679 /*      g_print ("\tFV: %d\n", ((GObject*)priv->folder_view)->ref_count); */
680 /* } */
681
682 ModestWindow *
683 modest_main_window_new (void)
684 {
685         ModestMainWindow *self = NULL;  
686         ModestMainWindowPrivate *priv = NULL;
687         ModestWindowPrivate *parent_priv = NULL;
688         GtkWidget *folder_win = NULL;
689         ModestDimmingRulesGroup *menu_rules_group = NULL;
690         ModestDimmingRulesGroup *toolbar_rules_group = NULL;
691         GtkActionGroup *action_group = NULL;
692         GError *error = NULL;
693         GdkPixbuf *window_icon = NULL; 
694         ModestConf *conf = NULL;
695         GtkAction *action = NULL;
696
697         self  = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
698         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
699         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
700
701         parent_priv->ui_manager = gtk_ui_manager_new();
702         parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
703
704         action_group = gtk_action_group_new ("ModestMainWindowActions");
705         gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
706         gtk_action_group_set_translate_func (action_group, (GtkTranslateFunc) translate_func, GETTEXT_PACKAGE, g_free);
707
708         menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules");
709         toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules");
710
711         /* Add common actions */
712         gtk_action_group_add_actions (action_group,
713                                       modest_action_entries,
714                                       G_N_ELEMENTS (modest_action_entries),
715                                       self);
716
717         gtk_action_group_add_actions (action_group,
718                                       modest_folder_view_action_entries,
719                                       G_N_ELEMENTS (modest_folder_view_action_entries),
720                                       self);
721
722         gtk_action_group_add_actions (action_group,
723                                       modest_header_view_action_entries,
724                                       G_N_ELEMENTS (modest_header_view_action_entries),
725                                       self);
726
727         gtk_action_group_add_toggle_actions (action_group,
728                                              modest_toggle_action_entries,
729                                              G_N_ELEMENTS (modest_toggle_action_entries),
730                                              self);
731
732         gtk_action_group_add_toggle_actions (action_group,
733                                              modest_main_window_toggle_action_entries,
734                                              G_N_ELEMENTS (modest_main_window_toggle_action_entries),
735                                              self);
736
737         gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
738         g_object_unref (action_group);
739
740         /* Load the UI definition */
741         gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
742                                          MODEST_UIDIR "modest-main-window-ui.xml", &error);
743         if (error != NULL) {
744                 g_warning ("Could not merge modest-ui.xml: %s", error->message);
745                 g_error_free (error);
746                 error = NULL;
747         }
748
749         /* Add common dimming rules */
750         modest_dimming_rules_group_add_rules (menu_rules_group, 
751                                               modest_main_window_menu_dimming_entries,
752                                               G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
753                                               self);
754         modest_dimming_rules_group_add_rules (toolbar_rules_group, 
755                                               modest_main_window_toolbar_dimming_entries,
756                                               G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
757                                               self);
758
759         /* Insert dimming rules group for this window */
760         modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
761         modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
762         g_object_unref (menu_rules_group);
763         g_object_unref (toolbar_rules_group);
764         
765         /* Add accelerators */
766         gtk_window_add_accel_group (GTK_WINDOW (self), 
767                                     gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
768
769         /* Menubar. Update the state of some toggles */
770         parent_priv->menubar = modest_maemo_utils_menubar_to_menu (parent_priv->ui_manager);
771         conf = modest_runtime_get_conf ();
772         action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
773                                             "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
774         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
775                                       modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR, NULL));
776         action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
777                                             "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
778         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
779                                       modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR_FULLSCREEN, NULL));
780         hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
781
782         /* Get device name */
783         modest_maemo_utils_get_device_name ();
784
785         /* header view */
786         priv->header_view =
787                 MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
788         if (!priv->header_view)
789                 g_printerr ("modest: cannot instantiate header view\n");
790         modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
791         modest_widget_memory_restore (modest_runtime_get_conf (), G_OBJECT(priv->header_view),
792                                       MODEST_CONF_HEADER_VIEW_KEY);
793
794         /* Empty view */ 
795         priv->empty_view = create_empty_view ();
796                  
797         /* Create scrolled windows */
798         folder_win = gtk_scrolled_window_new (NULL, NULL);
799         priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
800         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
801                                         GTK_POLICY_NEVER,
802                                         GTK_POLICY_AUTOMATIC);
803         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
804                                         GTK_POLICY_NEVER,
805                                         GTK_POLICY_AUTOMATIC);
806
807         /* paned */
808         priv->main_paned = gtk_hpaned_new ();
809         gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
810         gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
811         gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
812
813         /* putting it all together... */
814         priv->main_vbox = gtk_vbox_new (FALSE, 6);
815         gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
816
817         gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
818
819         /* Set window icon */
820         window_icon = modest_platform_get_icon (MODEST_APP_ICON);
821         gtk_window_set_icon (GTK_WINDOW (self), window_icon);
822         
823         HildonProgram *app = hildon_program_get_instance ();
824         hildon_program_add_window (app, HILDON_WINDOW (self));
825         
826         g_signal_connect (G_OBJECT(app), "notify::is-topmost",
827                 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
828
829         g_signal_connect (G_OBJECT(self), "show",
830                           G_CALLBACK (modest_main_window_on_show), folder_win);
831                 
832
833         restore_settings (MODEST_MAIN_WINDOW(self), FALSE);
834
835 /*      { */
836 /*              g_signal_connect (self, "destroy",  */
837 /*                                G_CALLBACK (on_window_destroy), self); */
838 /*      } */
839
840         return MODEST_WINDOW(self);
841 }
842
843 gboolean 
844 modest_main_window_close_all (ModestMainWindow *self)
845 {
846         GtkWidget *note;
847         GtkResponseType response;
848
849         /* Create the confirmation dialog MSG-NOT308 */
850         note = hildon_note_new_confirmation_add_buttons (GTK_WINDOW (self),
851                                                          _("emev_nc_close_windows"),
852                                                          _("mcen_bd_yes"), GTK_RESPONSE_YES,
853                                                          _("mcen_bd_no"), GTK_RESPONSE_NO,
854                                                          NULL);
855
856         response = gtk_dialog_run (GTK_DIALOG (note));
857         gtk_widget_destroy (GTK_WIDGET (note));
858
859         if (response == GTK_RESPONSE_YES)
860                 return TRUE;
861         else
862                 return FALSE;
863 }
864
865
866 void 
867 modest_main_window_set_style (ModestMainWindow *self, 
868                               ModestMainWindowStyle style)
869 {
870         ModestMainWindowPrivate *priv;
871         ModestWindowPrivate *parent_priv;
872         GtkAction *action;
873
874         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
875
876         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
877         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
878
879         /* no change -> nothing to do */
880         if (priv->style == style)
881                 return;
882
883         /* Get toggle button */
884         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarToggleView");
885
886         priv->style = style;
887         switch (style) {
888         case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
889                 /* Remove main paned */
890                 g_object_ref (priv->main_paned);
891                 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
892
893                 /* Reparent the contents widget to the main vbox */
894                 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
895
896                 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
897                 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
898                 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
899
900                 break;
901         case MODEST_MAIN_WINDOW_STYLE_SPLIT:
902                 /* Remove header view */
903                 g_object_ref (priv->contents_widget);
904                 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
905
906                 /* Reparent the main paned */
907                 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
908                 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
909
910                 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
911                 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), FALSE);
912                 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
913
914                 break;
915         default:
916                 g_return_if_reached ();
917         }
918
919         /* Let header view grab the focus if it's being shown */
920         if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
921                 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
922         else 
923                 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
924
925         /* Show changes */
926         gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
927 }
928
929 ModestMainWindowStyle
930 modest_main_window_get_style (ModestMainWindow *self)
931 {
932         ModestMainWindowPrivate *priv;
933
934         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
935
936         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
937         return priv->style;
938 }
939
940
941
942 static gboolean
943 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
944 {
945         if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
946                 ModestWindowPrivate *parent_priv;
947                 ModestWindowMgr *mgr;
948                 gboolean is_fullscreen;
949                 GtkAction *fs_toggle_action;
950                 gboolean active;
951                 
952                 mgr = modest_runtime_get_window_mgr ();
953                 
954                 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
955
956                 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
957                 
958                 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
959                 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
960                 if (is_fullscreen != active) {
961                         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
962                 }
963         }
964
965         return FALSE;
966
967 }
968
969 static void
970 set_homogeneous (GtkWidget *widget,
971                  gpointer data)
972 {
973         gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
974         gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
975 }
976
977 static void 
978 modest_main_window_show_toolbar (ModestWindow *self,
979                                  gboolean show_toolbar)
980 {
981         ModestMainWindowPrivate *priv = NULL;
982         ModestWindowPrivate *parent_priv = NULL;        
983         GtkWidget *reply_button = NULL, *menu = NULL;
984         GtkWidget *placeholder = NULL;
985         gint insert_index;
986
987         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
988         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
989         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
990
991         /* Set optimized view status */
992         priv->optimized_view = !show_toolbar;
993
994         if (!parent_priv->toolbar) {
995                 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, 
996                                                                   "/ToolBar");
997
998                 /* Set homogeneous toolbar */
999                 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar), 
1000                                        set_homogeneous, NULL);
1001         
1002                 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1003                 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1004                 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1005                 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1006                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1007                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1008                 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1009                 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1010
1011                 /* Add ProgressBar (Transfer toolbar) */ 
1012                 priv->progress_bar = modest_progress_bar_widget_new ();
1013                 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1014                 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
1015                 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1016                 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1017                 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1018                 
1019                 /* Connect cancel 'clicked' signal to abort progress mode */
1020                 g_signal_connect(priv->cancel_toolitem, "clicked",
1021                                  G_CALLBACK(cancel_progressbar),
1022                                  self);
1023                 
1024                 /* Add it to the observers list */
1025                 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1026
1027                 /* Add to window */
1028                 hildon_window_add_toolbar (HILDON_WINDOW (self), 
1029                                            GTK_TOOLBAR (parent_priv->toolbar));
1030
1031                 /* Set reply button tap and hold menu */
1032                 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager, 
1033                                                           "/ToolBar/ToolbarMessageReply");
1034                 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1035                                                   "/ToolbarReplyCSM");
1036                 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1037
1038                 /* Set send & receive button tap and hold menu */
1039                 on_account_update (TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()),
1040                                    NULL, self);
1041         }
1042
1043         if (show_toolbar) {
1044                 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */ 
1045                 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1046                 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1047
1048                 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1049                 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1050         } else
1051                 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1052
1053 }
1054
1055 static gint
1056 compare_display_names (ModestAccountData *a,
1057                        ModestAccountData *b)
1058 {
1059         return strcmp (a->display_name, b->display_name);
1060 }
1061
1062 static void 
1063 on_account_update (TnyAccountStore *account_store, 
1064                    const gchar *account_name,
1065                    gpointer user_data)
1066 {
1067         GSList *account_names, *iter, *accounts;
1068         ModestMainWindow *self;
1069         ModestMainWindowPrivate *priv;
1070         ModestWindowPrivate *parent_priv;
1071         ModestAccountMgr *mgr;
1072         gint i, num_accounts;                                   
1073         GtkActionGroup *action_group;
1074         GList *groups;
1075         gchar *default_account;
1076         GtkWidget *send_receive_button, *item;
1077                 
1078         self = MODEST_MAIN_WINDOW (user_data);
1079         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
1080         parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1081
1082         /* Get enabled account IDs */
1083         mgr = modest_runtime_get_account_mgr ();
1084         account_names = modest_account_mgr_account_names (mgr, TRUE);
1085         iter = account_names;
1086         accounts = NULL;
1087
1088         while (iter) {
1089                 ModestAccountData *account_data = 
1090                         modest_account_mgr_get_account_data (mgr, (gchar*) iter->data);
1091                 accounts = g_slist_prepend (accounts, account_data);
1092
1093                 iter = iter->next;
1094         }
1095         g_slist_free (account_names);
1096
1097         /* Order the list of accounts by its display name */
1098         accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
1099         num_accounts = g_slist_length (accounts);
1100
1101         /* Delete old send&receive popup items. We can not just do a
1102            menu_detach because it does not work well with
1103            tap_and_hold */
1104         if (priv->accounts_popup)
1105                 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup), 
1106                                        (GtkCallback) gtk_widget_destroy, NULL);
1107
1108         /* Delete old entries in the View menu. Do not free groups, it
1109            belongs to Gtk+ */
1110         groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
1111         while (groups) {
1112                 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
1113                              gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
1114                         gtk_ui_manager_remove_action_group (parent_priv->ui_manager, 
1115                                                             GTK_ACTION_GROUP (groups->data));
1116                         groups = NULL;
1117                         /* Remove uis */
1118                         if (priv->merge_ids) {
1119                                 for (i = 0; i < priv->merge_ids->len; i++)
1120                                         gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
1121                                 g_byte_array_free (priv->merge_ids, TRUE);
1122                         }
1123                         /* We need to call this in order to ensure
1124                            that the new actions are added in the right
1125                            order (alphabetical */
1126                         gtk_ui_manager_ensure_update (parent_priv->ui_manager);
1127                 } else 
1128                         groups = g_list_next (groups);
1129         }
1130         priv->merge_ids = g_byte_array_sized_new (num_accounts);
1131
1132         /* Get send receive button */
1133         send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1134                                                           "/ToolBar/ToolbarSendReceive");
1135
1136         /* Create the menu */
1137         if (num_accounts > 1) {
1138                 if (!priv->accounts_popup)
1139                         priv->accounts_popup = gtk_menu_new ();
1140                 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
1141                 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1142                 g_signal_connect (G_OBJECT (item), 
1143                                   "activate", 
1144                                   G_CALLBACK (on_send_receive_csm_activated),
1145                                   NULL);
1146                 item = gtk_separator_menu_item_new ();
1147                 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1148         }
1149
1150         /* Create a new action group */
1151         default_account = modest_account_mgr_get_default_account (mgr);
1152         action_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
1153         for (i = 0; i < num_accounts; i++) {
1154                 gchar *display_name = NULL;
1155                 
1156                 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
1157
1158                 /* Create display name. The default account is shown differently */
1159                 if (default_account && account_data->account_name && 
1160                         !(strcmp (default_account, account_data->account_name) == 0)) {
1161                         display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"), 
1162                                                         account_data->display_name);
1163                 }
1164                 else {
1165                         display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"), 
1166                                                         account_data->display_name);
1167                 }
1168
1169                 /* Create action and add it to the action group. The
1170                    action name must be the account name, this way we
1171                    could know in the handlers the account to show */
1172                 if(account_data->account_name) {
1173                         gchar* item_name, *refresh_action_name;
1174                         guint8 merge_id;
1175                         GtkAction *view_account_action, *refresh_account_action;
1176
1177                         view_account_action = gtk_action_new (account_data->account_name,
1178                                                               display_name, NULL, NULL);
1179                         gtk_action_group_add_action (action_group, view_account_action);
1180
1181                         /* Add ui from account data. We allow 2^9-1 account
1182                            changes in a single execution because we're
1183                            downcasting the guint to a guint8 in order to use a
1184                            GByteArray, it should be enough */
1185                         item_name = g_strconcat (account_data->account_name, "Menu", NULL);
1186                         merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
1187                         priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
1188                         gtk_ui_manager_add_ui (parent_priv->ui_manager,
1189                                                merge_id,
1190                                                "/MenuBar/ViewMenu/ViewMenuAdditions",
1191                                                item_name,
1192                                                account_data->account_name,
1193                                                GTK_UI_MANAGER_MENUITEM,
1194                                                FALSE);
1195         
1196                         /* Connect the action signal "activate" */
1197                         g_signal_connect (G_OBJECT (view_account_action),
1198                                           "activate",
1199                                           G_CALLBACK (on_show_account_action_activated),
1200                                           self);
1201
1202                         /* Create the items for the Tools->Send&Receive submenu */
1203                         refresh_action_name = g_strconcat ("SendReceive", account_data->account_name, NULL);
1204                         refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name, 
1205                                                                  display_name, NULL, NULL);
1206                         gtk_action_group_add_action (action_group, refresh_account_action);
1207
1208                         merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
1209                         priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
1210                         gtk_ui_manager_add_ui (parent_priv->ui_manager, 
1211                                                merge_id,
1212                                                "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
1213                                                item_name,
1214                                                refresh_action_name,
1215                                                GTK_UI_MANAGER_MENUITEM,
1216                                                FALSE);
1217                         g_free (refresh_action_name);
1218
1219                         g_signal_connect_data (G_OBJECT (refresh_account_action), 
1220                                                "activate", 
1221                                                G_CALLBACK (on_refresh_account_action_activated), 
1222                                                g_strdup (account_data->account_name),
1223                                                (GClosureNotify) g_free,
1224                                                0);
1225
1226                         /* Create item and add it to the send&receive
1227                            CSM. If there is only one account then
1228                            it'll be no menu */
1229                         if (priv->accounts_popup) {
1230                                 item = gtk_menu_item_new_with_label (display_name);
1231                                 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1232                                 g_signal_connect_data (G_OBJECT (item), 
1233                                                        "activate", 
1234                                                        G_CALLBACK (on_send_receive_csm_activated),
1235                                                        g_strdup (account_data->account_name),
1236                                                        (GClosureNotify) g_free,
1237                                                        0);
1238                         }
1239                         g_free (item_name);
1240                 }
1241
1242                 /* Frees */
1243                 g_free (display_name);
1244                 modest_account_mgr_free_account_data (mgr, account_data);
1245         }
1246         gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 1);
1247
1248         if (priv->accounts_popup) {
1249                 /* Mandatory in order to view the menu contents */
1250                 gtk_widget_show_all (priv->accounts_popup);
1251
1252                 /* Setup tap_and_hold just if was not done before*/
1253                 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
1254                         gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
1255         }
1256
1257         /* Frees */
1258         g_slist_free (accounts);
1259         g_free (default_account);
1260 }
1261
1262 /* 
1263  * This function manages the key events used to navigate between
1264  * header and folder views (when the window is in split view)
1265  *
1266  * FROM         KEY        ACTION
1267  * -------------------------------------------------
1268  * HeaderView   GDK_Left   Move focus to folder view
1269  * FolderView   GDK_Right  Move focus to header view
1270  *
1271  * There is no need to scroll to selected row, the widgets will be the
1272  * responsibles of doing that (probably managing the focus-in event
1273  */
1274 static gboolean 
1275 on_inner_widgets_key_pressed (GtkWidget *widget,
1276                               GdkEventKey *event,
1277                               gpointer user_data)
1278 {
1279         ModestMainWindowPrivate *priv;
1280
1281         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1282
1283         /* Do nothing if we're in SIMPLE style */
1284         if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1285                 return FALSE;
1286
1287         if (MODEST_IS_HEADER_VIEW (widget) && event->keyval == GDK_Left)
1288                 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1289         else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1290                 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1291
1292         return FALSE;
1293 }
1294
1295 static void
1296 set_alignment (GtkWidget *widget,
1297                gpointer data)
1298 {
1299         gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1300         gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1301 }
1302
1303 static GtkWidget *
1304 create_empty_view (void)
1305 {
1306         GtkLabel *label = NULL;
1307         GtkWidget *align = NULL;
1308
1309         align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1310         label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1311         gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);      
1312         gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1313
1314         return GTK_WIDGET(align);
1315 }
1316
1317 static GtkWidget *
1318 create_details_widget (TnyAccount *account)
1319 {
1320         GtkWidget *vbox;
1321         gchar *label;
1322
1323         vbox = gtk_vbox_new (FALSE, 0);
1324
1325         /* Account description: */
1326         
1327         if (modest_tny_account_is_virtual_local_folders (account)) {
1328                 /* Local folders: */
1329         
1330                 /* Get device name */
1331                 gchar *device_name = modest_conf_get_string (modest_runtime_get_conf(),
1332                                                       MODEST_CONF_DEVICE_NAME, NULL);
1333    
1334                 label = g_strdup_printf (_("mcen_fi_localroot_description"),
1335                                          device_name);
1336                 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1337                 g_free (device_name);
1338                 g_free (label);
1339         } else {
1340                 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1341                         gtk_box_pack_start (GTK_BOX (vbox), 
1342                                 gtk_label_new (tny_account_get_name (account)), 
1343                                 FALSE, FALSE, 0);
1344                 } else {
1345                         /* Other accounts, such as IMAP and POP: */
1346                         
1347                         GString *proto;
1348                         gchar *tmp;
1349         
1350                         /* Put proto in uppercase */
1351                         proto = g_string_new (tny_account_get_proto (account));
1352                         proto = g_string_ascii_up (proto);
1353                         
1354                         /* note: mcen_fi_localroot_description is something like "%s account"
1355                          * however, we should display "%s account: %s"... therefore, ugly tmp */
1356                         tmp   = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1357                         label = g_strdup_printf ("%s: %s", tmp,tny_account_get_name (account));
1358                         g_free (tmp);
1359
1360                         gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1361                         g_string_free (proto, TRUE);
1362                         g_free (label);
1363                 }
1364         }
1365
1366         /* Message count */
1367         TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1368         label = g_strdup_printf ("%s: %d", _("mcen_fi_rootfolder_messages"), 
1369                                  modest_tny_folder_store_get_message_count (folder_store));
1370         gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1371         g_free (label);
1372
1373         /* Folder count */
1374         label = g_strdup_printf ("%s: %d", _("mcen_fi_rootfolder_folders"), 
1375                                  modest_tny_folder_store_get_folder_count (folder_store));
1376         gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1377         g_free (label);
1378
1379         /* Size / Date */
1380         if (modest_tny_account_is_virtual_local_folders (account)) {
1381                 /* FIXME: format size */
1382                 label = g_strdup_printf ("%s: %d", _("mcen_fi_rootfolder_size"), 
1383                                          modest_tny_folder_store_get_local_size (folder_store));
1384                 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1385                 g_free (label);
1386         } else if (TNY_IS_ACCOUNT(folder_store)) {
1387                 TnyAccount *account = TNY_ACCOUNT(folder_store);
1388                 
1389                 time_t last_updated;
1390                 gchar *last_updated_string;
1391                 /* Get last updated from configuration */
1392                 last_updated = modest_account_mgr_get_int (modest_runtime_get_account_mgr (), 
1393                                                           tny_account_get_id (account), 
1394                                                           MODEST_ACCOUNT_LAST_UPDATED, 
1395                                                           TRUE);
1396                 if (last_updated > 0) 
1397                         last_updated_string = modest_text_utils_get_display_date(last_updated);
1398                 else
1399                         last_updated_string = g_strdup (_("mcen_va_never"));
1400
1401                 label = g_strdup_printf ("%s: %s", _("mcen_ti_lastupdated"), last_updated_string);
1402                 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1403                 g_free (last_updated_string);
1404                 g_free (label);
1405         }
1406
1407         /* Set alignment */
1408         gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1409
1410         return vbox;
1411 }
1412
1413 void 
1414 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1415 {
1416         GtkAction *action = NULL;
1417         GtkWidget *widget = NULL;
1418
1419         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1420
1421         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu"); 
1422         gtk_action_set_sensitive (action, FALSE);
1423 /*         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1424 /*      gtk_action_set_sensitive (action, FALSE); */
1425         widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");       
1426         gtk_widget_set_sensitive (widget, FALSE);
1427
1428
1429 void 
1430 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1431 {
1432         GtkAction *action = NULL;
1433         GtkWidget *widget = NULL;
1434
1435         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1436
1437         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu"); 
1438         gtk_action_set_sensitive (action, TRUE);
1439 /*         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu");     */
1440 /*      gtk_action_set_sensitive (action, TRUE); */
1441         widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");       
1442         gtk_widget_set_sensitive (widget, TRUE);
1443
1444
1445
1446 static void
1447 _on_msg_count_changed (ModestHeaderView *header_view,
1448                        TnyFolder *folder,
1449                        TnyFolderChange *change,
1450                        ModestMainWindow *main_window)
1451 {
1452         printf ("DEBUG: %s\n", __FUNCTION__);
1453         gboolean folder_empty = FALSE;
1454         TnyFolderChangeChanged changed;
1455         
1456         g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1457         g_return_if_fail (TNY_IS_FOLDER(folder));
1458         g_return_if_fail (TNY_IS_FOLDER_CHANGE(change));
1459         
1460         changed = tny_folder_change_get_changed (change);
1461         
1462         /* If something changes */
1463         if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1464                 folder_empty = (tny_folder_change_get_new_all_count (change) == 0);     
1465         else
1466                 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1467         
1468         printf ("DEBUG: %s: folder_empty=%d\n", __FUNCTION__, folder_empty);
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                 TnyFolderStore *selected_folderstore = 
1522                         modest_folder_view_get_selected (priv->folder_view);
1523                 if (TNY_IS_ACCOUNT (selected_folderstore)) {    
1524                         priv->details_widget = create_details_widget (
1525                                 TNY_ACCOUNT (selected_folderstore));
1526
1527                         wrap_in_scrolled_window (priv->contents_widget, 
1528                                          priv->details_widget);
1529                 }
1530                 g_object_unref (selected_folderstore);
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 ModestMainWindowContentsStyle
1545 modest_main_window_get_contents_style (ModestMainWindow *self)
1546 {
1547         ModestMainWindowPrivate *priv;
1548
1549         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1550
1551         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1552         return priv->contents_style;
1553 }
1554
1555
1556 static void 
1557 on_configuration_key_changed (ModestConf* conf, 
1558                               const gchar *key, 
1559                               ModestConfEvent event, 
1560                               ModestMainWindow *self)
1561 {
1562         ModestMainWindowPrivate *priv;
1563         TnyAccount *account;
1564
1565         if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
1566                 return;
1567
1568         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1569
1570         if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1571                 return;
1572
1573         account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1574         if (TNY_IS_ACCOUNT (account) &&
1575             !strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1576                 GList *children;
1577                 GtkLabel *label;
1578                 const gchar *device_name;
1579                 gchar *new_text;
1580                 
1581                 /* Get label */
1582                 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1583                 label = GTK_LABEL (children->data);
1584                 
1585                 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1586                                                       MODEST_CONF_DEVICE_NAME, NULL);
1587                 
1588                 new_text = g_strdup_printf ("%s: %s",
1589                                             _("mcen_fi_localroot_description"),
1590                                             device_name);
1591                 
1592                 gtk_label_set_text (label, new_text);
1593                 gtk_widget_show (GTK_WIDGET (label));
1594                 
1595                 g_free (new_text);
1596                 g_list_free (children);
1597         }
1598         g_object_unref (account);
1599 }
1600
1601 static gboolean
1602 set_toolbar_transfer_mode (ModestMainWindow *self)
1603 {
1604         ModestMainWindowPrivate *priv = NULL;
1605         
1606         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1607
1608         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1609
1610         set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1611         
1612         if (priv->progress_bar_timeout > 0) {
1613                 g_source_remove (priv->progress_bar_timeout);
1614                 priv->progress_bar_timeout = 0;
1615         }
1616
1617         return FALSE;
1618 }
1619
1620 static void 
1621 set_toolbar_mode (ModestMainWindow *self, 
1622                   ModestToolBarModes mode)
1623 {
1624         ModestWindowPrivate *parent_priv = NULL;
1625         ModestMainWindowPrivate *priv = NULL;
1626         GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1627         
1628         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1629
1630         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1631         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1632
1633         /* In case this was called before the toolbar exists: */
1634         if (!(parent_priv->toolbar))
1635                 return;
1636
1637         g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar)); 
1638         
1639         sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1640         refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1641         cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1642
1643         /* Sets current toolbar mode */
1644         priv->current_toolbar_mode = mode;
1645
1646         /* Show and hide toolbar items */
1647         switch (mode) {
1648         case TOOLBAR_MODE_NORMAL:
1649                 if (sort_action) 
1650                         gtk_action_set_visible (sort_action, TRUE);
1651                 if (refresh_action) 
1652                         gtk_action_set_visible (refresh_action, TRUE);
1653                 if (priv->progress_toolitem) {
1654                         gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1655                         gtk_widget_hide (priv->progress_toolitem);
1656                 }
1657                 if (priv->progress_bar)
1658                         gtk_widget_hide (priv->progress_bar);                   
1659                 
1660                 if (cancel_action)
1661                         gtk_action_set_visible (cancel_action, FALSE);
1662
1663                 /* Hide toolbar if optimized view is enabled */
1664                 if (priv->optimized_view)
1665                         gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
1666                 break;
1667         case TOOLBAR_MODE_TRANSFER:
1668                 if (sort_action)
1669                         gtk_action_set_visible (sort_action, FALSE);
1670                 if (refresh_action)
1671                         gtk_action_set_visible (refresh_action, FALSE);
1672                 if (cancel_action)
1673                         gtk_action_set_visible (cancel_action, TRUE);
1674                 if (priv->progress_toolitem) {
1675                         gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1676                         gtk_widget_show (priv->progress_toolitem);
1677                 }
1678                 if (priv->progress_bar)
1679                         gtk_widget_show (priv->progress_bar);                   
1680
1681                 /* Show toolbar if it's hiden (optimized view ) */
1682                 if (priv->optimized_view)
1683                         gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1684                 break;
1685         default:
1686                 g_return_if_reached ();
1687         }
1688 }
1689
1690 static void
1691 cancel_progressbar (GtkToolButton *toolbutton,
1692                     ModestMainWindow *self)
1693 {
1694         GSList *tmp;
1695         ModestMainWindowPrivate *priv;
1696         
1697         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1698
1699         /* Get operation observers and cancel its current operation */
1700         tmp = priv->progress_widgets;
1701         while (tmp) {
1702                 modest_progress_object_cancel_current_operation (MODEST_PROGRESS_OBJECT(tmp->data));
1703                 tmp=g_slist_next(tmp);
1704         }
1705 }
1706
1707 static gboolean
1708 observers_empty (ModestMainWindow *self)
1709 {
1710         GSList *tmp = NULL;
1711         ModestMainWindowPrivate *priv;
1712         gboolean is_empty = TRUE;
1713         guint pending_ops = 0;
1714  
1715         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1716         tmp = priv->progress_widgets;
1717
1718         /* Check all observers */
1719         while (tmp && is_empty)  {
1720                 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
1721                 is_empty = pending_ops == 0;
1722                 
1723                 tmp = g_slist_next(tmp);
1724         }
1725         
1726         return is_empty;
1727 }
1728
1729 static void
1730 on_queue_changed (ModestMailOperationQueue *queue,
1731                   ModestMailOperation *mail_op,
1732                   ModestMailOperationQueueNotification type,
1733                   ModestMainWindow *self)
1734 {
1735         ModestMainWindowPrivate *priv;
1736         ModestMailOperationTypeOperation op_type;
1737         ModestToolBarModes mode;
1738         GSList *tmp;
1739         gboolean mode_changed = FALSE;
1740 /*      ModestMailOperationStatus status; */
1741
1742         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1743         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1744                
1745         /* Get toolbar mode from operation id*/
1746         op_type = modest_mail_operation_get_type_operation (mail_op);
1747         switch (op_type) {
1748         case MODEST_MAIL_OPERATION_TYPE_SEND:
1749         case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
1750                 mode = TOOLBAR_MODE_TRANSFER;
1751                 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
1752                         mode_changed = TRUE;
1753                 break;
1754         default:
1755                 mode = TOOLBAR_MODE_NORMAL;
1756                 
1757         }
1758                 
1759                        
1760         /* Add operation observers and change toolbar if neccessary*/
1761         tmp = priv->progress_widgets;
1762         switch (type) {
1763         case MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED:
1764                 if (mode == TOOLBAR_MODE_TRANSFER) {
1765                         if (mode_changed)
1766                                 set_toolbar_transfer_mode(self);                    
1767                         while (tmp) {
1768                                 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
1769                                                                       mail_op);
1770                                 tmp = g_slist_next (tmp);
1771                         }
1772                 }
1773                 break;
1774         case MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED:
1775                 /* Change toolbar mode */
1776                 if (mode == TOOLBAR_MODE_TRANSFER) {                    
1777                         while (tmp) {
1778                                 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
1779                                                                          mail_op);
1780                                 tmp = g_slist_next (tmp);
1781                         }
1782                         
1783                         /* If no more operations are being observed, NORMAL mode is enabled again */
1784                         if (observers_empty (self)) {
1785                                 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
1786                                 
1787                         }
1788                 }
1789
1790                 break;
1791         }       
1792
1793 }
1794
1795 static void 
1796 on_show_account_action_activated  (GtkAction *action,
1797                                    gpointer user_data)
1798 {
1799         ModestAccountData *acc_data;
1800         ModestMainWindow *self;
1801         ModestMainWindowPrivate *priv;
1802         ModestAccountMgr *mgr;
1803         const gchar *acc_name;
1804
1805         self = MODEST_MAIN_WINDOW (user_data);
1806         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1807
1808         /* Get account data */
1809         acc_name = gtk_action_get_name (action);
1810         mgr = modest_runtime_get_account_mgr ();
1811         acc_data = modest_account_mgr_get_account_data (mgr, acc_name);
1812
1813         /* Set the new visible & active account */
1814         if (acc_data->store_account) { 
1815                 modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view,
1816                                                                              acc_data->store_account->account_name);
1817                 modest_window_set_active_account (MODEST_WINDOW (self), acc_data->account_name);
1818         }
1819
1820         /* Free */
1821         modest_account_mgr_free_account_data (mgr, acc_data);
1822 }
1823
1824 static void
1825 refresh_account (const gchar *account_name)
1826 {
1827         ModestWindow *win;
1828
1829         win = MODEST_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
1830
1831         /* If account_name == NULL, we must update all (option All) */
1832         if (!account_name)
1833                 modest_ui_actions_do_send_receive_all (win);
1834         else
1835                 modest_ui_actions_do_send_receive (account_name, win);
1836 }
1837
1838 static void 
1839 on_refresh_account_action_activated  (GtkAction *action,
1840                                       gpointer user_data)
1841 {
1842         refresh_account ((const gchar*) user_data);
1843 }
1844
1845 static void
1846 on_send_receive_csm_activated (GtkMenuItem *item,
1847                                gpointer user_data)
1848 {
1849         refresh_account ((const gchar*) user_data);
1850 }
1851
1852 static gchar * 
1853 translate_func (const gchar *msgid,
1854                 const gchar *domain_name)
1855 {
1856         return _(msgid);
1857 }