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