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