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