* Some aesthetic changes
[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 on_default_account_changed (ModestAccountMgr* mgr,
126                                         gpointer user_data);
127
128 static gboolean on_inner_widgets_key_pressed  (GtkWidget *widget,
129                                                GdkEventKey *event,
130                                                gpointer user_data);
131
132 static void on_configuration_key_changed      (ModestConf* conf, 
133                                                const gchar *key, 
134                                                ModestConfEvent event,
135                                                ModestConfNotificationId id,
136                                                ModestMainWindow *self);
137
138 static void set_toolbar_mode                  (ModestMainWindow *self, 
139                                                ModestToolBarModes mode);
140
141 static gboolean set_toolbar_transfer_mode     (ModestMainWindow *self); 
142
143 static void on_show_account_action_toggled      (GtkToggleAction *action,
144                                                  gpointer user_data);
145
146 static void on_refresh_account_action_activated   (GtkAction *action,
147                                                    gpointer user_data);
148
149 static void on_send_receive_csm_activated         (GtkMenuItem *item,
150                                                    gpointer user_data);
151
152 static void on_msg_count_changed (ModestHeaderView *header_view,
153                                   TnyFolder *folder,
154                                   TnyFolderChange *change,
155                                   ModestMainWindow *main_window);
156
157 static void modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self);
158
159
160 static GtkWidget * create_empty_view (void);
161
162 static gboolean  on_folder_view_focus_in (GtkWidget *widget,
163                                           GdkEventFocus *event,
164                                           gpointer userdata);
165
166 static gboolean  on_header_view_focus_in (GtkWidget *widget,
167                                           GdkEventFocus *event,
168                                           gpointer userdata);
169
170 static void      modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
171                                                                  TnyFolderStore *folder_store, 
172                                                                  gboolean selected,
173                                                                  ModestMainWindow *main_window);
174                                                 
175 static void set_at_least_one_account_visible(ModestMainWindow *self);
176
177 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
178 struct _ModestMainWindowPrivate {
179         GtkWidget *msg_paned;
180         GtkWidget *main_paned;
181         GtkWidget *main_vbox;
182         GtkWidget *contents_widget;
183         GtkWidget *empty_view;
184
185         /* Progress observers */
186         GtkWidget   *progress_bar;
187         GSList      *progress_widgets;
188
189         /* Tollbar items */
190         GtkWidget   *progress_toolitem;
191         GtkWidget   *cancel_toolitem;
192         GtkWidget   *sort_toolitem;
193         GtkWidget   *refresh_toolitem;
194         ModestToolBarModes current_toolbar_mode;
195
196         /* Merge ids used to add/remove accounts to the ViewMenu*/
197         GByteArray *merge_ids;
198         GtkActionGroup *view_additions_group;
199
200         /* On-demand widgets */
201         GtkWidget *accounts_popup;
202         GtkWidget *details_widget;
203
204         /* Optimized view enabled */
205         gboolean optimized_view;
206
207         /* Optimized view enabled */
208         gboolean send_receive_in_progress;
209
210         ModestHeaderView *header_view;
211         ModestFolderView *folder_view;
212
213         ModestMainWindowStyle style;
214         ModestMainWindowContentsStyle contents_style;
215
216         guint progress_bar_timeout;
217
218         /* Signal handler UIDs */
219         GList *queue_err_signals;
220         GSList *sighandlers;
221 };
222 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
223                                                 MODEST_TYPE_MAIN_WINDOW, \
224                                                 ModestMainWindowPrivate))
225
226 typedef struct _GetMsgAsyncHelper {
227         ModestMainWindowPrivate *main_window_private;
228         guint action;
229         ModestTnyMsgReplyType reply_type;
230         ModestTnyMsgForwardType forward_type;
231         gchar *from;
232         TnyIterator *iter;
233 } GetMsgAsyncHelper;
234
235
236 /* globals */
237 static GtkWindowClass *parent_class = NULL;
238
239
240 /* Private actions */
241 /* This is the context sensitive menu: */
242 static const GtkActionEntry modest_folder_view_action_entries [] = {
243
244         /* Folder View CSM actions */
245         { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
246         { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
247         { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL,  G_CALLBACK (modest_ui_actions_on_paste)},
248         { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
249         { "FolderViewCSMSearchMessages", NULL, N_("mcen_me_inbox_search"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_search_messages) },
250         { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
251 };
252
253 static const GtkActionEntry modest_header_view_action_entries [] = {
254
255         /* Header View CSM actions */
256         { "HeaderViewCSMOpen",          NULL,  N_("mcen_me_inbox_open"),        NULL,       NULL, G_CALLBACK (modest_ui_actions_on_open) },
257         { "HeaderViewCSMReply",         NULL,  N_("mcen_me_inbox_reply"),       NULL,      NULL, G_CALLBACK (modest_ui_actions_on_reply) },
258         { "HeaderViewCSMReplyAll",      NULL,  N_("mcen_me_inbox_replytoall"),  NULL,      NULL, G_CALLBACK (modest_ui_actions_on_reply_all) },
259         { "HeaderViewCSMForward",       NULL,  N_("mcen_me_inbox_forward"),     NULL,      NULL, G_CALLBACK (modest_ui_actions_on_forward) },
260         { "HeaderViewCSMCut",           NULL,  N_("mcen_me_inbox_cut"),         "<CTRL>X", NULL, G_CALLBACK (modest_ui_actions_on_cut) },
261         { "HeaderViewCSMCopy",          NULL,  N_("mcen_me_inbox_copy"),        "<CTRL>C", NULL, G_CALLBACK (modest_ui_actions_on_copy) },
262         { "HeaderViewCSMPaste",         NULL,  N_("mcen_me_inbox_paste"),       "<CTRL>V", NULL, G_CALLBACK (modest_ui_actions_on_paste) },
263         { "HeaderViewCSMDelete",        NULL,  N_("mcen_me_inbox_delete"),      NULL,      NULL, G_CALLBACK (modest_ui_actions_on_delete_message) },
264         { "HeaderViewCSMCancelSending", NULL,  N_("mcen_me_outbox_cancelsend"), NULL,      NULL, G_CALLBACK (modest_ui_actions_cancel_send) },
265         { "HeaderViewCSMHelp",          NULL,  N_("mcen_me_inbox_help"),        NULL,      NULL, G_CALLBACK (modest_ui_actions_on_help) },
266 };
267
268 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
269         { "ToggleFolders",     MODEST_STOCK_SPLIT_VIEW, N_("mcen_me_inbox_hidefolders"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), TRUE },
270 };
271
272 /************************************************************************/
273
274 GType
275 modest_main_window_get_type (void)
276 {
277         static GType my_type = 0;
278         if (!my_type) {
279                 static const GTypeInfo my_info = {
280                         sizeof(ModestMainWindowClass),
281                         NULL,           /* base init */
282                         NULL,           /* base finalize */
283                         (GClassInitFunc) modest_main_window_class_init,
284                         NULL,           /* class finalize */
285                         NULL,           /* class data */
286                         sizeof(ModestMainWindow),
287                         1,              /* n_preallocs */
288                         (GInstanceInitFunc) modest_main_window_init,
289                         NULL
290                 };
291                 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
292                                                   "ModestMainWindow",
293                                                   &my_info, 0);
294         }
295         return my_type;
296 }
297
298 static void
299 modest_main_window_class_init (ModestMainWindowClass *klass)
300 {
301         GObjectClass *gobject_class;
302         gobject_class = (GObjectClass*) klass;
303         ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
304
305         parent_class            = g_type_class_peek_parent (klass);
306         gobject_class->finalize = modest_main_window_finalize;
307
308         g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
309         
310         modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
311         modest_window_class->save_state_func = save_state;
312         modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
313         modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
314         modest_window_class->disconnect_signals_func = modest_main_window_disconnect_signals;
315 }
316
317 static void
318 modest_main_window_init (ModestMainWindow *obj)
319 {
320         ModestMainWindowPrivate *priv;
321
322         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
323
324         priv->queue_err_signals = NULL;
325         priv->msg_paned    = NULL;
326         priv->main_paned   = NULL;      
327         priv->main_vbox    = NULL;
328         priv->header_view  = NULL;
329         priv->folder_view  = NULL;
330         priv->contents_widget  = NULL;
331         priv->accounts_popup  = NULL;
332         priv->details_widget  = NULL;
333         priv->empty_view  = NULL;
334         priv->progress_widgets  = NULL;
335         priv->progress_bar = NULL;
336         priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
337         priv->style  = MODEST_MAIN_WINDOW_STYLE_SPLIT;
338         priv->contents_style  = -1; /* invalid contents style. We need this to select it for the first time */
339         priv->merge_ids = NULL;
340         priv->optimized_view  = FALSE;
341         priv->send_receive_in_progress  = FALSE;
342         priv->progress_bar_timeout = 0;
343         priv->sighandlers = NULL;
344 }
345
346 static void
347 modest_main_window_finalize (GObject *obj)
348 {
349         ModestMainWindowPrivate *priv;
350
351         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
352
353         /* Sanity check: shouldn't be needed, the window mgr should
354            call this function before */
355         modest_main_window_disconnect_signals (MODEST_WINDOW (obj));
356
357         modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj);
358
359         g_slist_free (priv->progress_widgets);
360
361         g_byte_array_free (priv->merge_ids, TRUE);
362
363         if (priv->progress_bar_timeout > 0) {
364                 g_source_remove (priv->progress_bar_timeout);
365                 priv->progress_bar_timeout = 0;
366         }
367
368         G_OBJECT_CLASS(parent_class)->finalize (obj);
369 }
370
371 GtkWidget*
372 modest_main_window_get_child_widget (ModestMainWindow *self,
373                                      ModestMainWindowWidgetType widget_type)
374 {
375         ModestMainWindowPrivate *priv;
376         GtkWidget *widget;
377         
378         g_return_val_if_fail (self, NULL);
379         g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_MAIN_WINDOW_WIDGET_TYPE_NUM,
380                               NULL);
381         
382         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
383
384         switch (widget_type) {
385         case MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW:
386                 widget = (GtkWidget*)priv->header_view; break;
387         case MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW:
388                 widget = (GtkWidget*)priv->folder_view; break;
389         default:
390                 return NULL;
391         }
392
393         return widget ? GTK_WIDGET(widget) : NULL;
394 }
395
396
397 static void
398 restore_settings (ModestMainWindow *self, gboolean do_folder_view_too)
399 {
400         ModestConf *conf;
401         ModestMainWindowPrivate *priv;
402
403         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
404
405         conf = modest_runtime_get_conf ();
406
407         modest_widget_memory_restore (conf, G_OBJECT(self),
408                                       MODEST_CONF_MAIN_WINDOW_KEY);
409
410         modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
411                                       MODEST_CONF_HEADER_VIEW_KEY);
412
413         if (do_folder_view_too)
414                 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
415                                       MODEST_CONF_FOLDER_VIEW_KEY);
416
417         modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
418                                       MODEST_CONF_MAIN_PANED_KEY);
419
420         /* We need to force a redraw here in order to get the right
421            position of the horizontal paned separator */
422         gtk_widget_show (GTK_WIDGET (self));
423 }
424
425
426 static void
427 save_state (ModestWindow *window)
428 {
429         ModestConf *conf;
430         ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
431         ModestMainWindowPrivate *priv;
432                 
433         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
434         conf = modest_runtime_get_conf ();
435         
436         modest_widget_memory_save (conf,G_OBJECT(self), 
437                                    MODEST_CONF_MAIN_WINDOW_KEY);
438         modest_widget_memory_save (conf, G_OBJECT(priv->main_paned), 
439                                    MODEST_CONF_MAIN_PANED_KEY);
440         //      modest_widget_memory_save (conf, G_OBJECT(priv->header_view), 
441         //                         MODEST_CONF_HEADER_VIEW_KEY);
442         modest_widget_memory_save (conf, G_OBJECT(priv->folder_view), 
443                                    MODEST_CONF_FOLDER_VIEW_KEY);
444 }
445
446 static gint
447 compare_display_names (ModestAccountData *a,
448                        ModestAccountData *b)
449 {
450         return strcmp (a->display_name, b->display_name);
451 }
452
453 static void
454 update_menus (ModestMainWindow* self)
455 {       
456         GSList *account_names, *iter, *accounts;
457         ModestMainWindowPrivate *priv;
458         ModestWindowPrivate *parent_priv;
459         ModestAccountMgr *mgr;
460         gint i, num_accounts;
461         GList *groups;
462         gchar *default_account;
463         GtkWidget *send_receive_button, *item;
464         GtkAction *send_receive_all = NULL;
465         GSList *radio_group;
466
467         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
468         parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
469
470         /* Get enabled account IDs */
471         mgr = modest_runtime_get_account_mgr ();
472         account_names = modest_account_mgr_account_names (mgr, TRUE);
473         iter = account_names;
474         accounts = NULL;
475
476         while (iter) {
477                 ModestAccountData *account_data = 
478                         modest_account_mgr_get_account_data (mgr, (gchar*) iter->data);
479                 accounts = g_slist_prepend (accounts, account_data);
480
481                 iter = iter->next;
482         }
483         modest_account_mgr_free_account_names (account_names);
484         account_names = NULL;
485
486         /* Order the list of accounts by its display name */
487         accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
488         num_accounts = g_slist_length (accounts);
489
490         send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager, 
491                                                       "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
492         gtk_action_set_visible (send_receive_all, num_accounts > 1);
493
494         /* Delete old send&receive popup items. We can not just do a
495            menu_detach because it does not work well with
496            tap_and_hold */
497         if (priv->accounts_popup)
498                 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup), 
499                                        (GtkCallback) gtk_widget_destroy, NULL);
500
501         /* Delete old entries in the View menu. Do not free groups, it
502            belongs to Gtk+ */
503         groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
504         while (groups) {
505                 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
506                              gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
507                         gtk_ui_manager_remove_action_group (parent_priv->ui_manager, 
508                                                             GTK_ACTION_GROUP (groups->data));
509                         groups = NULL;
510                         /* Remove uis */
511                         if (priv->merge_ids) {
512                                 for (i = 0; i < priv->merge_ids->len; i++)
513                                         gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
514                                 g_byte_array_free (priv->merge_ids, TRUE);
515                         }
516                         /* We need to call this in order to ensure
517                            that the new actions are added in the right
518                            order (alphabetical */
519                         gtk_ui_manager_ensure_update (parent_priv->ui_manager);
520                 } else 
521                         groups = g_list_next (groups);
522         }
523         priv->merge_ids = g_byte_array_sized_new (num_accounts);
524
525         /* Get send receive button */
526         send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
527                                                           "/ToolBar/ToolbarSendReceive");
528
529         /* Create the menu */
530         if (num_accounts > 1) {
531                 if (!priv->accounts_popup)
532                         priv->accounts_popup = gtk_menu_new ();
533                 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
534                 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
535                 g_signal_connect (G_OBJECT (item), 
536                                   "activate", 
537                                   G_CALLBACK (on_send_receive_csm_activated),
538                                   NULL);
539                 item = gtk_separator_menu_item_new ();
540                 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
541         }
542
543         /* Create a new action group */
544         default_account = modest_account_mgr_get_default_account (mgr);
545         priv->view_additions_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
546         radio_group = NULL;
547         for (i = 0; i < num_accounts; i++) {
548                 gchar *display_name = NULL;
549                 
550                 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
551
552                 /* Create display name. The UI specification specifies a different format string 
553                  * to use for the default account, though both seem to be "%s", so 
554                  * I don't see what the point is. murrayc. */
555                 if (default_account && account_data->account_name && 
556                         !(strcmp (default_account, account_data->account_name) == 0)) {
557                         display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"), 
558                                                         account_data->display_name);
559                 }
560                 else {
561                         display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"), 
562                                                         account_data->display_name);
563                 }
564
565                 /* Create action and add it to the action group. The
566                    action name must be the account name, this way we
567                    could know in the handlers the account to show */
568                 if(account_data && account_data->account_name) {
569                         gchar* item_name, *refresh_action_name;
570                         guint8 merge_id = 0;
571                         GtkAction *view_account_action, *refresh_account_action;
572
573                         view_account_action = GTK_ACTION (gtk_radio_action_new (account_data->account_name,
574                                                                                 display_name, NULL, NULL, 0));
575                         gtk_action_group_add_action (priv->view_additions_group, view_account_action);
576                         gtk_radio_action_set_group (GTK_RADIO_ACTION (view_account_action), radio_group);
577                         radio_group = gtk_radio_action_get_group (GTK_RADIO_ACTION (view_account_action));
578
579                         if (default_account && account_data->account_name && 
580                             (strcmp (default_account, account_data->account_name) == 0)) {
581                                 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (view_account_action), TRUE);
582                         }
583
584                         /* Add ui from account data. We allow 2^9-1 account
585                            changes in a single execution because we're
586                            downcasting the guint to a guint8 in order to use a
587                            GByteArray. It should be enough. */
588                         item_name = g_strconcat (account_data->account_name, "Menu", NULL);
589                         merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
590                         priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
591                         gtk_ui_manager_add_ui (parent_priv->ui_manager,
592                                                merge_id,
593                                                "/MenuBar/ViewMenu/ViewMenuAdditions",
594                                                item_name,
595                                                account_data->account_name,
596                                                GTK_UI_MANAGER_MENUITEM,
597                                                FALSE);
598
599                         /* Connect the action signal "activate" */
600                         g_signal_connect_after (G_OBJECT (view_account_action),
601                                                 "toggled",
602                                                 G_CALLBACK (on_show_account_action_toggled),
603                                                 self);
604
605                         /* Create the items for the Tools->Send&Receive submenu */
606                         refresh_action_name = g_strconcat ("SendReceive", account_data->account_name, NULL);
607                         refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name, 
608                                                                  display_name, NULL, NULL);
609                         gtk_action_group_add_action (priv->view_additions_group, refresh_account_action);
610
611                         merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
612                         priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
613                         gtk_ui_manager_add_ui (parent_priv->ui_manager, 
614                                                merge_id,
615                                                "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
616                                                item_name,
617                                                refresh_action_name,
618                                                GTK_UI_MANAGER_MENUITEM,
619                                                FALSE);
620                         g_free (refresh_action_name);
621
622                         g_signal_connect_data (G_OBJECT (refresh_account_action), 
623                                                "activate", 
624                                                G_CALLBACK (on_refresh_account_action_activated), 
625                                                g_strdup (account_data->account_name),
626                                                (GClosureNotify) g_free,
627                                                0);
628
629                         /* Create item and add it to the send&receive
630                            CSM. If there is only one account then
631                            it'll be no menu */
632                         if (priv->accounts_popup) {
633                                 GtkWidget *label = gtk_label_new(NULL);
634                                 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
635                                 if (default_account && (strcmp(account_data->account_name, default_account) == 0))
636                                 {
637                                         gchar *escaped = g_markup_printf_escaped ("<b>%s</b>", display_name);
638                                         gtk_label_set_markup (GTK_LABEL (label), escaped);
639                                         g_free (escaped);
640                                 }
641                                 else
642                                 {
643                                         gtk_label_set_text (GTK_LABEL (label), display_name);
644                                 }
645
646                                 item = gtk_menu_item_new ();
647                                 gtk_container_add (GTK_CONTAINER (item), label);
648
649                                 gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
650                                 g_signal_connect_data (G_OBJECT (item), 
651                                                        "activate", 
652                                                        G_CALLBACK (on_send_receive_csm_activated),
653                                                        g_strdup (account_data->account_name),
654                                                        (GClosureNotify) g_free,
655                                                        0);
656                         }
657                         g_free (item_name);
658                 }
659
660                 /* Frees */
661                 g_free (display_name);
662         }
663
664         gtk_ui_manager_insert_action_group (parent_priv->ui_manager, priv->view_additions_group, 1);
665
666         /* We cannot do this in the loop above because this relies on the action
667          * group being inserted. This makes the default account appear in bold.
668          * I agree it is a rather ugly way, but I don't see another possibility. armin. */
669         for (i = 0; i < num_accounts; i++) {
670                 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
671
672                 if(account_data->account_name && default_account &&
673                    strcmp (account_data->account_name, default_account) == 0) {
674                         gchar *item_name = g_strconcat (account_data->account_name, "Menu", NULL);
675
676                         gchar *path = g_strconcat ("/MenuBar/ViewMenu/ViewMenuAdditions/", item_name, NULL);
677                         GtkWidget *item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
678                         g_free(path);
679
680                         if (item) {
681                                 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
682                                 if (GTK_IS_LABEL (child)) {
683                                         const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
684                                         gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
685                                         gtk_label_set_markup (GTK_LABEL (child), bold_name);
686                                         g_free (bold_name);
687                                 }
688                         }
689
690                         path = g_strconcat("/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions/", item_name, NULL);
691                         item = gtk_ui_manager_get_widget (parent_priv->ui_manager, path);
692                         g_free (path);
693
694                         if (item) {
695                                 GtkWidget *child = gtk_bin_get_child (GTK_BIN (item));
696                                 if (GTK_IS_LABEL (child)) {
697                                         const gchar *cur_name = gtk_label_get_text (GTK_LABEL (child));
698                                         gchar *bold_name = g_markup_printf_escaped("<b>%s</b>", cur_name);
699                                         gtk_label_set_markup (GTK_LABEL (child), bold_name);
700                                         g_free (bold_name);
701                                 }
702                         }
703
704                         g_free(item_name);
705                 }
706
707                 modest_account_mgr_free_account_data (mgr, account_data);
708         }
709
710         if (priv->accounts_popup) {
711                 /* Mandatory in order to view the menu contents */
712                 gtk_widget_show_all (priv->accounts_popup);
713
714                 /* Setup tap_and_hold just if was not done before*/
715                 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
716                         gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
717         }
718
719         /* Frees */
720         g_slist_free (accounts);
721         g_free (default_account);
722
723
724         /* Make sure that at least one account is viewed if there are any 
725          * accounts, for instance when adding the first account: */
726         set_at_least_one_account_visible (self);
727 }
728
729 static void
730 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
731 {
732         if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
733                 gtk_scrolled_window_add_with_viewport
734                         (GTK_SCROLLED_WINDOW(win), widget);
735         else
736                 gtk_container_add (GTK_CONTAINER(win),
737                                    widget);
738 }
739
740
741 typedef struct {
742         TnySendQueue *queue;
743         guint signal;
744 } QueueErrorSignal;
745
746 static void
747 modest_main_window_cleanup_queue_error_signals (ModestMainWindow *self)
748 {
749         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
750
751         GList *oerrsignals = priv->queue_err_signals;
752         while (oerrsignals) {
753                 QueueErrorSignal *esignal = (QueueErrorSignal *) oerrsignals->data;
754                 g_signal_handler_disconnect (esignal->queue, esignal->signal);
755                 g_slice_free (QueueErrorSignal, esignal);
756                 oerrsignals = g_list_next (oerrsignals);
757         }
758         g_list_free (priv->queue_err_signals);
759         priv->queue_err_signals = NULL;
760 }
761
762
763 static void
764 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
765 {
766         g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
767
768         /* Update dimmed */     
769         modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");  
770 }
771
772 static void
773 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
774 {
775         g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
776
777         /* Update visibility */
778
779         /* Update dimmed */     
780         modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");  
781 }
782
783 static void
784 modest_main_window_disconnect_signals (ModestWindow *self)
785 {       
786         ModestMainWindowPrivate *priv;  
787         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
788
789         modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
790         priv->sighandlers = NULL;       
791 }
792
793 static void
794 connect_signals (ModestMainWindow *self)
795 {       
796         ModestWindowPrivate *parent_priv;
797         ModestMainWindowPrivate *priv;
798         GtkWidget *menu;
799         
800         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
801         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
802
803         /* folder view */
804         
805         priv->sighandlers = 
806                 modest_signal_mgr_connect (priv->sighandlers,
807                                            G_OBJECT(priv->folder_view), "key-press-event",
808                                            G_CALLBACK(on_inner_widgets_key_pressed), self);
809         priv->sighandlers = 
810                 modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "folder_selection_changed",
811                                            G_CALLBACK (modest_main_window_on_folder_selection_changed), self);
812         priv->sighandlers = 
813                 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->folder_view), "folder-display-name-changed",
814                                            G_CALLBACK (modest_ui_actions_on_folder_display_name_changed), self);
815         priv->sighandlers = 
816                 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (priv->folder_view), "focus-in-event", 
817                                            G_CALLBACK (on_folder_view_focus_in), self);
818
819         /* Folder view CSM */
820         menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
821         gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
822         priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers, G_OBJECT(priv->folder_view), "tap-and-hold",
823                                                        G_CALLBACK(_folder_view_csm_menu_activated),
824                                                        self);
825         /* header view */
826         priv->sighandlers = 
827                 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_selected",
828                                            G_CALLBACK(modest_ui_actions_on_header_selected), self);
829         priv->sighandlers = 
830                 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "header_activated",
831                                            G_CALLBACK(modest_ui_actions_on_header_activated), self);
832         priv->sighandlers = 
833                 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "item_not_found",
834                                            G_CALLBACK(modest_ui_actions_on_item_not_found), self);
835         priv->sighandlers = 
836                 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "key-press-event",
837                                            G_CALLBACK(on_inner_widgets_key_pressed), self);
838         priv->sighandlers = 
839                 modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(priv->header_view), "msg_count_changed",
840                                            G_CALLBACK(on_msg_count_changed), self);
841         priv->sighandlers = 
842                 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->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT(modest_runtime_get_conf ()),
863                                                        "key_changed", G_CALLBACK (on_configuration_key_changed), 
864                                                        self);
865         
866         /* Track account changes. We need to refresh the toolbar */
867         priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (modest_runtime_get_account_store ()),
868                                                        "account_inserted", G_CALLBACK (on_account_inserted),
869                                                        self);
870         priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (modest_runtime_get_account_store ()),
871                                                        "account_removed", G_CALLBACK (on_account_removed),
872                                                        self);
873
874         /* We need to refresh the send & receive menu to change the bold
875          * account when the default account changes. */
876         priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
877                                                        G_OBJECT (modest_runtime_get_account_mgr ()),
878                                                        "default_account_changed", 
879                                                        G_CALLBACK (on_default_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/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu";
1386         else
1387                 action_name = "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/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_default_account_changed (ModestAccountMgr* mgr,
1404                             gpointer user_data)
1405 {
1406         update_menus (MODEST_MAIN_WINDOW (user_data));
1407 }
1408
1409 static void
1410 on_account_removed (TnyAccountStore *accoust_store,
1411                      TnyAccount *account,
1412                      gpointer user_data)
1413 {
1414         update_menus (MODEST_MAIN_WINDOW (user_data));
1415 }
1416
1417 /* 
1418  * This function manages the key events used to navigate between
1419  * header and folder views (when the window is in split view)
1420  *
1421  * FROM         KEY        ACTION
1422  * -------------------------------------------------
1423  * HeaderView   GDK_Left   Move focus to folder view
1424  * FolderView   GDK_Right  Move focus to header view
1425  *
1426  * There is no need to scroll to selected row, the widgets will be the
1427  * responsibles of doing that (probably managing the focus-in event
1428  */
1429 static gboolean 
1430 on_inner_widgets_key_pressed (GtkWidget *widget,
1431                               GdkEventKey *event,
1432                               gpointer user_data)
1433 {
1434         ModestMainWindowPrivate *priv;
1435
1436         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1437
1438         /* Do nothing if we're in SIMPLE style */
1439         if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1440                 return FALSE;
1441
1442         if (MODEST_IS_HEADER_VIEW (widget)) {
1443                 if (event->keyval == GDK_Left)
1444                         gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1445                 else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) {
1446                         hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1447                         return TRUE;
1448                 }
1449         } else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1450                 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1451
1452         return FALSE;
1453 }
1454
1455 static void
1456 set_alignment (GtkWidget *widget,
1457                gpointer data)
1458 {
1459         gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1460         gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1461 }
1462
1463 static GtkWidget *
1464 create_empty_view (void)
1465 {
1466         GtkLabel *label = NULL;
1467         GtkWidget *align = NULL;
1468
1469         align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1470         label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1471         gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);      
1472         gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1473
1474         return GTK_WIDGET(align);
1475 }
1476
1477 /*
1478  * Free the returned string
1479  */
1480 static gchar *
1481 get_gray_color_markup (GtkWidget *styled_widget)
1482 {
1483         gchar *gray_color_markup;
1484
1485         /* Obtain the secondary text color. We need a realized widget, that's why 
1486            we get styled_widget from outside */
1487 #ifndef MODEST_HAVE_HILDON0_WIDGETS
1488         GdkColor color;
1489         gtk_style_lookup_color (styled_widget->style, "SecondaryTextColor", &color);
1490         gray_color_markup = modest_text_utils_get_color_string (&color);
1491 #else
1492         gray_color_markup = g_strdup ("#BBBBBB");
1493 #endif  
1494         return gray_color_markup;
1495 }
1496
1497 /*
1498  * Free the returned string
1499  */
1500 static gchar*
1501 create_device_name_visual_string (const gchar *device_name,
1502                                   const gchar *gray_color_markup)
1503 {
1504         gchar *tmp, *label;
1505
1506         /* We have to use "" to fill the %s of the translation. We can
1507            not just use the device name because the device name is
1508            shown in a different color, so it could not be included
1509            into the <span> tag */
1510         tmp = g_strdup_printf (_("mcen_fi_localroot_description"), "");
1511         label = g_markup_printf_escaped ("<span color='%s'>%s</span>%s", 
1512                                          gray_color_markup, 
1513                                          tmp, 
1514                                          device_name);
1515         g_free (tmp);
1516
1517         return label;
1518 }
1519
1520 static GtkWidget *
1521 create_details_widget (GtkWidget *styled_widget, TnyAccount *account)
1522 {
1523         /* TODO: Clean up this function. It's a mess, with lots of copy/paste. murrayc. */
1524         
1525         GtkWidget *vbox;
1526         GtkWidget *label_w;
1527         gchar *label;
1528         gchar *gray_color_markup;
1529
1530         vbox = gtk_vbox_new (FALSE, 0);
1531
1532         gray_color_markup = get_gray_color_markup (styled_widget);
1533
1534         /* Account description: */
1535         if (modest_tny_account_is_virtual_local_folders (account)
1536                 || (modest_tny_account_is_memory_card_account (account))) {
1537         
1538                 /* Get device name */
1539                 gchar *device_name = NULL;
1540                 if (modest_tny_account_is_virtual_local_folders (account))
1541                         device_name = modest_conf_get_string (modest_runtime_get_conf(),
1542                                                       MODEST_CONF_DEVICE_NAME, NULL);
1543                 else
1544                         device_name = g_strdup (tny_account_get_name (account));
1545
1546                 label = create_device_name_visual_string ((const gchar *) device_name, 
1547                                                           (const gchar *) gray_color_markup);
1548                 label_w = gtk_label_new (NULL);
1549                 gtk_label_set_markup (GTK_LABEL (label_w), label);
1550                 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1551                 g_free (device_name);
1552                 g_free (label);
1553         } else {
1554                 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1555                         gtk_box_pack_start (GTK_BOX (vbox), 
1556                                 gtk_label_new (tny_account_get_name (account)), 
1557                                 FALSE, FALSE, 0);
1558                 } else {
1559                         /* Other accounts, such as IMAP and POP: */
1560                         
1561                         GString *proto;
1562                         gchar *tmp;
1563         
1564                         /* Put proto in uppercase */
1565                         proto = g_string_new (tny_account_get_proto (account));
1566                         proto = g_string_ascii_up (proto);
1567                         
1568                         /* note: mcen_fi_localroot_description is something like "%s account"
1569                          * however, we should display "%s account: %s"... therefore, ugly tmp */
1570                         tmp   = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1571                         label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", 
1572                                                          gray_color_markup, tmp, tny_account_get_name (account));
1573                         g_free (tmp);
1574
1575                         label_w = gtk_label_new (NULL);
1576                         gtk_label_set_markup (GTK_LABEL (label_w), label);
1577                         gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1578                         g_string_free (proto, TRUE);
1579                         g_free (label);
1580                 }
1581         }
1582
1583         /* Message count */
1584         TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1585         label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %d", 
1586                                          gray_color_markup, _("mcen_fi_rootfolder_messages"), 
1587                                          modest_tny_folder_store_get_message_count (folder_store));
1588         label_w = gtk_label_new (NULL);
1589         gtk_label_set_markup (GTK_LABEL (label_w), label);
1590         gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1591         g_free (label);
1592
1593         /* Folder count */
1594         label = g_markup_printf_escaped ("<span color='%s'>%s</span>: %d", 
1595                                          gray_color_markup, 
1596                                          _("mcen_fi_rootfolder_folders"), 
1597                                          modest_tny_folder_store_get_folder_count (folder_store));
1598         label_w = gtk_label_new (NULL);
1599         gtk_label_set_markup (GTK_LABEL (label_w), label);
1600         gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1601         g_free (label);
1602
1603         /* Size / Date */
1604         if (modest_tny_account_is_virtual_local_folders (account)
1605                 || modest_tny_account_is_memory_card_account (account)) {
1606
1607                 gchar *size = modest_text_utils_get_display_size (
1608                         modest_tny_folder_store_get_local_size (folder_store));
1609                 
1610                 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", 
1611                                                  gray_color_markup, _("mcen_fi_rootfolder_size"),
1612                                                  size);
1613                 g_free (size);
1614                 
1615                 label_w = gtk_label_new (NULL);
1616                 gtk_label_set_markup (GTK_LABEL (label_w), label);
1617                 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1618                 g_free (label);
1619         } else if (TNY_IS_ACCOUNT(folder_store)) {
1620                 TnyAccount *account = TNY_ACCOUNT(folder_store);
1621                 
1622                 time_t last_updated;
1623                 gchar *last_updated_string;
1624                 /* Get last updated from configuration */
1625                 last_updated = modest_account_mgr_get_int (modest_runtime_get_account_mgr (), 
1626                                                           tny_account_get_id (account), 
1627                                                           MODEST_ACCOUNT_LAST_UPDATED, 
1628                                                           TRUE);
1629                 if (last_updated > 0) 
1630                         last_updated_string = modest_text_utils_get_display_date(last_updated);
1631                 else
1632                         last_updated_string = g_strdup (_("mcen_va_never"));
1633
1634                 label = g_markup_printf_escaped ("<span color='%s'>%s:</span> %s", 
1635                                                  gray_color_markup, _("mcen_ti_lastupdated"), last_updated_string);
1636                 label_w = gtk_label_new (NULL);
1637                 gtk_label_set_markup (GTK_LABEL (label_w), label);
1638                 gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0);
1639                 g_free (last_updated_string);
1640                 g_free (label);
1641         }
1642
1643         g_free (gray_color_markup);
1644
1645         /* Set alignment */
1646         gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1647
1648         return vbox;
1649 }
1650
1651 gboolean
1652 modest_main_window_send_receive_in_progress (ModestMainWindow *self)
1653 {
1654         ModestMainWindowPrivate *priv = NULL;
1655         
1656         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1657
1658         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1659
1660         return priv->send_receive_in_progress;
1661 }
1662
1663 void 
1664 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1665 {
1666         GtkAction *action = NULL;
1667         GtkWidget *widget = NULL;
1668         ModestMainWindowPrivate *priv = NULL;
1669                 
1670         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1671         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1672         
1673         priv->send_receive_in_progress  = TRUE;
1674
1675         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu"); 
1676         gtk_action_set_sensitive (action, FALSE);
1677 /*         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu"); */
1678 /*      gtk_action_set_sensitive (action, FALSE); */
1679         widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");       
1680         gtk_widget_set_sensitive (widget, FALSE);
1681
1682
1683 void 
1684 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1685 {
1686         GtkAction *action = NULL;
1687         GtkWidget *widget = NULL;
1688         ModestMainWindowPrivate *priv = NULL;
1689                 
1690         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1691         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1692
1693         priv->send_receive_in_progress  = FALSE;
1694
1695         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu"); 
1696         gtk_action_set_sensitive (action, TRUE);
1697 /*         action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu");     */
1698 /*      gtk_action_set_sensitive (action, TRUE); */
1699         widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");       
1700         gtk_widget_set_sensitive (widget, TRUE);
1701
1702
1703
1704 static void
1705 on_msg_count_changed (ModestHeaderView *header_view,
1706                       TnyFolder *folder,
1707                       TnyFolderChange *change,
1708                       ModestMainWindow *main_window)
1709 {
1710         gboolean folder_empty = FALSE;
1711         gboolean all_marked_as_deleted = FALSE;
1712         TnyFolderChangeChanged changed; 
1713         ModestMainWindowPrivate *priv;
1714         
1715         g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
1716         g_return_if_fail (TNY_IS_FOLDER(folder));
1717         g_return_if_fail (TNY_IS_FOLDER_CHANGE(change));
1718         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
1719         
1720         changed = tny_folder_change_get_changed (change);
1721         
1722         /* If something changes */
1723         if ((changed) & TNY_FOLDER_CHANGE_CHANGED_ALL_COUNT)
1724                 folder_empty = (tny_folder_change_get_new_all_count (change) == 0);
1725         else
1726                 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1727         
1728 /*      Check header removed  (hide marked as DELETED headers) */
1729         if (changed & TNY_FOLDER_CHANGE_CHANGED_EXPUNGED_HEADERS) {
1730                 modest_header_view_refilter (MODEST_HEADER_VIEW(priv->header_view));
1731         }
1732
1733         /* Check if all messages are marked to be deleted */
1734         all_marked_as_deleted = modest_header_view_is_empty (header_view);
1735         folder_empty = folder_empty || all_marked_as_deleted ;
1736         
1737         /* Set contents style of headers view */
1738         if (folder_empty)  {
1739                 modest_main_window_set_contents_style (main_window,
1740                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1741                 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1742         }
1743         else {
1744                 modest_main_window_set_contents_style (main_window,
1745                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1746         }       
1747 }
1748
1749
1750 void 
1751 modest_main_window_set_contents_style (ModestMainWindow *self, 
1752                                        ModestMainWindowContentsStyle style)
1753 {
1754         ModestMainWindowPrivate *priv;
1755
1756         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1757
1758         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1759
1760         /* We allow to set the same content style than the previously
1761            set if there are details, because it could happen when we're
1762            selecting different accounts consecutively */
1763         if ((priv->contents_style == style) &&
1764             (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1765                 return;
1766
1767         /* Remove previous child. Delete it if it was an account
1768            details widget */
1769         GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1770         if (content) {
1771                 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1772                         g_object_ref (content);
1773                 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1774                         g_object_ref (priv->empty_view);
1775                         gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1776                 }
1777                 
1778                 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1779         }
1780
1781         priv->contents_style = style;
1782
1783         switch (priv->contents_style) {
1784         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1785                 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1786                 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1787                                                       TRUE);
1788                 break;
1789         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1790         {
1791                 /* if we're started without main win, there may not be a folder
1792                  * view. this fixes a GLib-Critical */
1793                 if (priv->folder_view) {
1794                         TnyFolderStore *selected_folderstore = 
1795                                 modest_folder_view_get_selected (priv->folder_view);
1796                         if (TNY_IS_ACCOUNT (selected_folderstore)) {    
1797                                 priv->details_widget = create_details_widget (GTK_WIDGET (self),
1798                                                                 TNY_ACCOUNT (selected_folderstore));
1799                                 
1800                                 wrap_in_scrolled_window (priv->contents_widget, 
1801                                                          priv->details_widget);
1802                         }
1803                         g_object_unref (selected_folderstore);
1804                         modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1805                                                               FALSE);
1806                 }
1807                 break;
1808         }
1809         case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1810                 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1811                 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget),
1812                                                       FALSE);
1813                 break;
1814         default:
1815                 g_return_if_reached ();
1816         }
1817
1818         /* Show */
1819         gtk_widget_show_all (priv->contents_widget);
1820 }
1821
1822 ModestMainWindowContentsStyle
1823 modest_main_window_get_contents_style (ModestMainWindow *self)
1824 {
1825         ModestMainWindowPrivate *priv;
1826
1827         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
1828
1829         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1830         return priv->contents_style;
1831 }
1832
1833
1834 static void 
1835 on_configuration_key_changed (ModestConf* conf, 
1836                               const gchar *key, 
1837                               ModestConfEvent event,
1838                               ModestConfNotificationId id, 
1839                               ModestMainWindow *self)
1840 {
1841         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1842         TnyAccount *account = NULL;
1843
1844         if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
1845                 return;
1846
1847         if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1848                 return;
1849
1850         if (priv->folder_view) 
1851                 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1852
1853         if (account && TNY_IS_ACCOUNT (account) &&
1854             strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0) {
1855                 GList *children;
1856                 GtkLabel *label;
1857                 const gchar *device_name;
1858                 gchar *new_text, *gray_color_markup;
1859                 
1860                 /* Get label */
1861                 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1862                 label = GTK_LABEL (children->data);
1863                 
1864                 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1865                                                       MODEST_CONF_DEVICE_NAME, NULL);
1866
1867                 gray_color_markup = get_gray_color_markup (GTK_WIDGET (self));          
1868                 new_text = create_device_name_visual_string (device_name, gray_color_markup);
1869                 
1870                 gtk_label_set_markup (label, new_text);
1871                 gtk_widget_show (GTK_WIDGET (label));
1872                 
1873                 g_free (gray_color_markup);
1874                 g_free (new_text);
1875                 g_list_free (children);
1876         }
1877         g_object_unref (account);
1878 }
1879
1880 static gboolean
1881 set_toolbar_transfer_mode (ModestMainWindow *self)
1882 {
1883         ModestMainWindowPrivate *priv = NULL;
1884         
1885         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1886
1887         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1888
1889         set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1890         
1891         if (priv->progress_bar_timeout > 0) {
1892                 g_source_remove (priv->progress_bar_timeout);
1893                 priv->progress_bar_timeout = 0;
1894         }
1895
1896         return FALSE;
1897 }
1898
1899 static void 
1900 set_toolbar_mode (ModestMainWindow *self, 
1901                   ModestToolBarModes mode)
1902 {
1903         ModestWindowPrivate *parent_priv = NULL;
1904         ModestMainWindowPrivate *priv = NULL;
1905         GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1906         
1907         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1908
1909         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1910         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1911
1912         /* In case this was called before the toolbar exists: */
1913         if (!(parent_priv->toolbar))
1914                 return;
1915
1916         g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar)); 
1917         
1918         sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1919         refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1920         cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1921
1922         /* Sets current toolbar mode */
1923         priv->current_toolbar_mode = mode;
1924
1925         /* Checks the dimming rules */
1926         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1927
1928         /* Show and hide toolbar items */
1929         switch (mode) {
1930         case TOOLBAR_MODE_NORMAL:
1931                 if (sort_action)
1932                         gtk_action_set_visible (sort_action, TRUE);
1933                 if (refresh_action)
1934                         gtk_action_set_visible (refresh_action, TRUE);
1935                 if (priv->progress_toolitem) {
1936                         gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1937                         gtk_widget_hide (priv->progress_toolitem);
1938                 }
1939                 if (priv->progress_bar)
1940                         gtk_widget_hide (priv->progress_bar);
1941                 
1942                 if (cancel_action)
1943                         gtk_action_set_visible (cancel_action, FALSE);
1944
1945                 /* Hide toolbar if optimized view is enabled */
1946                 if (priv->optimized_view)
1947                         gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
1948                 break;
1949         case TOOLBAR_MODE_TRANSFER:
1950                 if (sort_action)
1951                         gtk_action_set_visible (sort_action, FALSE);
1952                 if (refresh_action)
1953                         gtk_action_set_visible (refresh_action, FALSE);
1954                 if (cancel_action)
1955                         gtk_action_set_visible (cancel_action, TRUE);
1956                 if (priv->progress_toolitem) {
1957                         gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1958                         gtk_widget_show (priv->progress_toolitem);
1959                 }
1960                 if (priv->progress_bar)
1961                         gtk_widget_show (priv->progress_bar);
1962
1963                 /* Show toolbar if it's hiden (optimized view ) */
1964                 if (priv->optimized_view)
1965                         gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1966                 break;
1967         default:
1968                 g_return_if_reached ();
1969         }
1970 }
1971
1972 gboolean
1973 modest_main_window_transfer_mode_enabled (ModestMainWindow *self)
1974 {
1975         ModestMainWindowPrivate *priv;
1976
1977         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1978         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1979
1980         return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
1981 }
1982
1983 static void
1984 cancel_progressbar (GtkToolButton *toolbutton,
1985                     ModestMainWindow *self)
1986 {
1987         GSList *tmp;
1988         ModestMainWindowPrivate *priv;
1989         
1990         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1991
1992         /* Get operation observers and cancel all the operations */
1993         tmp = priv->progress_widgets;
1994         while (tmp) {
1995                 modest_progress_object_cancel_all_operations (MODEST_PROGRESS_OBJECT(tmp->data));
1996                 tmp=g_slist_next(tmp);
1997         }
1998 }
1999
2000 static gboolean
2001 observers_empty (ModestMainWindow *self)
2002 {
2003         GSList *tmp = NULL;
2004         ModestMainWindowPrivate *priv;
2005         gboolean is_empty = TRUE;
2006         guint pending_ops = 0;
2007  
2008         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2009         tmp = priv->progress_widgets;
2010
2011         /* Check all observers */
2012         while (tmp && is_empty)  {
2013                 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
2014                 is_empty = pending_ops == 0;
2015                 
2016                 tmp = g_slist_next(tmp);
2017         }
2018         
2019         return is_empty;
2020 }
2021
2022 static void
2023 on_queue_changed (ModestMailOperationQueue *queue,
2024                   ModestMailOperation *mail_op,
2025                   ModestMailOperationQueueNotification type,
2026                   ModestMainWindow *self)
2027 {
2028         ModestMainWindowPrivate *priv;
2029         ModestMailOperationTypeOperation op_type;
2030         ModestToolBarModes mode;
2031         GSList *tmp;
2032         gboolean mode_changed = FALSE;
2033
2034         g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
2035         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2036                
2037         /* Get toolbar mode from operation id*/
2038         op_type = modest_mail_operation_get_type_operation (mail_op);
2039         switch (op_type) {
2040         case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
2041         case MODEST_MAIL_OPERATION_TYPE_OPEN:
2042                 mode = TOOLBAR_MODE_TRANSFER;
2043                 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
2044                         mode_changed = TRUE;
2045                 break;
2046         default:
2047                 mode = TOOLBAR_MODE_NORMAL;
2048                 
2049         }
2050                 
2051                        
2052         /* Add operation observers and change toolbar if neccessary*/
2053         tmp = priv->progress_widgets;
2054         switch (type) {
2055         case MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED:
2056                 if (mode == TOOLBAR_MODE_TRANSFER) {
2057                         if (mode_changed) {
2058                                 set_toolbar_transfer_mode(self);                    
2059                         }
2060                         while (tmp) {
2061                                 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2062                                                                       mail_op);
2063                                 tmp = g_slist_next (tmp);
2064                         }
2065                 }
2066                 break;
2067         case MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED:
2068                 /* Change toolbar mode */
2069                 if (mode == TOOLBAR_MODE_TRANSFER) {                    
2070                         while (tmp) {
2071                                 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
2072                                                                          mail_op);
2073                                 tmp = g_slist_next (tmp);
2074                         }
2075                         
2076                         /* If no more operations are being observed, NORMAL mode is enabled again */
2077                         if (observers_empty (self)) {
2078                                 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);                           
2079                         }
2080                 }
2081
2082                 break;
2083         }       
2084
2085 }
2086
2087 static void
2088 set_account_visible(ModestMainWindow *self, const gchar *acc_name)
2089 {
2090         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2091         GtkAction *action;
2092
2093         /* Get account data */
2094         ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
2095         ModestAccountData *acc_data = modest_account_mgr_get_account_data (mgr, acc_name);
2096
2097         /* Set the new visible & active account */
2098         if (acc_data && acc_data->store_account) { 
2099                 modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view,
2100                                                                              acc_data->store_account->account_name);
2101                 modest_window_set_active_account (MODEST_WINDOW (self), acc_data->account_name);
2102                 action = gtk_action_group_get_action (priv->view_additions_group, acc_data->account_name);
2103                 if (action != NULL) {
2104                         if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
2105                                 modest_maemo_toggle_action_set_active_block_notify (
2106                                         GTK_TOGGLE_ACTION (action),
2107                                         TRUE);
2108                         }
2109                 }
2110         }
2111         
2112         modest_folder_view_select_first_inbox_or_local (priv->folder_view);
2113
2114
2115         /* Free */
2116         if (acc_data)
2117                 modest_account_mgr_free_account_data (mgr, acc_data);
2118 }
2119
2120 /* Make sure that at least one account is "viewed": */
2121 static void
2122 set_at_least_one_account_visible(ModestMainWindow *self)
2123 {
2124         ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
2125         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2126
2127         if (!(priv->folder_view)) {
2128                 /* It is too early to do this. */
2129                 return; 
2130         }
2131         
2132         const gchar *active_server_account_name = 
2133                 modest_folder_view_get_account_id_of_visible_server_account (priv->folder_view);        
2134         if (!active_server_account_name ||
2135                 !modest_account_mgr_account_exists (account_mgr, active_server_account_name, TRUE))
2136         {
2137                 gchar* first_modest_name = modest_account_mgr_get_first_account_name (account_mgr);
2138                 if (first_modest_name) {
2139                         set_account_visible (self, first_modest_name);
2140                         g_free (first_modest_name);
2141                 }
2142         }
2143 }
2144
2145 static void 
2146 on_show_account_action_toggled  (GtkToggleAction *action,
2147                                    gpointer user_data)
2148 {
2149         ModestMainWindow *self = MODEST_MAIN_WINDOW (user_data);
2150
2151         const gchar *acc_name = gtk_action_get_name (GTK_ACTION (action));
2152         if (gtk_toggle_action_get_active (action))
2153                 set_account_visible (self, acc_name);
2154 }
2155
2156 static void
2157 refresh_account (const gchar *account_name)
2158 {
2159         ModestWindow *win;
2160
2161         win = MODEST_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2162
2163         /* If account_name == NULL, we must update all (option All) */
2164         if (!account_name)
2165                 modest_ui_actions_do_send_receive_all (win);
2166         else
2167                 modest_ui_actions_do_send_receive (account_name, win);
2168         
2169 }
2170
2171 static void 
2172 on_refresh_account_action_activated  (GtkAction *action,
2173                                       gpointer user_data)
2174 {
2175         refresh_account ((const gchar*) user_data);
2176 }
2177
2178 static void
2179 on_send_receive_csm_activated (GtkMenuItem *item,
2180                                gpointer user_data)
2181 {
2182         refresh_account ((const gchar*) user_data);
2183 }
2184
2185 static gboolean
2186 on_zoom_minus_plus_not_implemented (ModestWindow *window)
2187 {
2188         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE);
2189
2190         hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2191         return FALSE;
2192
2193 }
2194
2195 static gboolean
2196 on_folder_view_focus_in (GtkWidget *widget,
2197                          GdkEventFocus *event,
2198                          gpointer userdata)
2199 {
2200         ModestMainWindow *main_window = NULL;
2201         
2202         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2203         main_window = MODEST_MAIN_WINDOW (userdata);
2204         
2205         /* Update toolbar dimming state */
2206         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2207
2208         return FALSE;
2209 }
2210
2211 static gboolean
2212 on_header_view_focus_in (GtkWidget *widget,
2213                          GdkEventFocus *event,
2214                          gpointer userdata)
2215 {
2216         ModestMainWindow *main_window = NULL;
2217         ModestMainWindowPrivate *priv = NULL;
2218
2219         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (userdata), FALSE);
2220         main_window = MODEST_MAIN_WINDOW (userdata);
2221         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (main_window);
2222
2223         /* Update toolbar dimming state */
2224         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2225
2226         return FALSE;
2227 }
2228
2229 static void 
2230 modest_main_window_on_folder_selection_changed (ModestFolderView *folder_view,
2231                                                 TnyFolderStore *folder_store, 
2232                                                 gboolean selected,
2233                                                 ModestMainWindow *main_window)
2234 {
2235         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (main_window);
2236         GtkAction *action = NULL;
2237         gboolean show_reply = TRUE;
2238         gboolean show_forward = TRUE;
2239         gboolean show_cancel_send = FALSE;
2240         gboolean show_clipboard = TRUE;
2241         gboolean show_delete = TRUE;
2242
2243         if (selected) {
2244                 if (TNY_IS_ACCOUNT (folder_store)) {
2245                         show_reply = show_forward = show_cancel_send = show_clipboard = show_delete = FALSE;
2246                 } else if (TNY_IS_FOLDER (folder_store)) {
2247                         if (modest_tny_folder_is_local_folder (TNY_FOLDER (folder_store))) {
2248                                 TnyFolderType folder_type = modest_tny_folder_get_local_or_mmc_folder_type (
2249                                         TNY_FOLDER (folder_store));
2250                                 switch (folder_type) {
2251                                 case TNY_FOLDER_TYPE_DRAFTS:
2252                                         show_clipboard = show_delete = TRUE;
2253                                         show_reply = show_forward = show_cancel_send = FALSE;
2254                                         break;
2255                                 case TNY_FOLDER_TYPE_SENT:
2256                                         show_forward = show_clipboard = show_delete = TRUE;
2257                                         show_reply = show_cancel_send = FALSE;
2258                                         break;
2259                                 case TNY_FOLDER_TYPE_OUTBOX:
2260                                         show_clipboard = show_delete = show_cancel_send = TRUE;
2261                                         show_reply = show_forward = FALSE;
2262                                         break;
2263                                 default:
2264                                         show_reply = show_forward = show_clipboard = show_delete = TRUE;
2265                                         show_cancel_send = FALSE;
2266                                 }
2267                         } else {
2268                                 show_reply = show_forward = show_clipboard = show_delete = TRUE;
2269                                 show_cancel_send = FALSE;
2270                         }
2271                 }
2272         }
2273
2274         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReply");
2275         gtk_action_set_visible (action, show_reply);
2276         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMReplyAll");
2277         gtk_action_set_visible (action, show_reply);
2278         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMForward");
2279         gtk_action_set_visible (action, show_forward);
2280         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMCancelSending");
2281         gtk_action_set_visible (action, show_cancel_send);
2282         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/HeaderViewCSM/HeaderViewCSMDelete");
2283         gtk_action_set_visible (action, show_delete);
2284
2285         /* We finally call to the ui actions handler, after updating properly
2286          * the header view CSM */
2287         modest_ui_actions_on_folder_selection_changed (folder_view, folder_store, selected, main_window);
2288 }
2289
2290 gboolean 
2291 modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_window,
2292                                                    GtkTreeModel *model,
2293                                                    GtkTreeRowReference *row_reference,
2294                                                    ModestMainWindow *self)
2295 {
2296         ModestMainWindowPrivate *priv = NULL;
2297         GtkTreeModel *header_model = NULL;
2298         GtkTreePath *path = NULL;
2299
2300         g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (view_window), FALSE);
2301         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
2302         g_return_val_if_fail (gtk_tree_row_reference_valid (row_reference), FALSE);
2303
2304         priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
2305         header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->header_view));
2306
2307         /* Do nothing if we changed the folder in the main view */
2308         if (header_model != model)
2309                 return FALSE;
2310
2311         /* Select the message in the header view */
2312         path = gtk_tree_row_reference_get_path (row_reference);
2313         gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->header_view),
2314                                   path, NULL, FALSE);
2315         gtk_tree_path_free (path);
2316
2317         return TRUE;
2318 }
2319