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