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