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