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