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