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