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