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