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