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