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